• [技术干货] GaussDB 集群启停问题定位指南
    集群启停问题定位指南1      集群启停基本原理1.1      起停依赖关系描述及图示FIM:集群管理界面,用户可以从FIM界面上下发启动和停止集群操作; cron:系统服务,每一分钟定时查看om_monitor服务是否拉起,如果没有拉起,则拉起;om_monitor:常驻系统,用于拉起cm_agent;cm_agent:起停 cn、dn、gtm、cm_server,以及在停止时,当cn、dn、gtm、cm_server停止后,cm_agent自退出。      1.2      日志路径组件名日志路径FIM/var/log/Bigdata/mpp/scriptlog/prestart.log/var/log/Bigdata/mpp/scriptlog/start.log以上日志每个数据节点上均存在gs_om/var/log/Bigdata/mpp/omm/om/gs_om-   YYYY-MM-DD_hhmmss.log以上日志每个数据节点上均存在om_monitor/var/log/Bigdata/mpp/omm/cm/cm_agent/om_monitor-YYYY-MM-DD_hhmmss.log以上日志每个数据节点上均存在cm_agent/var/log/Bigdata/mpp/omm/cm/cm_agent/cm_agent-YYYY-MM-DD_hhmmss.log/var/log/Bigdata/mpp/omm/cm/cm_agent/system_call-YYYY-MM-DD_hhmmss.log以上日志每个数据节点上均存在cm_server/var/log/Bigdata/mpp/omm/cm/cm_agent/cm_server-YYYY-MM-DD_hhmmss.log以上日志仅在主备cm_server节点上均存在1.3      集群实例角色状态信息表实例角色状态DN   build 状态和GTM 同步状态CMSPrimary(主)Standby(备)Pending(待仲裁状态,等待仲裁为主或者备)DownCNNormal(正常)Deleteing(正在删除)Deleted(已经删除)DownDNPrimary(主)Standby(备)Dummy_standby(从备)Pending(待仲裁状态,等待仲裁为主或者备)DownNormal(正常)Starting(正在启动)Need   repair(待处理状态)Waiting   Promoting(等待升主)Promoting(备机升主中)Demoting(主机降备中)Building(备机正在build)Build   failed(备机build失败)Manual   stop(手动停止)Disk   damaged(磁盘故障)Port   used(端口占用)Unknown(状态未知)Connecting(DN主备连接)Disconnect(DN主备未连接)Walsegmen   removed(DN日志分叉) GTMPrimary(主)Standby(备)Pending(待仲裁状态,等待仲裁为主或者备)DownConnection   OK(主备连接OK)Connection   bad(主备连接有问题)Starting(正在启动)Manual   stop(手动停止)Disk   damaged(磁盘故障)Port   used(端口占用)Unknown(状态未知)Sync(同步模式)Async(非同步模式)Most   available(最大可用模式)2      启动集群常见问题分类3      集群启停问题定位方法及解决措施使用命令cm_ctl query -Cv查看集群状态,根据状态进入不同分支场景进行排查处理。3.1      整节点未启动Step1. 使用命令cm_ctl query -Cv查看集群状态信息确认整节点未启动的主机名;Step2. omm用户登录对应节点,查看om_monitor进程是否存在,如果om_monitor进程不存在,则可能原因是omm用户定时任务异常、omm用户密码超期、cgroup挂载异常,可通过分析om_monitor日志、omm用户定时任务、omm用户密码超期时间等方式进行进一步分析;Step3. 如果节点上om_monitor进程存在,cm_agent进程不存在,则可能原因是FIM界面启动命令未成功下发到后台、python版本过高或其它原因导致om_monitor未能启动cm_agent,可通过检查启停标志文件、节点上python版本、om_monitor日志等方式进一步分析。部分实例未启动,查看具体的实例问题,逐步分析。一般启动问题为DN、CN、GTM等实例启动失败,或者无法选主。这种情况,需要结合日志分析。通常有磁盘故障、端口占用、环境变量冲突等情况。3.2      节点内部分实例未启动Step1. 使用命令cm_ctl query -Cv查看集群状态信息确认未启动的实例及所在节点主机名;Step2. omm用户登录对应节点,查看cn/dn/gtm/cm_server实例进程是否存在,如果进程不存在,则可能原因是端口被占、lvs虚拟ip丢失、cn/dn的postgresql.conf配置文件的listen_address参数存在无效ip、进程listen端口号对应锁文件残留、cn/dn配置文件中存在无效GUC参数、系统信号量参数配置过小、存在多个cm_agent进程、路径无权限、磁盘满、数据目录权限异常等,需要结合日志具体分析;Step3.如果cn/dn/gtm/cm_server进程存在,但状态为down或者unknown,则可能原因是当前节点与主cm_server节点网络不通、cm_server无主、节点上存在子网卡等;Step4.如果cn/dn/gtm/cm_server进程存在,但状态为pengding,则说明可能是在做redo,可通过查看堆栈来确认。3.3      节点实例未停止Step1. 首先使用如下命令找到未正常停止的实例:gs_ssh -c 'ps -ef|grep /opt/huawei/Bigdata/mppdb/core/bin/ | grep -v grep'Step2.1 实例未被停止分为两种情况,一种是实例收到停止信号,但是无法停止,这种现象主要体现在CN、DN正在执行业务,无法停止。当CN、DN无法停止的时候,需要搜集CN、DN堆栈,用于定位问题;Step2.2 第二种是执行停止的命令异常,此时请查看cma日志,手动拆解停止的shell命令,查看那些命令异常,一般为pstree命令异常。当pstree命令等shell命令异常时,分为两种情况:1)系统不存在该命令,请安装该命令,或者查看环境变量是否正确;2)系统pstree结果不符合预期,请更新该命令版本。4      集群启停问题常见案例4.1      整节点未启动,om_monitor进程不存在问题现象:启动集群时整节点未启动,对应节点上om_monitor进程不存在定位过程:omm用户登录到到未启动的节点,使用以下命令确认om_monitor进程不存在:ps –eaf | grep om_monitor4.1.1        Om_monitor定时任务未挂载场景描述:使用如下命令查看启动om_monitor的定时任务是否挂载到cron服务上,如果未挂载上,则是安装失败或定时任务被删除。通过 crontab服务可以看到如下命令,代表om_monitor服务挂载成功。crontal -l解决方法:参照正常节点将om_monitor定时任务服务添加到omm用户的定时任务中。4.1.2        Omm用户密码超期场景描述:使用如下命令检查是否设置了omm用户密码超期时间且密码已过期,如果密码超期会导致omm用户定时任务无权限查看,进而导致无法拉起om_monitor进程。chage -l omm解决方法:使用如下命令将omm用户密码超期时间设置为永不过期chage -M 99999 omm4.2      整节点未启动,cm_agent进程不存在问题现象:整节点未启动,om_monitor进程存在,但cm_agent进程不存在定位过程:omm用户登录到未启动的节点,使用以下命令确认cm_agent进程不存在:ps –eaf | grep cm_agent4.2.1        启停标志文件存在场景描述:检查om_monitor日志中是否有如下格式的日志打印,如果有说明cgroup未挂载成功,导致CMA拉起异常can't get the *cgroup*解决方法:重新挂载cgroup。4.2.2        启停标志文件存在场景描述:检查bin目录下启停标志文件是否存在,如果存在说明FIM界面启动命令未下发到后端ll /opt/huawei/Bigdata/mppdb/core/bin/cluster_manual_start解决方法:1、  删除此文件即可从后台自动拉起该节点实例;2、  FIM界面启动命令未下发到内核原因可排查分析该节点上如下两个日志文件中的报错信息来确认/var/log/Bigdata/mpp/scriptlog/prestart.log/var/log/Bigdata/mpp/scriptlog/start.log4.2.3        Python版本过高场景描述:检查节点上python版本为3.x,与数据库默认的2.7不符,FIM界面启动时start.log日志中有如下报错,则说明是python版本过高导致启动异常解决方法:与现场人员确认是否手动升级过python版本或安装了多个版本的python,并让现场人员将节点上默认python版本恢复为2.7版本。4.2.4          环境变量文件为空场景描述:检查/opt/huawei/Bigdata/mppdb/.mppdbgs_profile环境变量文件为空,则说明环境变量文件为空导致FIM界面启动命令未下发到内核         解决方法:从正常节点拷贝一份过来即可。4.2.5        启停标志文件不存在场景描述:检查bin目录下启停标志文件不存在,说明是其它原因导致om_monitor未能启动cm_agent解决方法:收集节点上om_monitor和cm_agent日志进一步分析。4.3      节点内部分实例未启动,cn/dn/gtm/cm_server进程不存在问题现象:节点内部分实例未启动,未启动的cn/dn/gtm/cm_server实例进程不存在定位过程:omm用户登录到实例未启动的节点,使用以下命令确认相应实例进程不存在:ps –eaf | grep gaussdbps –eaf | grep gs_gtmps –eaf | grep cm_server4.3.1        信号量不足导致cn/dn启动异常场景描述: 检查对应cn/dn实例的pg_log日志,如果有如下报错,则说明是信号量不足导致cn/dn启动异常解决方法:1、  使用root用户执行如下命令可以将节点上os参数配置为预期值;/opt/huawei/Bigdata/mppdb/wisequery/script/gs_checkos -i B1 --detail2、建议使用巡检工具对集群进行全面巡检和整改。4.3.2        postgresql.conf配置文件存在无效GUC参数场景描述:检查对应节点上cm_agent和systemcall日志中如果有如下报错,则说明cn/dn的postgresql.conf配置文件中存在无效参数配置/var/log/Bigdata/mpp/omm/cm/cm_agent/cm_agent-YYYY-MM-DD_hhmmss-current.log/var/log/Bigdata/mpp/omm/cm/cm_agent/system_call-YYYY-MM-DD_hhmmss-current.log解决方法:删除postgresql.conf配置文件中无效参数即可。4.3.3        端口号被占场景描述:检查对应节点上cm_agent和systemcall日志中如果有如下报错,则说明cn/dn/cm_server/gtm的端口号被占/var/log/Bigdata/mpp/omm/cm/cm_agent/cm_agent-YYYY-MM-DD_hhmmss-current.log/var/log/Bigdata/mpp/omm/cm/cm_agent/system_call-YYYY-MM-DD_hhmmss-current.log Port 25308 is used, run 'netstat -anop|grep 25308' or 'lsof -i:25308'(need root) to see who is using this port.解决方法:1、  使用如下命令找到占用端口的进程netstat -anop|grep portlsof -i:port (root执行)2、  kill -9清理掉占用端口的进程,然后重新启动。4.3.4        Lvs虚拟ip未挂载场景描述:cn的listen_addresses参数中配置了lvs虚拟ip,但cn节点上lvs虚拟ip未正常挂载,则也会导致cn启动不了检查cn实例listen_addresses配置命令:cat /srv/BigData/mppdb/data1/coordinator/postgresql.conf|grep listen_addresses查看节点上ip信息命令:/sbin/ifconfig解决方法:使用如下命令重新挂载lvs虚拟ipsh /etc/init.d/gs_vip start4.3.5          进程listen端口号锁文件残留场景描述:机器异常掉电重启等情况下可能会导致进程listen端口号锁文件残留,这样当重新启动时会因锁文件已存在而无法启动。检查锁文件命令:ls -la  /opt/huawei/Bigdata/mppdb/mppdb_tmp检查查出来的锁文件产生时间是否是在启动时间之前,如果是则说明是之前残留的。解决方法:将残留的锁文件删除。4.3.6        Cn/dn的listen_addresses中存在无效ip场景描述:cn/dn的postgresql.conf配置文件的listen_addresses参数存在无效ip时会导致cn/dn无法正常启动,system_call日志中会有如下报错:FATAL:  could not create listen socket for "100.185.180.62"/var/log/Bigdata/mpp/omm/cm/cm_agent/system_call-YYYY-MM-DD_hhmmss-current.log检查cn实例listen_addresses配置命令:cat /srv/BigData/mppdb/data1/coordinator/postgresql.conf|grep listen_addresses解决方法:将listen_addresses参数中的无效ip删除。4.3.7        数据目录无权限场景描述:cn/dn/gtm/cm_server的数据目录权限预期是700,当权限不足时cm_agent日志中会有如下报错:data path disc writable test failed, /srv/BigData/mppdb/data3/slave1解决方法:根据报错提示修复cn/dn/gtm/cm_server数据目录的权限。4.3.8        磁盘满场景描述:节点上数据盘、日志盘等满均会导致cn/dn/gtm/cm_server进程启动异常。磁盘使用率检查命令:df -lh解决方法:清理释放磁盘空间,消除磁盘满。4.4      节点内部分实例未启动,查看状态CN、DN、GTM实例状态为down或者unknown启动集群失败,后台查看集群状态,发现CN、DN、GTM实例显示down或者unknown。4.4.1        当前节点与主cm_server节点网络不通场景描述:当节点与主cm_server节点网络不通时,当前节点cm_agent无法将实例状态上报给cm_server,导致实例状态显示为down或unknown。检查当前节点与主cm_server节点网络命令:在当前节点上ping 主cm_server节点ip,如果不能ping通则说明网络异常。解决方法:联系网络侧人员解决网络问题。4.4.2        Cm_server无主场景描述:当集群中两个cm_server实例均为pending状态,没有选出主时,无法对DN状态进行仲裁,导致DN状态均显示为down或unknown。检查当前集群cm_server状态命令:cm_ctl query -vCd|grep cm_server 解决方法:收集主备cm_server日志并联系研发人员处理。4.4.3        节点上存在多个om_monitor进程场景描述:当节点上存在多个om_monitor进程时,会导致cm_agent进程反复被杀,无法持续向cm_server上报实例状态,进而导致节点上实例状态显示为down或unknown。检查当前节点om_monitor个数命令:ps -ef|grep om_monitor|grep -v grep 解决方法:kill掉当前所有om_monitor进程待起自动重新拉起。 
  • [技术干货] 解密TaurusDB存储端高并发之线程池
    1. TaurusDB背景随着云计算进入2.0时代,数据急剧膨胀,这对实现数据库的高可靠、高性能、高吞吐的目标产生了巨大的挑战。如图1 所示,TaurusDB是华为自研的最新一代企业级具备横向扩展、海量存储能力的分布式数据库,其采用了计算存储分离,一写多读的分布式架构。将原本计算层的高密度存储相关压力下沉到存储层,极大地释放了计算层的算力。但同时将原来的存储IO转移到了网络IO,这也就是意味着,存储层将面临来自计算层风暴级的压力。如果存储层不能快速响应计算层的读写请求,会极大影响用户的使用体验。图1 TaurusDB整体架构图2 slice功能组件从图2可知,TaurusDB的存储层,不单单只做存储相关的工作,也需要大量的算力,比如consolidation生成特定数据页、compation回收旧版本数据、BufferPool缓存热点数据页等任务。为了能加快这些任务的高效执行,我们首先能想到的就是能够并行执行这些任务,也就是采用多线程技术处理的方式,增加处理器单元的吞吐能力,从而提高存储端的执行效率。2.线程池化设计思想2.1线程为什么需要池化首先,线程是稀缺的资源,如果频繁创建和销毁线程的开销是可观的,所占用的时间可能多于实际任务的执行;且当需要执行任务时,都去创建一个对应的线程去处理,那么服务器的资源(比如地址空间和内核参数)很快就会被耗尽,导致而导致OOM问题。其次,通过事先创建好一定数量的线程并置于公共池之中,这样当有任务需要执行时,只需从公共池取一个线程执行当前的任务即可,待任务结束后,此线程又可以执行其他任务或处于休眠状态,等待下一次被调度,达到线程资源重复使用的目的。2.2线程池如何管理为了能有效的管理多线程,TaurusDB存储端采用了如图3的线程池模型。图3 线程池模型ThreadPool: ThreadPool: 主要负责控制线程池的大小、状态变更、线程的创建、销毁、调度策略的选取;Scheduler:负责具体任务的接收、被调度的顺序,并触发任务的执行;Worker:负责具体任务的执行;Monitor:负责监控线程执行任务时是否出现异常,以及异常告警,比如线程执行一次任务长时间执行未能结束。2.3 线程池的调度策略当前TaurusDB存储端线程池支持三种策略:先进先出调度(FifoScheduler)、定时调度(TimeScheduler)、基于容量调度(CapacityScheduler)。对于FifoScheduler和TimeScheduler,比较容易理解。当有任务需要执行时,只需将此任务存放在一个队列即可,有scheduler按照顺序逐一调度即可。对于CapacityScheduler,是一种基于事先为某一类型的任务预留可执行线程的思想,其预留的线程个数由下发任务的用户指定。具体调度过程见图4。图4 CapacityScheduler调度比如:初始化线程大小为10,TaskType1预留线程数4,TaskType2:预留线程数5,TaskTypeN:预留线程数4当线程池处于如图4状态时,任务类型是1和3的尚未达到预留值,任务类型N已达到阈值。此时如果Threadpool中处于idle的线程数为1,则该线程将会被调度到任务类型为2的队列中。 2.4 任务异常监控告警我们知道,一旦任务被调度的线程执行过程中,可能会出现异常情况,比如线程死锁,导致该任务不能按照预期推进,轻者引发系统出现CPU、IO等系统资源使用率飚高的情况,严重者会导致系统down情形。比如TaurusDB的存储端,执行log的checkpoint的线程出现长时间卡顿,会导致存储端旧的log不能正常回收,导致磁盘空间逐步膨胀,进而影响存储端其他各个模块平滑的推进。如果能够识别出处于异常状态的线程,并能够进行告警,基于事先自定义规则进行修复,将能够持续保证存储端业务的连续性。线程池Monitor组件就是用于识别处于异常状态的线程,其基本思想就是,定期巡检线程池中的各线程处于状态,如果发现线程状态长时间未更新,则判定该线程处于异常状态,上报告警,并基于相应的处理规则处理。3. 下一步演进方向从2.3中可以看出,CapacityScheduler策略是基于实际在执行的线程数,作为idle线程线程被调度的依据,尚未衡量实时任务的重要程度。考虑这样一种场景,如果有两种类型的任务A、B,在某一时间,用于执行A、B任务的线程数恰好线程或差值极小,但B类型任务的优先级大于A任务,这时可能出现idle线程被调度执行A类型任务,B类型任务不能分配到充足的线程数(预留值是静态分配),用于加快推进任务的处理。考虑的方案:1.  限制类型任务类型队列的长度,这样可以均衡各类型任务的调度,不至于某一类或几类任务数过多;2.  在系统资源有限的前提下,支持动态伸缩线程池大小的功能,这样可以在工作负载过重时,扩充线程池大小,用于调度到急需执行的任务;3. 进一步细化CapacityScheduler策略,采用任务的重要程度和实际执行的线程数的规则,作为idle线程被调度的依据。
  • [Atlas300] 如何退出device端的死循环
    看到《Atlas小百科》里面写到的Device侧守护进程问题:创建Graph时,Device侧会起一个服务进程,如果Host进程异常退出,Device侧的进程能自动销毁吗?是否有心跳检测机制?说明:Device 侧始终有一个 MatrixDaemon 守护进程,在Device侧运行,它是每个Graph进程的父进程,负责启动Graph子进程和回收Graph资源。MatrixDaemon接收Host侧发送过来的建链请求,创建链接并创建一个同名的MatrixDaemon子进程,子进程会不断从HDC接收消息,只要接收失败(或断链)就会退出。此时如果Host不重新发起建链请求则Device侧就不会创建子进程。另外,如果Device端程序有死循环,则不会退出。请问如何退出死循环?
  • [Atlas300] host侧进程已退出,请教kill掉device侧进程的方法
    host侧程序已经退出,但devcie侧代码进入死锁,一直退不出来,/var/dlog/下还一直在打device侧的重复日志。。。已无有用信息请教kill掉device侧进程的方法[ERROR] HIAIENGINE:2020-05-26-15:17:10.688.566 device create dir result,[hiaiengine/connector/host/../common/src/graph_impl.cpp:4929:UpdateDeviceCreateDirResult], Msg: directory already used in another file failed[ERROR] HIAIENGINE:2020-05-26-15:17:10.688.804 createDirResult_ failed,[hiaiengine/connector/host/../common/src/graph_impl.cpp:2485:SendCreateDirMsg], Msg: directory already used in another file failed[ERROR] HIAIENGINE:2020-05-26-15:17:10.688.941 SendCreateDirMsg failed,[hiaiengine/connector/host/../common/src/graph_impl.cpp:2230:HdcSendFile], Msg: directory already used in another file failed[ERROR] APP:2020-05-26-15:17:10.689.127 Fail to start graph. ret = 3,[main.cpp:90:main], Msg: app log level: error
  • [技术干货] 关于UOS虚拟机命令行删除flameshot等软件过程说明
     关于UOS虚拟机命令行删除flameshot软件过程说明一、系统条件1、  UOS虚拟机配置:2、  Linux系统为Debian:二、在uos终端中使用命令行安装和卸载flameshot(一款截图软件)1、安装最新版本:flameshot 0.6.0-11# apt install flameshot安装结束后,任务栏出现flameshot菜单图标:,点击图标,打开软件,此时任务栏出现软件的托盘图标:,点击该图标可开始截图。2、  不退出该软件,卸载该软件,使用命令:# sudo apt autoremove flameshot,卸载完成后,发现任务栏图标消失了,但是托盘图标还在,并且点击还能正常使用该软件功能。这时候会给人错觉以为没有卸载成功(实际已经卸载成功了:使用dpkg –l flameshot显示找不到该软件包)。3、  查看软件进程发现它确实还在运行:# ps –ef | grep flameshot杀死该进程:# kill -9 23270,托盘图标消失。   相关解释:这是linux上的一个删除机制,linux可以删除正在运行的软件,删除后,它还会运行在linux内存中,此时需要关掉或者杀死该进程后软件才能完整删除。最直接的方式就是先退出软件(或者杀死进程),再使用卸载命令删除软件就可以了,同时所有的软件相关图标全部被删除。
  • [调优工具] java线程gc监控曲线显示断线//转OLC客户试用问题
    当鼠标放上去以后,出现断线了,这个还是不太友好看看怎么优化一下。
  • [前沿分享] 【量子计算】Cloud IDE使用小技巧
    1.       进入到自己的Cloud IDE实例,打开Terminal。可以看到系统以及默认导入了HiQ的一部分样例代码2.       可以创建一个自己的开发目录3.       在指定目录下新建一个文件,也可以从外部直接导入文件,比如我们可以导入华为-上海大学量子编程比赛第一题的题目4.       把程序导入之后,我们可以尝试用终端指令直接运行程序,当然,Cloud IDE的Debug功能也是非常实用的5.       Cloud IDE的本质是一个容器,我们可以查看我们自己的容器的配置信息,我们可以看到HiQ团队为大家提供的免费实例的配置是64核的,甚至可以执行中等规模的一些并行测试6.       对于Cloud IDE中已有的一些源,我们可以直接使用pip指令进行安装7.       接下来我们测试一下用例程序运行的时间,可以看到第一次实例运行的时间为0.97s。但是这里要为大家提供一个特别的使用技巧,那就是加上线程配置。需要知道的是,并不是线程数量配置的越多,速度就越快。可以看到我们将OMP_NUM_THREADS这个参数配置为1时,运行速度大大提升。在运行不同程序的时候,可以手动修改这个配置。同时需要注意的是,这个参数的配置只在本次登录中生效8.       最后,附上HiQ团队的祝福,希望大家答题愉快,拿奖品更愉快!
  • [问题求助] LiteOS移植到GD32F303,启动后任务调度一次就挂了?
    在GD32F303CGT6上移植LiteOS,使用KEIL开发环境移植的系统已经正常运行。目前在往ubuntu18.04LTS上使用gcc环境,源码和keil工程一样,只更换了启动文件和链接脚本文件。进入 LOS_Start(); 任务只能切换一次,就失败了,LOS_Start();未能正常执行完,有没有人提供下排查思路?
  • [技术干货] Taurus2.0垃圾回收Compactor优化方案
    1.   简介TaurusDB是一种基于MySQL的计算与存储分离架构的云原生数据库,一个集群中包含多个存储几点,每个存储节点包含多块磁盘,每块磁盘对应一个或者多个slicestore的内存逻辑结构来管理. 在taurus的slicestore中将数据划为多个slice进行管理,每个slice的大小是10G,Taurus架构图如下:TauruDB的存储层支持append-only写和随机读,最小数据存储逻辑单元为plog,每个slice中包含多个plog,默认每个plog的大小为64M。slice中的plog主要用来存放page。Plog中存放中不同版本的page,有些老page已经过期,需要删除;有些page是新page,需要被保留下来。Compator主要用来清理plog中过期的page,把一个plog上所有没有过期的page搬移到一个新plog,老的plog删除掉。Compactor的任务需要频繁访问内存中索引结构和读写plog中的page页,这两部分都属于整个系统中关键资源,锁竞争的压力比较大,会直接影响性能,所以compactor的优化方案主要围绕减少内存访问和磁盘IO,需要考虑以下几个点:A、 选取的清理的plog集最优问题,每次回收需要搬运有效page,搬运的有效page数越少,磁盘IO就越小。如何每次调度都选取到垃圾量最大的一批plog;B、 垃圾量是否分布均匀,如何让垃圾集中到一起,回收垃圾集中的plog,提高回收效率;C、 回收周期是固定的,怎么样保证在每个周期内,都能取到最优plog集;2.   关键点1-全局调度全局调度的方案增大plog垃圾量的排序范围,从slice的范围增大到slicestore的范围。因为考虑到后面需要针对单个磁盘进行“加速回收”,所以不扩大到一个存储节点的全局范围。全局调度方案按照slicestore来选取回收plog,先遍历所有的slicestore,然后在slicestore内部进行垃圾量排序,选取最多的若干个plog进行回收;优点:有效避免一个slicestore中由于垃圾分布不均匀引起的plog的无效搬运,减少对plog的读写产生的IO;缺点:排序范围增大后,排序算法会增加CPU的消耗;3.   关键点2-排序算法优化原始方案中在slice内部对plog按照垃圾量排序采用C++标准库排序(std::sort),该算法内部基于快速排序、插入排序和堆排序实现。原始方案中每个slice中最多存有160个plog,小数据量的排序或许效率影响不大,但是一个slicestore中存储成百上千的slice,排序算法的效率问题就值得关注。Taurus设计了一种topN算法,能够提升该场景下的效率。假设需要在n个元素中选取m个最大的元素,两种算法的时间复杂度和空间复杂度:C++标准库排序时间复杂度为O(nlogn),空间复杂度为O(nlogn);topN算法排序时间复杂度为O(nlogm),空间复杂度为O(1);Compactor应用场景中,n和m相差几个数量级,topN算法在时间和空间上都更具优势。         优点:减少时间复杂度和空间复杂度;4.   关键点3-调度数优化公共线程池分配给compactor的线程数是固定的,每个周期调度器生成一次任务。原始方案中compactor的每次生成的任务数由slice个数决定,会导致任务队列中的任务数过多或者过少。过多的话会失去时效性,也就是说plog的垃圾量会随着时间改变,如果在队列个等待执行的时间太长,可能就不是当前最高垃圾量的plog,同时一次挑选的plog个数太多,会增加算法的时间和空间复杂度;过少的话,compactor线程没有跑满,会导致垃圾回收速度降低。调度数优化也是基于全局调度优化,调度策略只需要保证在一个调度周期内,任务队列中任务数刚好满足compactor线程执行。假设有8个slicestore,分配了24个执行线程,每个线程每个调度周期完成一个plog的回收,则每个调度周期每个slicestore只需要生成3个任务。调度数优化即记录公共线程池中正在执行和准备执行的任务数,跟据记录决定本轮调度生成多少个回收任务,从而保证执行线程刚好够用,且不多不少。优点:保证垃圾回收速度,最优回收的plog集,有效的减少page的搬运量。5.   关键点4-冷热分区优化在数据库系统中,数据的更新并不是相同频率,一些数据页更新或者写入会更加频繁(例如系统页),这部分页面被称作热页,另外一些更新不频繁的称作冷页。如果把冷页和热页混合放到一起,就会导致更高的写放大。举个简单的例子,假设有100个热页和10个冷页,冷页基本不更新但是每次垃圾回收,都需要重复把冷页搬运一次。如果把冷页单独写入一个plog,那么在垃圾回收阶段,就可以减少重复搬运这部分冷页,达到减少IO放大的效果。         优点:提高垃圾回收的效率和速度。         缺点:需要额外的内存记录热度信息。6.   关键点5-磁盘逃生优化为了后台线程比如备份、快照、垃圾回收、页面回放等线程有足够的磁盘空间运行,在磁盘容量使用到达一定阈值,会置Full标志位,同时停止前台IO。在极端情况下,磁盘使用到阈值前台IO会出现断崖式下跌为零:为了避免在磁盘容量达到一定阈值之后前台IO完全停止,在磁盘使用率未达到阈值时,就应该有相应的处理机制。比如说在磁盘使用率未达阈值时,增加如下处理:A、 降低前台IO,减少磁盘的压力;B、 加速垃圾回收,也就是TaurusDB中的compactor机制;A点不涉及compactor的功能,所以本文先不涉及,下面主要介绍加速机制。6.1 修改写IO优先级Compactor作为后台线程,考虑到整个系统的效率,正常运行时plog写IO优先级默认为low。在加速回收阶段,plog的IO需要修改为high。6.2 提高执行速度前文可知,公共线程池为compactor分配固定数目执行线程,而且运行过程中只支持扩容不支持恢复。如果压缩其他后台任务的执行线程,对整个系统的影响太大,量也不易控制。所以不考虑。考虑到过程中不能扩容,那就初始化就扩容,通过控制调度任务数控制任务执行速度。例如,假设compactor的运行线程在正常场景下为4个,加速状态下需要增加到8个。可以在公共线程池中先分配8个线程,在正常场景下,控制任务队列为4个,另外4个线程处于wait状态,只会占用文件句柄,并不影响CPU。而在加速状态下,控制任务队列中的任务数为8,就可以实现上述的加速逻辑。6.3 总结提升写IO的优先级能够加速page的搬运,提升垃圾回收速度。通过控制调度任务数控制任务执行速度却很难控制很精准,上下会有一定的小波动。7.   总结以上1-4个方案能有效的减少page的搬运数,达到减少IO的目的。方案5能够处理磁盘容量紧急情况。目前本地测试,在500G的小数据集情况下,IO放大能减少到原来的1/6。系统资源占用减少到原来的1/3。
  • Cassandra copy命令使用指南
    copy是cqlsh中的逻辑导入导出命令。包括两个命令COPY TO / COPY FROM.使用这组命令可以在Cassandra与其他RDBMS或Cassandra之间迁移数据。目前已经支持csv, json文件格式以及标准输出和输入。 1. 如何执行copy?    1. 执行copy时,首先要启动cqlsh. 启动cqlsh的方法见 如何使用cqlsh访问Cassandra。启动cqlsh后,接着执行copy命令。如下./cqlsh 127.0.0.1 9042 -u {user_name} -p {password}COPY cycling.cyclist_name TO '/home/cas/copydata';2. 如果数据量很大,可以放在后台执行。使用cqlsh的-e 参数。-e 参数用来后台执行给定的语句,然后退出。命令如下./cqlsh 127.0.0.1 9042 -u {user_name} -p {password} -e "COPY cycling.cyclist_name TO '/home/cas/copydata'";2. COPY TO   ./cqlsh 127.0.0.1 9042 -e "COPY cycling.cyclist_name to '/home/cas/copydata'"COPY TO 常见的参数有: NUMPROCESSES, RATEFILE, PAGESIZE, BEGINTOKEN, ENDTOKEN, MAXATTEMPTS, MAXOUTPUTSIZE; 新增的参数有: RESULTFILE, DATAFORMATS, WHERECONDITION.重点介绍常见和新增的参数,关于其他COPY TO的参数可以参考Cassandra官网文档: copy-to1. `file name` 导出时,可以指定文件名称为目录, 也可以指定文件名称为文件。默认导出到文件。如果指定导出文件为存在的目录时,将会按照range范围导出到目录下的不同的文件中,如果某一个range范围导出没有数据,则不会生成文件。如果指定的文件名是文件,那将会导出到指定的文件中。如果文件不存在,则新创建该文件。./cqlsh 127.0.0.1 9042 -e "COPY cycling.cyclist_name to '/home/cas/copydata'"./cqlsh 127.0.0.1 9042 -e "COPY cycling.cyclist_name to '/home/cas/copydata/cycling.cyclist_name'"2. `NUMPROCESSES` 导出的线程数。在导出时,会将range范围进行细分。导出的线程数越多,细分range的范围数也就越多。但当线程数太多的时候,容易对服务端造成压力,造成导出失败。所以要选择一个合适的线程数进行导出,默认的线程个数是(CPU核数 - 1)3.  `RATEFILE` 速率文件。指定文件路径后,会打印导出过程的瞬时速率,可以用来评价导出的性能。4.  `PAGESIZE` 在一次page查询中。获取的row数。 默认为 1000。 建议不要设的调小。设置太小会影响导出性能。5.  `BEGINTOKEN, ENDTOKEN` 执行要导出的range范围。默认是全部数据导出。6.  `MAXATTEMPTS` 每一个查询重试的次数。如果某次查询达到最大重试次数,那么导出将会直接失败。 7.  `MAXOUTPUTSIZE` 每一个导出文件中的最大的行数。如果导出数据大于这个值。将会轮转生成另一个文件。默认是不限制的。./cqlsh 127.0.0.1 9042 -e "COPY cycling.cyclist_name to '/home/cas/copydata/cycling.cyclist_name' with MAXOUTPUTSIZE=1"8.  `RESULTFILE` 导出结果文件路径,如果不设置。默认生成在当前执行目录下。如果执行目录中存在之前的结果文件,将会重命名之前的结果文件。导出结果的内容主要包括:导出成功与否,总共导出的行数和速率,导出的range范围数,以及成功失败的range范围数,并展示每一个range范围的结果和导出的行数。9. `DATAFORMATS` 导出的数据格式。取值为csv, json。默认为csv格式。指定为json时,导出为json格式的数据。10. `WHERECONDITION` 导出的查询条件。支持查询条件的导出。对于非主键列,如果通过索引来查询,提高导出性能。         1. wherecondition 格式如下 `[key(operators)value,key(operators)value...]`        2. operators 支持 `[">=", "<=", ">", "<", "="]`,例如: `'keyspace_name=system,table_name>=local'`        3. 如果value中包含有特殊字符,比如保留字符 【" ,><=’】, 那么需要给字符加上双引号,例如:`'keyspace_name=system,table_name>="loc>=al"'`一个完整的COPY TO例子:nohup ./cqlsh 127.0.0.1 9042 --request-timeout=3600 --debug -e "COPY nihao.sz_user to '/home/cas/copydata' with WHERECONDITION='update_timestamp=1' NUMPROCESSES=12 AND RATEFILE='rate.txt' AND RESULTFILE='export_result' AND dataformats='json';"  >export.log 2>&1 &3. COPY FROM   COPY <table name> [(<column>, ...)] FROM <file name> WITH <copy option> [AND <copy option> ...]COPY FROM 常见的参数有: NUMPROCESSES, MAXROWS, INGESTRATE, ERRFILE, MAXBATCHSIZE, MINBATCHSIZE, CHUNKSIZE, MAXPARSEERRORS, MAXINSERTERRORS, SKIPROWS, SKIPCOLS;新增的参数有: DATAFORMATS.重点介绍常见和新增的参数,关于其他COPY FROM参数可以参考Cassandra官网文档: copy-from1. `file name` 导入数据时,指定导入的文件路径,可以是一个目录,或者是一个文件,或者是逗号分隔的文件名列表。如果是目录,则导入该目录下的所有文件。2. `NUMPROCESSES` 导入的线程数3. `MAXROWS` 导入的最大行数。默认不限制。4. `INGESTRATE` 每一秒导入的最大行数。默认为 1000005. `ERRFILE` 导入失败的列将放在这个文件中。6. `MAXBATCHSIZE` 每一次batch导入的最大行数。默认为207. `MINBATCHSIZE` 每一次batch导入的最小行数。默认为28. `CHUNKSIZE` 导入主线程给子线程每次传递的行数,默认为 10009. `MAXPARSEERRORS` 可以忽略的语法解析错误的最大行数。默认不限制10. `MAXINSERTERRORS` 可以忽略的插入失败的最大行数。默认为100011. `SKIPROWS` 导入时初始跳过的行数。默认为0,不跳过12. `SKIPCOLS` 导入时忽略的列名,以逗号分隔。默认不忽略。13. `DATAFORMATS` 导入的数据格式。取值为csv,json。默认为csv格式。数据为json格式时,必须指定为json。一个完整的COPY FROM例子:nohup ./cqlsh 127.0.0.1 9042 --request-timeout=3600 --debug -e "COPY nihao.sz_user FROM '/home/cas/copydata' with NUMPROCESSES=12 AND RATEFILE='rate.txt' AND dataformats='json';"  >import.log 2>&1 &
  • [技术干货] 高并发场景下MariaDB(10.3.9)的性能优化
     1 问题背景测试场景:虚拟机上部署MariaDB,远端压力服务器上部署sysbench。通过使用sysbench对MariaDB进行1比1混合读写操作,测试分为8/16/32/64/128/256/512线程。服务上虚拟出两台4C24G虚拟机,虚拟化平台为KVM,两台虚拟机位于不同的片上,两个虚拟机使用不同网卡,Sysbench部署在一台远端服务器上,通过网线直连服务器上两块网卡。测试连线图如下  软件栈:软件名功能Qemu+kvm虚拟化Sysbench   0.5可以用来进行CPU、内存、磁盘I/O、线程、数据库的性能测试MariaDB 10.3.9数据库硬件配置:服务器型号TaiShan2280 V2                                          CPU配置鲲鹏920   48core内存配置12*32GB网卡配置Hisi1822   4*25GE硬盘配置480GB   SSD *2操作系统Centos   7.6部署情况使用系统自带KVM进行虚拟化部署   2 原因分析 从64线程开始,MariaDB读写性能开始出现下降,在512线程时,性能出现坍塌。MVCC是MariaDB为了提升高并发下只读性能引入的,其实现为在事务第一次查询到数据会建立一个快照,并**存储在一个readview链表中。当查找的数据被写等操作锁住无法查询时,会先使用快照数据;当事务写操作执行失败需要undo时,也需要从readview链表获取undo相关信息。但是MariaDB为了保证readview链表的一致性,引入了一个全局锁,事务越多,链表越庞大,链表遍历是越长,占用锁时间越长,另外当读写混合时,并发线程数越多,锁竞争也更加激烈,线程无法获取到锁时,线程会自旋等待,消耗大量cpu资源,性能下降。 3 解决方案在存在全局锁的场景下,并非线程约多性能越好。当innodb_thread_concurrency != 0,则表示有并发数限制,当一个新的请求发起时,innodb会检查当前并发线程数是否达到了 innodb_thread_concurrency的限制值,如果超过阈值,则需要sleep一段时间(sleep的设置详见下一部分),然后再次请求。但此参数系统模式配置为0,即不限制并发数。在此情况下,线程获取不到锁便会自旋等待,大量消耗cpu时间片。在此测试用例下innodb_thread_concurrency=64性能最优,提升幅度最大,并且可以避免512线程下出现性能坍塌。 4 总结高并发场景下,若线程间存在原子争抢,并非线程数越多越好,过多的线程只会让更多的CPU时间片消耗在原子操作争抢中。【来自转载】 
  • [调优工具] 创建“系统资源调度分析任务”Profile System后的结果可以增加“进程/线程调度”状态过滤吗
    创建任务页面:针对“进程/线程调度”中几种状态“Wait_Blocked”、“Wait_For_CPU”和“Running”可以支持过滤吗:
  • [技术干货] 轻松读懂MySQL主从复制演进过程
    (1)前言        今天来和大家聊聊MySQL的复制演进过程,熟悉MySQL的同学应该都知道什么是MySQL复制mysql,关于这块知识网络上也有各种材料,笔者查找过很多资料,发现很多材料都描述得不够全面,光看单篇文章难以建立整体概念,因此梳理了一版浅显全面的文章出来,帮助大家轻松读懂MySQL复制演进过程。        言归正传,一直以来,MySQL的主从复制都常常被大家诟病,总结原因有以下几点:        1. 主从复制速度问题(这是最主要的)        mysql采取的复制方式是,主机执行提交之后将语句记录进binlog,备机启动一个IO线程从主传输binlog到本地,进入本地的relaylog;然后备机会另外启动一个SQL线程负责顺序执行relaylog中的语句,对语句在备机上重做,所以说这是一个异步的拷贝过程。这样会导致一个问题,就是备机数据大部分情况下会延后。主机对本地磁盘的IO、备机从主机传输的网络IO、备机本地的磁盘IO、最后备机重放数据的IO,经过了四个过程,即使服务器和网络配置都很快,理论上也一定是有延迟的;如果服务器和网络配置有瓶颈,这个延迟就会扩大化到影响业务的程度,最直接的就是读写分离的情况下,导致前端写入操作明明已经返回完成了,后端读数据时却显示没有完成。        2. 主机宕机切换后脏数据问题        mysql的主备目的之一,就是在主宕机的情况下,能及时切换到备机继续提供服务,不至于整个系统挂掉,即故障转移。但就是因为主从复制要经过复制这一消耗IO的步骤,主在挂掉的一瞬间,一般主备机都会有一定量的数据区别,这些在主机执行完毕了但还未传输到备机上的数据,就是所谓的脏数据。这样的脏数据,同样会导致前后不一致,如果服务器和网络配置不高,本来同步复制就慢的情况下,会导致极大的差别。                2009年oracle公司收购了sun,对mysql进行升级换代之后,有了巨大的改进,在5.5、5.6、5.7版本都针对主从有升级改造,在目前的5.7版本达到了非常高的可用性,配合最新的HA中间件mysql fabric,可以达到以前的几倍的稳定性。下面来详细讲一讲这三个版本中,oracle都对主从具体做了什么改进。(2)MySQL5.5版本        1. 5.5版本添加了一个semi-sync replication(半同步复制)的插件,这个插件就是为了优化同步复制的脏数据问题而生的。        2. 半同步复制在提交过程中增加了一个延迟,在提交事务后,只有在备库收到了该事务的binlog时才会给客户端进行查询结束的反馈。这会给客户端查询体验增加一些延迟,不过问题不大,因为相对于写入硬盘的时间,通过网络传输些日志的时延不算什么。重要的是,半同步复制不会阻塞事务的提交,而是阻塞在给客户端的反馈;当备库一直没有回应已收到事件,主库会超时并转化成正常的异步复制模式。        3. 顺带提一下半同步复制简单原理:在传输binlog时,要求备机返回ack证明自己拿到了数据,在至少一个备机返回ack后,主机才将数据修改提交到本地,这样能保证至少一个备机和主机是完全一致的。        4. 再举个例吧:当在主机上持续不断insert数据时,始终有一部分数据处在传输到备机的过程中,这部分数据在主机上已经是执行成功的状态,但因为还没传输完成收到任何一台备机的回应,所以尚未持久化。这个瞬间主机宕机了,数据传输不完,备机的回应也收不到了,主机重启后,主机上的这部分数据因为没有收到回应进行持久化,所以消失了。而备机上的这部分数据因为尚未接收完全,也不能作为一个relaylog提交执行,所以备机也没有这部分数据。最终的结果就是,这部分脏数据就被丢弃了,不会造成主从的不一致。        5. 优点:保证至少一个备机和主机在任何时候都是一致的,不会出现你比我多或者我比你多的情况,不需要进行主从恢复后的数据恢复行为。在只有一主一从的情况下,整个系统永远不会有脏数据。        6. 缺点:显而易见的,一主多备的情况下,除了只有一台备机的情况外,其他备机都会有数据不一致现象。另外,没有成功传输的数据就被直接丢弃了,找都找不回来,如果涉及金融交易,瞬时的数据丢失也是不可原谅的,所以这种架构在数据重要度非常高的业务里不能用。(3)MySQL5.6版本        1. 5.6版本对主从同步进行了改进,加入了GTID(5.6.2开始,5.6.10完善)的事务区分标志,又加入了多线程复制和组提交的新模式。        2. GTID:在MySQL5.6以前对于主从复制出现问题有时候需要分析BINLOG找到POS点,然后再CHANG MASTER TO。容易犯错,造成主从复制错误。引入GTID后,不需要再寻找BINLOG和POS点,只需要知道MASTER的IP、密码、端口就可以,MySQL会从内部GTID机制自动找到同步点。加入GTID后,一是可以根据GTID可以知道事务最初是在哪个实例上提交的,二是GTID的存在也方便了Replication的Failover。        3. GTID原理:分成两部分,一部分是服务的UUID,保存在mysql数据目录的auto.cnf文件中,这是一个非常重要的文件,不能删除,这一部分是不会变的。另外一部分就是事务ID(TID)了,随着事务的增加,其值依次递增。        4. 多线程并发复制:在MySQL5.6之前,复制是单线程队列式的,只能一个一个运行。在新版中支持基于库的多线程复制,但是库里的表不能多线程。针对多个库的情况,开启多线程,每个库一个独立IO线程,可以交叉并发传输。在不同库同一时间进行的操作理论上是互不影响的,可以同步进行,你改你的,我改我的。极大改善了多库业务的复制速度。贴个经典的图。                5. 5.6的并行复制框架实际包含了一个协调线程和若干个工作线程,协调线程负责分发和解决冲突,工作线程只负责执行。        6. 但是多线程并发复制也不一定完全有效,其并行只是基于schema的,也就是基于库的。如果用户的MySQL数据库实例中存在多个schema,对于备机复制的速度的确可以有比较大的帮助。但如果业务始终只有一个库,或者数据库压力都集中在一个库上,其他库基本没什么操作,那针对库的多线程基本没有意义,还是和以前的单线程复制是一样的速度。所以说MySQL 5.6所谓的并行复制对真正用户来说,有点雷声大雨点小。        7. 组提交:极大提升了binlog和innodb的redolog的落盘(保存到磁盘)效率,可将多次磁盘IO可以合并成一次磁盘IO,减少读写次数,有效提高了写日志的速度。也就意味着在主从同步过程中,磁盘IO这一块的效率提高了。        8. 组提交的原理:多个事务同时执行完成,数据需要持久化到log中时,会全部进入一个待提交队列。最先进入队列的事务线程成为leader线程,其他后续进入的成为follower线程,leader线程将会获得这个队列的控制权,就是会获得一个锁,全权负责本次队列中所有事务的落盘操作。接着联系其他follower线程,将他们的提交内容获取得到,并让他们等待自己完成操作。接着这个leader线程会进入后续的落盘过程,等完成后,会通知本队列中所有follower线程落盘已经完成,可以返回成功状态了。(4)MySQL5.7版本        1. MySQL 5.6基于库的并行复制出来后,基本无人问津,在沉寂了一段时间之后,MySQL 5.7出来了,它的并行复制以一种全新的姿态出现在用户面前。MySQL 5.7才可称为真正的并行复制,这其中最为主要的原因就是slave服务器的回放与master是一致的,即master服务器上是怎么并行执行的,那么slave上就怎样进行并行回放。不再有库的并行复制限制,对于binlog格式也无特殊的要求(基于库的并行复制也没有要求)。        2. 5.7之所以被看作mysql主从复制上一个划时代的版本,主要原因是mysql将日志组提交的模式应用到了主从网络IO上,在原来已经通过组提交优化了的磁盘IO效率基础上,对网络IO效率进行了同样的优化,正是将困扰mysql主从复制多年的两大难题解决的最重要版本。官方称之为Enhanced Multi-Threaded Slave(简称MTS)。        3. MTS这么牛,再多点一下:增强的多线程复制,即通过备机开启多个IO线程,主机通过组提交的模式并行地传输事务进行复制。具体思想简单易懂,一言以蔽之:一个组提交的事务都是可以并行回放的,若这些事务都已进入到事务的prepare阶段,则说明事务之间没有任何冲突(否则就不可能提交),关于MTS的详细原理和实现,可以查阅资料详细学习一下,这里点到为止。        4. 但是前面提到的网络IO是有先后顺序的,和传输顺序通常是不同的,收到事务后需要区分先后顺序来执行,否则备机执行顺序和主机不同,数据同样会出错。获取事务先后顺序的方法也很简单,就是使用的MYSQL 5.6已经加入的GTID,因为每个事务在提交时已经按顺序生成了唯一的GTID,备机读到事务后按照GTID的顺序执行就可以了。        5. 在这样的模式下,从机可以同时消费主机的多个事务队列,在同一时间接收到更多的数据传输,有效降低了数据来不及传输而导致的宕机数据丢失的概率。        6.最后提一个问:MySQL5.7是如何识别哪些事务是要一起提交的呢?        其实就是在GTID event 中增加了两个字段:int64 last committed和int64 sequence number,同一个组提交里多个事务gtid不同,但last committed却是一致的,同时一个组里的last committed对应上一个事务的sequence number。当slave的coordinator线程在分发这些event的时候,具有相同last committed 的事务(event的集合)就可以同时发送给不同的work线程,达到并行同步的目的。        总结一下,MySQL复制演进历程大致可以概括为:从5.5的单线程复制,到5.6基于Schema级别的并行复制,再到5.7最大化还原主库的支持事务级别的并行复制。其实总体来看其发展是有连贯的前因后果的,大致了解MySQL复制的来龙去脉之后,再去抠细节会清晰许多。
  • [大赛专区] &lt;华为云DevCloud软件编程大赛&gt;口罩配送大作战--代码测试工具
    下方提供代码测试工具下载使用方式:编译命令(要求jdk1.8):javac MaskTest.java运行命令:java MaskTest <你的代码进程启动命令>例如:C++(windows): java MaskTest Main.exeC++(linux): java MaskTest ./Main.outjava: java MaskTest java Mainpython: java MaskTest python Main.py代码常见问题:1. 配送路径值为非法数据:只接受[E|W|S|N]2. 超过步数上限500:一张地图的步数超出了5003. 快递员中间离开地图范围:接受某次移动方向后,快递员离开地图范围4. 运行超时:  a. 所有待配送小区需求口罩数已为零,进程没有中断  b. 进程在接受'G'指令后,没有返回方向字符,仍在等待输入,进程被IO阻塞  c. 每次输出没有独占一行,例如java应使用System.out.println()而不是System.out.print()  d. 存在死循环  e. 时间复杂度过高5. 配送结束后,尚有小区未获得口罩:进程退出时,仍存在待配送小区6. 运行出错:  a. 代码无法通过编译  b. 代码抛出异常、内存溢出、return非零值等运行时错误  c. 进程退出时,仍存在待配送小区(导致接收'G'指令的通道关闭)
  • [问题求助] Tuning kit 安装在鲲鹏云服务器上,运行时报错,请帮忙查看,进程分析、系统分析任务也失败
    资源信息如下:
总条数:755 到第
上滑加载中