-
1. 适用场景 当GaussDB A集群中Coordinator实例数量偏少时,可通过添加Coordinator实例来分担其它Coordinator实例的压力。 本方案仅适用于线下产品。2. 前提条件 添加Coordinator实例前,GaussDB A集群需处于“良好”状态。su - ommsource /opt/huawei/Bigdata/mppdb/.mppdbgs_profilecm_ctl query -Cv 2) 添加Coordinator前不能锁定GaussDB A集群。3) 一次仅允许添加一个Coordinator实例。 3. 注意事项1) 添加Coordinator前不能锁定GaussDB A集群。2) 一次仅允许添加一个Coordinator实例。3) 添加Coordinator实例需要在一个状态正常的物理节点上操作。4) 添加Coordinator实例操作不能与其它运维操作交叉执行。5) 在GaussDB A节点添加Coordinator实例需要提前创建好Coordinator实例相应目录。4. 对系统影响1) 增加CN过程中集群可以执行业务,特别说明:由于过程中会短暂锁集群,锁集群后用户下发的包含显式启动事务的DDL语句会出现等待,集群解锁后会报错或等待时间超过20分钟会报错。如包含创建临时表操作,在集群解锁后会报错(Don't support temp table when need reconnect pooler)。2) 增加、删除CN过程中系统将关闭“自动剔除故障CN”功能,在完成后系统再次打开该功能。5. 准备工作该部分工作可在增加CN操作开始前执行。5.1确认集群状态步骤1 按前提条件查询若balanced显示为No不影响增加CN操作。步骤2 如果不满足以上状态,则联系华为工程师处理。5.2检查正常CN目录是否正常步骤1 使用omm用户登录正常CN所在节点。步骤2 切换到CN目录下,检查是否有非omm用户文件。cd /srv/BigData/mppdb/data1/coordinator/ls -al红色斜体按CN具体所在目录替换步骤3 检查是否有不属于CN目录的超大文件(如core),如有移走。du -sh *移走超大文件,如无法确定该文件是否属于该目录,请及时联系华为工程师。5.3检查需添加CN的节点是否已有CN进程步骤1 登录需添加CN节点执行如下命令。ps -ef | grep coor | grep -v grep如无返回结果正常,否则kill -9 异常进程。5.4检查信号量是否不足步骤1 root用户登录需添加CN节点执行如下命令。cat /proc/sys/kernel/sem若结果为 250 6400000 1000 25600结束该检查否则执行 echo 250 6400000 1000 25600 > /proc/sys/kernel/sem5.5检查enable_stateless_pooler_reuse参数是否关闭8.0版本不涉及此问题,6.5.1版本需检查步骤1 使用omm用户登录任意数据节点,source Gauss环境变量,执行如下命令。su - ommsource /opt/huawei/Bigdata/mppdb/.mppdbgs_profilegs_guc check -Z coordinator -Z datanode -N all -I all -c "enable_stateless_pooler_reuse"步骤2 如显示enable_stateless_pooler_reuse=on 需关闭该参数并重启集群,显示enable_stateless_pooler_reuse=NULL或off跳过该项检查。gs_guc set -Z coordinator -Z datanode -N all -I all -c "enable_stateless_pooler_reuse=off"cm_ctl stop && cm_ctl start 6. 变更步骤6.1增加CN实例步骤1登录FusionInsight Manager系统,选择“集群 > 待操作的集群名称 > 服务 > MPPDB”。步骤2 单击“实例”,在实例列表中选择需添加CN节点对应的MPPDBServer。步骤3 单击“实例配置 > 全部配置”,在搜索框中输入参数名称“mppdb.coo.number”进行搜索。步骤4 将“mppdb.coo.number”的值设置为1,单击“保存”。步骤5 在弹出窗口中,单击“确定”。待界面提示“操作成功。”,单击“完成”,Coordinator实例添加成功。说明如果界面保存配置失败,需联系技术支持查找失败的原因,等待故障排除后,在界面将“mppdb.coo.number”的值改为1,单击“保存”,以确保和后台实际集群状态一致,再尝试执行步骤4&步骤5。 6.2更新lvs(如果有)步骤1 以root用户身份登录服务器,执行source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile命令启动环境变量。步骤2 执行gs_loadbalance更新负载均衡配置。gs_loadbalance -t reload -U omm -X ${BIGDATA_HOME}/FusionInsight_MPPDB_*/*_*_MPPDBServer/etc/mppdb-install-config.xml --lvs-addr=10.146.156.101路径中红色斜体替换为实际版本路径参数说明-U:运行集群的操作系统用户名。必选。-X:集群配置文件。必选。--lvs-addr:后续供客户端连接的LVS IP地址。必选。
-
1. 适用场景 DN状态异常(down) CN处于deleted或down状态2. 前提条件1) GaussDB A集群安装成功,且处于已启动状态。2) DN环的主、备实例不能同时损坏,DN环的主、从备实例不能同时损坏,DN环的备、从备实例不能同时损坏,即一个DN环中只能损坏一个实例。3) GaussDB A集群内如下实例至少存在一个正常运行的:◾CMServer◾CMAgent◾GTM◾Coordinator4) 如果某个GTM实例存在故障,则要求实例修复前另外一个GTM实例必须为最高可用模式。3. 注意事项1) 操作要在正常节点执行,不能在被修复节点执行2) 在前一次修复结束后才能再次执行修复。2) 修复前不能锁定GaussDB A集群。3) 修复故障实例过程中系统将关闭“自动剔除故障CN”功能,完成后系统再次打开该功能。因此建议在开始修复前确认故障的CN已经被自动剔除(即故障的CN状态为Deleted),否则在修复过程中用户执行DDL会报错。4) 实例修复前用户手动在故障实例上配置的guc参数、pg_hba.conf配置的白名单会丢失,需要提前备份。5) gs_replace不涉及cn的,可以在线执行;gs_replace涉及cn的,8.0版本之前,必须离线执行;gs_replace涉及cn的,8.0版本之后,只要保证被修复的cn没有DDL业务即可4. 对系统影响由于过程中会短暂锁集群,锁集群后用户下发的包含显式启动事务的DDL语句会出现等待,集群解锁后会报错或等待时间超过20分钟会报错。如包含创建临时表操作,在集群解锁后会报错(Don't support temp table when need reconnect pooler)。5. 准备工作5.1检查集群状态步骤1 以omm用户登录GaussDB A集群的第一个正常的cn节点步骤2 执行以下命令,启用环境变量source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile步骤3 执行以下命令,查看GaussDB A集群当前状态cm_ctl query -Cv查看具体故障实例所在节点:实例不是“Normal”状态,且持续5分钟没有自恢复[ Cluster State ] cluster_state : Degradedredistributing : Nobalanced : Yes [ Datanode State ] node instance state | node instance state | node instance state--------------------------------------------------------------------------------------------------------------------------1 redhat1-1 6001 P Down Disk damaged | 2 redhat1-2 6002 S Standby Normal | 3 redhat1-3 3002 R Secondary Normal1 redhat1-1 6003 P Primary Normal | 3 redhat1-3 6004 S Standby Normal | 2 redhat1-2 3003 R Secondary Normal2 redhat1-2 6005 P Primary Normal | 3 redhat1-3 6006 S Standby Normal | 1 redhat1-1 3004 R Secondary Normal2 redhat1-2 6007 P Primary Normal | 1 redhat1-1 6008 S Standby Normal | 3 redhat1-3 3005 R Secondary Normal3 redhat1-3 6009 P Primary Normal | 1 redhat1-1 6010 S Standby Normal | 2 redhat1-2 3006 R Secondary Normal3 redhat1-3 6011 P Primary Normal | 2 redhat1-2 6012 S Standby Normal | 1 redhat1-1 3007 R Secondary Normal步骤4以上查询结果为例,故障实例所在节点名称为redhat1-15.2关闭集群通信白名单(需要离线时做)注意:若被修复节点上没有cn,在没有IO压力的情况下可以在线操作。如果被修复节点有cn,则必须离线操作!步骤 1 现场实施人员知会并确认用户已完成数据库业务停止操作。步骤 2 以omm用户登录第一个正常的CN节点,执行如下命令注释用户白名单 以默认CN实例目录/srv/BigData/mppdb/data1/coordinator为示例,现场需根据实际情况进行调整。source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile gs_ssh -c "hostname && if [ -f /srv/BigData/mppdb/data1/coordinator/pg_hba.conf ]; then cp -f /srv/BigData/mppdb/data1/coordinator/pg_hba.conf /srv/BigData/mppdb/data1/coordinator/pg_hba.conf_comment; fi " gs_ssh -c "hostname && if [ -f /srv/BigData/mppdb/data1/coordinator/pg_hba.conf ]; then sed -i '/^[^#].*sha256.*/s/\(.*\)/#@#@#\1/g' /srv/BigData/mppdb/data1/coordinator/pg_hba.conf; fi " gs_ssh -c "hostname && if [ -f /srv/BigData/mppdb/data1/coordinator/pg_hba.conf ]; then sed -i '/^[^#].*md5.*/s/\(.*\)/#@#@#\1/g' /srv/BigData/mppdb/data1/coordinator/pg_hba.conf; fi "步骤 3 以omm用户登录第一个正常的CN节点,关闭MPPDB实例节点下的后台访问连接和应用连接。具体操作如下:source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile gs_ssh -c "ps ux |grep -w gsql |grep -v grep |awk '{print \$2}' |xargs -r kill -9" gs_ssh -c "ps ux |grep -w ap_agent |grep -v grep |awk '{print \$2}' |xargs -r kill -9"步骤 4 以omm用户登录每一个正常CN节点,执行如下命令重启CN。执行以下命令,获取到CN的进程Pidps -ef | grep /srv/BigData/mppdb/data1/coordinator | grep -v grep执行以下命令,杀死CN进程kill -9 Pid执行以下命令,观察CN被重新拉起,并且Pid与之前获取的Pid不同ps -ef | grep /srv/BigData/mppdb/data1/coordinator | grep -v grep6. 变更步骤6.1清理残留文件步骤1 以omm用户登录被修复的节点步骤2 执行以下命令,启用环境变量source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile步骤3 使用如下命令在需要修复实例的主机上清理可能存在的残留文件。此命令仅在上次修复故障实例执行失败的情况下需要执行。if [ -f $PGHOST/GaussReplace.dat ];then rm $PGHOST/GaussReplace.dat;fi 说明该文件为替换故障实例、替换主机中产生的用于记录执行步骤的临时文件,如果在上次执行过程中出现宕机或网卡中断等,可能会导致该文件残留。在替换故障实例前检查该文件是否存在,且生成时间非本次替换故障实例的时间,则可判断为上次执行的残留文件,删除该文件后,继续执行替换故障实例。6.2修改原cn目录名称(被修复节点有cn时做)步骤1 以omm用户登录需要被修复的节点步骤2 执行以下命令,启用环境变量source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile步骤3 使用如下命令修改原cn目录名称,防止修失败回退后误拉起损坏的cn。mv /srv/BigData/mppdb/data1/coordinator /srv/BigData/mppdb/data1/coordinator_bak 6.3配置实例步骤1 以omm用户登录GaussDB A集群的健康节点步骤2 执行以下命令,启用环境变量source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile步骤3 执行以下命令,完成故障实例所在节点配置操作gs_replace -t config -h redhat1-1 说明配置操作会清理替换实例的空间,初始化替换实例,配置替换实例。如果收到提示:“GAUSS_50201: The XXX does not exist.”,则请检查对应的实例数据目录是否存在。如果不存在,请重新创建目录后再次执行上述命令。如果指定主机的表空间所在磁盘出现故障,从而导致表空间中的数据损坏,更换新磁盘后,需要指定“--force”参数对该主机强制进行表空间数据的恢复。如果在config阶段指定“--force”参数,则在start阶段也必须指定“--force”参数。6.4还原cn的白名单(被修复节点有cn时做)如果有配置lvs,每个cn的白名单相同,可跳过此小节。步骤1 以omm用户登录需要被修复的节点步骤2 执行以下命令,启用环境变量source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile步骤3 使用如下命令将备份的白名单还原,操作前确认备份的白名单文件没有损坏。cp /srv/BigData/mppdb/data1/coordinator_bak/pg_hba.conf /srv/BigData/mppdb/data1/coordinator/ 6.5恢复集群通信白名单(需要离线时做)步骤1 以omm用户登录第一个正常的CN节点,执行如下命令注释用户白名单 以默认CN实例目录/srv/BigData/mppdb/data1/coordinator为示例,现场需根据实际情况进行调整。source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile gs_ssh -c "hostname && sed -i '/^#@#@#.*/s/#@#@#\(.*\)/\1/g' /srv/BigData/mppdb/data1/coordinator/pg_hba.conf && rm -f /srv/BigData/mppdb/data1/coordinator/pg_hba.conf_comment "6.6启动实例步骤1 以omm用户登录GaussDB A集群的健康节点步骤2 执行以下命令,启用环境变量source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile步骤3 执行以下命令,完成故障实例所在节点启动操作gs_replace -t start -h redhat1-1启动操作会启动集群替换实例的主机gs_replace -t start -h redhat1-1Starting.======================================================================Successfully started instance process. Waiting to become Normal.======================================================================.======================================================================Start succeeded on all nodes.Start succeeded.6.7重置实例参考主备均衡方案实施。cid:link_06.8更新lvs(被修复节点有cn时做)步骤1 以root用户身份登录服务器,执行source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile命令启动环境变量。步骤2 在主备lvs节点和所有cn节点执行gs_loadbalance更新负载均衡配置。gs_loadbalance -t reload -U omm -X ${BIGDATA_HOME}/FusionInsight_MPPDB_*/*_*_MPPDBServer/etc/mppdb-install-config.xml --lvs-addr=10.146.156.101路径中红色斜体替换为实际版本路径参数说明-U:运行集群的操作系统用户名。必选。-X:集群配置文件。必选。--lvs-addr:后续供客户端连接的LVS IP地址。必选。7. 验证步骤7.1确认结果1)后台集群状态验证步骤1 以omm用户登录GaussDB A集群的第一个正常的cn节点步骤2 执行以下命令,启用环境变量source ${BIGDATA_HOME}/mppdb/.mppdbgs_profile步骤3 执行以下命令,查看GaussDB A集群当前状态cm_ctl query如下则为正常[ Cluster State ] cluster_state : Normalredistributing : Nobalanced : Yes2)客户业务验证验证方案需包括DDL和DML语句
-
什么是多线程? 在单片机上学习RT-Thread的多线程之前,要先把“进程”这个概念先放一边,因为单片机是没有多进程概念的。单片机运行操作系统,不管多少个任务,他们都是多个(或单个)线程之间进行处理这些任务,单片机一般不涉及多进程。 什么是多线程?在哪些情况下要用到多线程?先来举一个音乐播放器的例子,这个音乐播放器要做以下这些基本的工作:读取音乐文件并播放、读取歌词并显示、读取MV文件并播放。 如果这三个基本的工作不用多线程来完成,单片机使用裸机的方式去做这三个工作的话,必然会造成音乐播放卡顿,歌词显示不同步,MV视频播放与音乐不同步。 因为单片机做这三件事情的时候,是Step by Step的,必须完成一件事情之后,再去做下一件事情,这三件事情是有先后顺序的,并且不断循环重复,如下图所示。 而如果采用多线程这种方式来完成这个工作,这个过程就变得相对简单了,比如针对音乐播放器这个场景,可以设计这几个线程来处理:音乐文件读取线程,歌词文件读取线程,MV文件读取线程,音视频和歌词显示线程。 (此处只为举例描述多线程的概念,不考虑音视频编解码的复杂过程,不考虑线程同步,实际上音乐播放器的实现比此处描述更复杂) 音乐文件读取线程只负责从磁盘读取音乐文件,歌词文件读取线程和MV文件读取线程也是同样的道理,它们只做文件读取工作,而音视频和歌词显示线程,是负责把读取到的数据进行显示。这几个线程的工作过程,如下图所示。 如上图所示,这几个任务看上去是“同时”进行的,每个任务都只完成自己的事情,通过多线程,就可以把原本串行完成的任务改为并行完成,大大提高了工作效率。 所以,通俗地对多线程进行理解,就是把一个比较大型的任务,拆分为多个小型的任务,然后通过合理的调度方式,让这几个小型的任务“同时”运行,当这几个小型任务完成后,大型的任务也随之完成,这样可以大大提高任务的完成效率。多线程的几种状态 对于运行RT-Thread操作系统,线程都处于以下五种状态的其中一种(初始状态、就绪状态、运行状态、挂起状态、关闭状态),通过调用操作系统提供的接口函数,可以让线程在这五种状态中进行来回切换。 关于这五种线程状态的描述,如下表所示:多线程的API函数 如上图的状态机所示,多线程可以通过调用系统提供的函数接口,在多个状态之间进行切换。这些API函数在官方提供的参考文档里面都有详细的说明描述,以下列举一些比较常用的函数接口。多线程的应用示例 多线程的应用示例,主要是为了验证以上的多线程API接口函数,并且通过实验现象观察多线程的运行情况,主要有以下三个示例: 示例源码下载链接:https://github.com/embediot/rtthread_study_notes1、线程动态创建与静态创建、线程退出示例。 这个示例主要是通过动态方式创建线程1,,通过静态方式创建线程2,线程1的优先级比线程2的优先级低,因此可以被线程2抢占。线程2运行10次后就会主动退出,初始化代码如下图所示。2、相同优先级线程的时间片轮转调度示例。 这个示例主要是通过动态方式创建线程1和线程2,这两个线程都是相同的优先级,并且共用一个线程入口函数,主要是通过传入不同的线程参数以区分线程1和线程2。线程2运行所占用的时间片比线程1要少,因此线程2运行的时间比较短,初始化代码如下图所示。3、线程调度器的钩子函数使用示例。 这个示例主要测试了线程在进行调度时,关于钩子函数的调用情况。通过线程调度器的钩子函数,打印出线程间的切换信息,初始化的代码如下图所示。多线程应用的注意事项 在使用RT-Thread实时操作系统进行多线程应用开发的时候,应该要注意以下事项:1、RT-Thread的线程调度器是抢占式的,也就是能够保证就绪队列里面,最高优先级的任务总能获得CPU的使用权,在任务设计的时候,要充分考虑好任务的优先级。2、在硬件中断服务程序运行期间,如果有高优先级的任务就绪,那么被中断的低优先级任务将被挂起,高优先级的任务将会获得CPU的使用权。3、每个线程都有独立的线程栈,用来保存线程调度时上下文的信息,因此在创建线程分配栈空间的时候,要充分考虑栈的大小。4、在线程的循环体里面,应该要设置某些条件,在必要的时候主动让出CPU的使用权,特别对于高优先级的线程,如果程序里面有死循环操作而又不主动让出CPU使用权,那么这个线程将会一直占用CPU,并且低优先级的线程永远不会被调度执行。5、对于没有一直循环执行的线程,线程执行完毕后,资源的回收情况实际上是在空闲线程里面进行的,线程变为关闭状态后,不代表资源马上被回收。6、系统空闲线程是最低优先级且永远为就绪状态的,空闲线程是一个死循环,永远不会被挂起,但可以被其他高优先级任务抢占,空闲线程主要执行僵尸线程的资源回收工作。7、空闲线程也可以设置钩子函数,用来进行功耗管理,看门狗喂狗等工作。8、通过动态方式创建的线程,需要设置好系统堆内存的大小,而通过静态方式创建的线程,线程栈和线程句柄在程序编译的时候就已经确定,不能被动态分配,也不能被释放。9、大多数线程都是在不断循环执行的,无需进行删除,一般不推荐主动删除线程。线程运行完毕后,系统调度器将会自动把线程加入僵尸队列,资源回收工作将在空闲线程里面进行。
-
关键字: 句柄不回收;空间不释放;deleted;磁盘满;磁盘使用率高;现象: 磁盘使用率高,df -h和du -sh查看数据目录,发现大小不同,差别很大。lsof查看发现有大量的文件处于deleted状态:这类文件分三种,按照下面命令可以统计这类不回收文件的数量1. base 目录下数据文件:lsof|grep deleted |grep base| wc -l2. pg_xlog目录下的xlog文件;lsof|grep deleted |grep pg_xlog| wc -l3. cm和om目录下的各种目录文件,这类文件句柄查出来有很多重复的,一般情况不用处理;通过lsof|grep deleted |grep '.log'| wc -l规避措施:1. base目录下数据文件和pg_xlog下xlog文件可以采用以下方法之一进行处理:方法一:kill dn实例。具体操作步骤如下:gsql 连接CN, 执行checkpoint;在空间不回收的实例上杀掉dn进程; 这里27620是上图中dn的进程号,实际操作请替换给对应的进程号: kill -9 27620影响:kill DN实例会导致当前业务执行报错,请确认后操作;方法二:在线清理句柄。具体操作如下:连接CN执行checkpoint;连接CN清理每个库的空闲连接: clean connection to all for database xxxx;这里xxxx是数据库名称,通过 \l 命令可以查看当前所有数据库。对每个库都做同样的清理。该动作知会清理idle连接,不影响业务。如果前面两步执行完,空间依旧不释放,说明可能存在长连接,连接空间不释放的实例,找出这些连接,全部杀掉即可。查询语句如下:select now()-query_start as ctime, * from pg_stat_activity where state='idle' order by ctime desc;杀语句方法:select pg_terminate_backend(pid) from pg_stat_activity where state='idle' order by ctime desc;2. cm和om日志,这部分使用空间不大,一般只有几十MB,可以不用处理。但是部分异常情况下,日志没有分割,导致占用空间比较大:规避措施分两步:查看om日志持续上涨的原因,这里27709是上图中的进程号,3是文件句柄:tailf /proc/27709/fd/3根据报信息找研发处理对应报错;清理存量数据cat /dev/null > /proc/27709/fd/3注释:该方法不会释放文件句柄,只是释放空间,并保证空间不会上涨。
-
【问题现象】通过iotop观察主OMS节点 stats collector 进程占用的IO非常高,导致该节点的性能下降。【规避办法】1. 切换到数据库用户,例如su - ommdba2. cd $GAUSSDATA3. vi postgresql.conf4. 文件末尾添加:stats_temp_directory='/dev/shm/pg_stat_tmp'5. 保存后退出6. 执行该命令令其生效:gs_ctl reload然后可以iotop 观察,可以明显看到io降下去了【原理说明】stats_temp_directory参数说明:设置存储临时统计数据的目录。参数类型:SIGHUP将其设置为一个基于RAM的文件系统目录会减少实际的I/O开销并可以提升其性能。
GreatPeter
发表于2021-07-27 11:31:12
2021-07-27 11:31:12
最后回复
Select*fromMacchiato
2021-07-30 23:45:25
2245 1 -
【问题现象】drop表的语句,hang住,无法执行。【问题分析】(1) 先通过这个语句查询pgxc_stat_activity,找到这个语句的query_id。select query_id from pgxc_stat_activity where query like '%drop table %';(2) 查找等待视图,发现这个语句在等DN上的锁。(3)连接到DN6075上,找到锁冲突的线程。select oid,* from pg_class where relname='表名';select * from pg_locks where relation = 94747;(4) 连接到DN6075上,根据pid 找到冲突语句的query_idselect query_id from pg_stat_activity where pid = 'xxxx';(5) 在CN上,创建下面的存储过程,根据query_id,批量的杀掉 各个DN上残留的线程。CREATE OR REPLACE PROCEDURE pgxc_terminate_query(IN queryId TEXT)AS nodeName TEXT; kpid TEXT; query_str TEXT;BEGIN FOR nodeName, kpid IN SELECT node_name, tid FROM pgxc_thread_wait_status WHERE query_id = queryId LOOP query_str = 'EXECUTE DIRECT ON ('|| nodeName||') '' SELECT PG_TERMINATE_BACKEND('''''||kpid||''''')'';'; --dbms_output.put_line(query_str); EXECUTE query_str; END LOOP;END;/select pgxc_terminate_query(query_id);注意: 如果通过上面的语句无法杀掉DN上残留的语句,可以先通过kill DN的方式进行规避。
GreatPeter
发表于2021-07-27 10:59:17
2021-07-27 10:59:17
最后回复
Select*fromMacchiato
2021-07-30 23:46:20
3308 3 -
做压力测试时,发现docker容器只能支持128个线程。超过128后出现 fork: retry: Resource temporarily unavailable导致容器中的其他进程无法启动。AR502H宿主由于linux下的每个线程都有一个PID。如果按PID的方式限制是否应该按进程的PID。容器的ulimit -a 信息top -H问题:1. 如何修改线程128限制?2. 如果128个PID受限了,怎样配置为按进程的PID而不是按线程的PID?
-
[root@k8s-master tmp]# scp -r /opt/etcd/ root@114.x.x.x:/opt/root@114.x.x.x's password: server-key.pem 100% 1679 2.2MB/s 00:00 ca-key.pem 100% 1675 1.0MB/s 00:00 server.pem 100% 1338 2.4MB/s 00:00 ca.pem 100% 1265 2.0MB/s 00:00 etcd.conf 100% 519 883.6KB/s 00:00 etcdctl 100% 13MB 191.0KB/s 01:09 scp: /opt//etcd/bin/etcd: Text file busy搜了下这个报错是因为etcd进程还处于alive状态,也就是说数据一直在同步当中,系统限制了scp的文件拷贝。解决的办法很简单,kill掉进程就可以了。在每个节点用systemctl stop etcd然后再重新执行一遍文件拷贝工作。[root@k8s-master tmp]# scp -r /opt/etcd/ root@114.x.x.x:/opt/root@114.x.x.x's password: server-key.pem 100% 1679 2.9MB/s 00:00 ca-key.pem 100% 1675 3.4MB/s 00:00 server.pem 100% 1338 2.5MB/s 00:00 ca.pem 100% 1265 2.5MB/s 00:00 etcd.conf 100% 519 1.0MB/s 00:00 etcdctl 100% 13MB 188.3KB/s 01:10 etcd 100% 16MB 192.2KB/s 01:26 [root@k8s-master tmp]#
-
调优介绍在 SMP(Symmetric multiprocessing)架构中,每个CPU拥有一个cache,用来存储当前访问以及预测接下来会访问到的数据。Cache Line是一次加载到cache中的数据单元。通常是64 byte,但在鲲鹏920上的L3 cacheline是128byte。多个CPU上的多个线程同时修改自己的变量,这些变量表面上是不同的变量,但是实际上却存储在同一条Cache Line里。在这种情况下,由于Cache一致性协议,两个处理器都存储有相同的Cache Line拷贝的前提下,本地CPU变量的修改会导致本地Cache Line变成Modified状态,然后在其它共享此Cache Line的CPU上,引发Cache Line的Invalidate操作,导致Cache Line变为Invalidate状态,因此必须得从memory加载,这种现象就叫做伪共享false sharing。解决伪共享的方式有很多,例如:使用编译器优化选项。通过对内存填充(padding),保证不同线程使用的变量在不同的Cache Line中。定义变量时,进行内存对齐。用thread local变量。将同一个Cache Line上的变量拷贝一份到本地,进行使用。本示例中使用第三种方法用alignas进行强制以128byte对齐。组网环境请确认服务器上已安装的操作系统是否为openEuler 20.03,GCC版本是否为7.3.0及以上。请确认服务器上是否已安装鲲鹏性能分析工具(Hyper Tuner)2.3.T10版本。请从Github下载代码样例falsesharing.c、falsesharing_mod.c、falsesharing_start.sh,并赋予所有用户只读、只写、可执行权限。chmod 777 falsesharing.c falsesharing_mod.c falsesharing_start.sh前提条件1. 服务器和操作系统正常运行。2. PC端已经安装SSH远程登录工具。3. 目标环境上HyperTuner工具已经安装完成,并正常运行。调优思路1. 在进行调优之前,先用HyperTuner工具对目标环境的空载系统进行全局的系统性能分析。2. 对全景性能分析中,有异常的指标进一步分析,并根据优化建议进行优化修改。3. 对优化后的系统再次进行全景性能分析,验证调优后的效果。操作步骤步骤1 程序准备编译c并赋予执行文件所有用户只读、只写、可执行权限。gcc falsesharing.c -lpthread -D _GNU_SOURCE -o falsesharing -g && chmod 777 falsesharing使用后台启动脚本循环运行falsesharing 100次,同时nohup命令使得即使退出账户之后会继续运行相应的进程,防止任务中断。nohup bash falsesharing_start.sh >>falsesharing.out 2>&1 &程序运行的输出(标准输出(1))将会保存到falsesharing.out文件,错误信息(2)会重定向到falsesharing.out文件。其中falsesharing_start.sh脚本内容如下。如果falsesharing_start.sh程序没有正常运行,可以通过falsesharing.out文件检查错误信息,注意检查是否是window-style line endings问题,如果是,可以通过vi -b falsesharing_start.sh进行删除。步骤2 在程序运行的过程当中,我们利用鲲鹏性能分析工具创建系统全景分析任务,分析当前程序。创建系统全景分析任务,并启动分析。查看采集分析结果。系统全景分析结果总览系统全景性能分析结果(时序)系统全景性能分析结果(列表)“总览”页签上方会显示“检测到CPU利用率高”的优化建议,并且从“性能”页签的CPU利用率图7-3可以看到图形化界面的top5 %cpu对应的CPU核在采集时间内的利用率变化,可以看到0-3核CPU利用率很高。点击右上角的按钮切换至列表图7-4,可以看到在采集时间内的各项数据的平均值。当前有CPU核0-3的使用率(“性能”页签下%cpu的数值)很高,并且绝大部分消耗在用户态。由此说明这个程序全部消耗在用户态计算,没有其他IO或中断操作。步骤3 采用进程/线程性能分析,找到是哪个进程造成的CPU消耗。创建进程/线程性能分析任务,并启动分析。 配置参数如下:分析对象:系统采样时长:10秒采样类型:全部勾选采集线程信息:开启查看采集分析结果。默认排序是按照PID/TID升序排列,为了观察哪个进程造成了CPU消耗,我们点击%CPU列旁边的按钮进行降序排列。在“CPU”页签下,点击筛选按钮选择falsesharing程序所对应的PID,可以看到在falsesharing进程下有4个线程的CPU利用率达到100%。可以得出falsesharing程序在消耗大量的CPU,同时全部消耗在用户态中,由此我们可以推测很可能是自身代码实现算法差或Cache Miss问题。在这个步骤中,由于本示例是循环运行falsesharing程序,所以,如果采集时间长的话,可能采集到多个falsesharing程序进程。步骤4 结束程序。通过jobs -l查看falsesharing程序运行pid(如果程序尚未结束,可以看到后台运行的程序),通过kill -9结束进程。jobs -l kill -9 <falsesharing程序pid>步骤5 采用热点函数分析功能分析该程序,找到热点函数和指令。创建热点函数分析任务,并启动分析。 配置参数如下:分析对象:应用应用:输入程序所在的绝对路径,例如本示例将代码样例放在服务器上“/opt/testdemo/falsesharing/falsesharing”目录下。采样范围:用户态。采样范围分用户态、内核态、所有。因为我们这里发现所有的CPU消耗都在用户态,所以只采集用户态的数据。二进制/符号文件路径和C/C++源文件路径:用于采集过程当中,获取函数名和源文件代码。查看采集分析结果。从“总览”页面可以看到程序的运行时长、周期和指令数,以及热点函数inc_b1, inc_b, sum_a, sum_a1,但还是不知道是什么原因造成的。步骤6 采用“访存分析 > Miss事件分析”,进一步确认是Cache Miss造成。创建访存分析任务,并启动分析。 配置参数如下:分析对象:应用访存分析类型:Miss事件分析查看采集分析结果。从“时序视图”页签下,可以看到CPU 0,1,2,3核的Miss事件很多,总的LLC Miss事件个数达到392,732个。在“详细视图”页签下,从下拉菜单中选择“模块/函数/调用栈”,可以看到在程序falsesharing中有四个函数的Miss次数很高。这一步虽然可以确认Cache Miss造成,但是找不到优化点的。步骤7 针对Cache Miss造成问题,但又找不到是多个线程修改同一个全局变量(或变量成员),可以考虑继续采用伪共享分析。创建伪共享分析任务,并启动分析。 配置参数如下:分析对象:应用访存分析类型:伪共享分析采样时长:5秒。数值不宜过大,因为伪共享采集数据量大待采样CPU核:0,1,2,3 。因为从Miss事件分析中我们发现CPU0,1,2,3核Miss事件发生的次数最多,同时在全景分析中,这四个核的CPU利用率高二进制/符号文件路径和C/C++源文件路径:用于采集过程当中,获取函数名和源文件代码查看采集分析结果从“总览”页签中,可以发现在某一缓存行中伪共享一共发生了6,348,650次,在目标文件名中可以找到我们运行的应用程序falsesharing,点击相应的符号名,进入函数对应的代码页面。从“代码流”模块,可以找到伪共享数目占比高的Basic Block(颜色越深说明占比越高),单击Basic Block,可以在源代码模块和汇编代码模块浅蓝色高亮显示对应伪共享发生次数高的代码行。进一步定位此代码发生的问题。可以发现,两个线程同时修改了struct f中连续两个int变量x,y,由于int类型是4字节,所以x,y加载在同一个Cache Line上面,当运行在两个CPU核中的两个线程同时修改同一个Cache Line上面的不同变量数据时,产生了false sharing事件。优化方案使用alignas进行强制以128byte对齐解决伪共享问题。步骤1 程序准备。编译falsesharing_mod.c并赋予执行文件所有用户只读、只写、可执行权限。gcc falsesharing_mod.c -lpthread -D _GNU_SOURCE -o falsesharing_mod -g && chmod 777 falsesharing_mod步骤2 采用热点函数分析功能分析该程序。创建热点函数分析任务,并启动分析。 配置参数如下:分析对象:应用应用:输入程序所在的绝对路径,例如本示例将代码样例放在服务器“/opt/testdemo/falsesharing/falsesharing_mod”目录中。采样范围:用户态。采样范围分用户态、内核态、所有。因为我们这里发现所有的CPU消耗都在用户态,所以只采集用户态的数据。二进制/符号文件路径和C/C++源文件路径:用于采集过程当中,获取函数名和源文件代码。查看采集分析结果。 可以看出与之前falsesharing程序的热点函数分析相比,运行时间减少。步骤3 采用“访存分析 > Miss事件分析”功能进一步分析。创建Miss事件分析任务,并启动分析。 配置参数如下:分析对象:应用访存分析类型:Miss事件分析查看采集分析结果。Miss事件分析结果(时序视图)Miss事件分析结果(详细视图) 可以看到优化后的程序,Miss事件数目大幅减少,没有再在falsesharing_mod程序模块产生Miss事件。步骤4 采用“访存分析 > 伪共享分析”功能进一步分析。创建伪共享分析任务,并启动分析。 配置参数如下:分析对象:应用访存分析类型:伪共享分析采样时长:5秒。数值不宜过大,因为伪共享采集数据量大。待采样CPU核:0,1,2,3二进制/符号文件路径和C/C++源文件路径:用于采集过程当中,获取函数名和源文件代码。查看采集分析结果 可以看到不再有false sharing事件发生。---结束
-
【功能模块】arcore【操作步骤&问题现象】rsyslogd和systemd-journal这两个进程占用了cpu很多,怎么回事?【截图信息】无【日志信息】(可选,上传日志内容或者附件)无
-
一、概念Linux crontab是用来定期执行程序的命令。当安装完成操作系统之后,默认便会启动此任务调度命令。crond是后台进程,每分钟会定期检查是否有要执行的工作,如果有要执行的工作便会自动执行该工作。二、工作分类linux 任务调度的工作主要分为以下两类:系统执行的工作:系统周期性所要执行的工作,如备份系统数据、清理缓存。在/etc目录下有一个crontab文件,这个就是系统任务调度的配置文件。使用vim crontab打开后,界面如下:一般默认即可。个人执行的工作:某个用户定期要做的工作,比如用户数据备份,这些工作可由每个用户自行设置。所有用户定义的crontab文件都被保存在/var/spool/cron目录下。三、语法crontab [ -u user ] { -l | -r | -e }-u user 是指设定指定 user 的时程表,这个前提是你必须要有其权限(比如说是 root)才能够指定他人的时程表。如果不使用 -u user 的话,就是表示设定自己的时程表。-e : 执行文字编辑器来设定时程表,内定的文字编辑器是 VI,如果你想用别的文字编辑器,则请先设定 VISUAL 环境变数来指定使用那个文字编辑器(比如说 setenv VISUAL joe)-r : 删除目前的时程表-l : 列出目前的时程表四、案例使用使用时,须严格遵守下图的格式。 其中 f1 是表示分钟,f2 表示小时,f3 表示一个月份中的第几日,f4 表示月份,f5 表示一个星期中的第几天。commond表示要执行的程序。当 f1 为 * 时表示每分钟都要执行 commond,f2 为 * 时表示每小时都要执行程序,其余类推当 f1 为 a-b 时表示从第 a 分钟到第 b 分钟这段时间内要执行,f2 为 a-b 时表示从第 a 到第 b 小时都要执行,其余类推当 f1 为 */n 时表示每 n 分钟个时间间隔执行一次,f2 为 */n 表示每 n 小时个时间间隔执行一次,其余类推当 f1 为 a, b, c,... 时表示第 a, b, c,... 分钟要执行,f2 为 a, b, c,... 时表示第 a, b, c...个小时要执行,其余类推示例:每一分钟执行一次 /bin/ls:* * * * * /bin/ls在 12 月内, 每天的早上 6 点到 12 点,每隔 3 个小时 0 分钟执行一次 /usr/bin/backup:0 6-12/3 * 12 * /usr/bin/backup五、crond服务操作命令 1、service crond start 启动服务 2、service crond stop 关闭服务 3、service crond restart 重启服务 4、service crond reload 重新载入配置 5、service crond status 服务是否运行
-
以 RH2288H V3 服务器使用 2.6GHz 主频 CPU 为例,单台服务器有 2 个物理 CPU,每颗 CPU 有 8 核,又因为超线程技术可以提供每个物理内核两个处理线程,因此每颗 CPU 有 16 线程,总 vCPU 数量为 2 _ 8 _ 2=32 个 vCPU。总资源为32*2.6GHz=83.2GHz。
-
1 背景某某应用需要存储大量数据(千万-亿),根据数据量和数据特征,最终选择leveldb数据库来存。2 准备工作2.1 安装leveldb数据库使用源码安装,上github上下载1.20版本,然后解压,使用cmake编译安装可以参考https://www.huaweicloud.com/kunpeng/software/leveldb.html 2.2 C++知识准备查询资料得知,c++如何调用leveldb接口leveldb::DB *db leveldb::Options optionsleveldb::DB::Open如何插入数据db->Put(leveldb::WriteOptions(), f_key, f_value) 3 功能实现&性能优化3.1 实现简单的插入查询数据功能#include <iostream>#include <cassert>#include <cstdlib>#include <string>#include <leveldb/db.h>using namespace std;int main(void){ leveldb::DB *db = nullptr; leveldb::Options options; options.create_if_missing = true; leveldb::Status status = leveldb::DB::Open(options, "/tmp/testdb", &db); assert(status.ok()); std::string key = "A"; std::string value = "a"; std::string get_value; leveldb::Status s = db->Put(leveldb::WriteOptions(), key, value); if (s.ok()) s = db->Get(leveldb::ReadOptions(), "A", &get_value); if (s.ok()) cout << get_value << endl; else cout << s.ToString() << endl; delete db; return 0;}3.2 实现插入1千万条数据修改插入数据部分代码,使用for循环,进行插入for(int i=0; i<10000000; i++) { std::string f_value = value + to_string(i); std::string f_key = key + to_string(i); leveldb::Status s = db->Put(leveldb::WriteOptions(), f_key, f_value); if (!s.ok()) cout << s.ToString() << endl; }使用C++任务采集程序结果:通过工具性能数据发现,1千万条数据,时间花费27~28秒,与预期相差甚远,采集资源调度任务,发现进程线程切换频繁,且C++采集报告种syscalls:sys_enter_write事件非常多,怀疑是程序写入太频繁,数据库写入的buffer_size太小导致(4M),遂将其调整为1024M,结果如下: 调整buffer_size为1024M修改后,发现进程线程切换虽然变少,但是总体写入速度并未减少,怀疑是写入方式的问题导致写入速度慢,通过查询资料得知,leveldb写入数据时,可以通过原子批量写入方式,遂修改写入数据代码,结果如下: 设置批量写后:leveldb::WriteBatch bt; for(int i=0; i<10000000; i++) { std::string f_value = value + to_string(i); std::string f_key = key + to_string(i); bt.Put(f_key, f_value); } leveldb::Status s = db->Write(leveldb::WriteOptions(), &bt); 修改后,应用写入耗时变成16.58秒,有明显提升,但是发现资源调度任务结果中进程切换和numa节点切换依然存在,遂试试绑核执行程序,如下:绑核:绑核对写入速度并没有提升,还需要进一步分析,再进行验证调试
-
1 调优概述华为鲲鹏性能优化工具是一款针对鲲鹏平台的性能调优工具,包含系统性能优化工具和Java性能优化工具以及诊断调试工具。本文使用Java性能优化工具对运行中的Java程序进行在线分析和采样分析,找到程序问题,并根据分析结果进行优化修改,从而实现Java程序最佳运行。2 环境要求项目说明服务器TaiShan 200 服务器(型号2280)CPU鲲鹏920 4826处理器OSCentOS 7.6调优工具华为鲲鹏性能优化工具 V2.2.13 前提条件服务器和操作系统正常运行。PC端已经安装SSH远程登录工具需要优化的Java程序4 调优思路 使用Java性能优化工具对Java进程进行在线分析; 使用Java性能优化工具对Java进程进行采样分析 针对性能的瓶颈点进行性能优化; 观察优化后的Java程序,判断问题是否解决5 调优过程5.1 对程序进行在线分析,在概览页签下观察每种状态的线程数量发现有大量线程处于阻塞状态,有锁竞争的可能 发现有大量线程处于等待状态,有锁竞争的可能5.2 切换到CPU->线程列表,执行多次线程转储操作 5.3 切换到线程转储页签观察多个时间点线程转储的锁分析图,发现有多个线程同时竞争同一把锁,的确出现了锁竞争的情况,还可以发现这把锁不是JUC提供的工具锁,程序中使用的是 synchronized,如果锁竞争比较激烈,该类锁就会升级成重量级,会导致上下文切换比较严重,从而影响性能和关键业务的阻塞。 如果程序使用的是JUC提供的锁,锁分析图如下 5.4 切换到线程转储->原始数据根据从锁分析图中找到的对应锁的地址,在原始数据中进行搜索,可以看出有多个线程在获取这把锁,这把锁的类型以及竞争这把锁的代码位置 5.5 发现问题并解决根据线程转储中提供的锁的类型和位置,咱们就可以分析代码的业务逻辑,从而找到调优方案。下面介绍两种锁竞争的调优方法,仅供参考。情况一:使用synchronized,但在业务上竞争比较激烈将 synchronized 替换成 JUC 提供的工具锁(ReentrantLock等)情况二:使用JUC 提供的工具锁,但在业务上竞争比较激烈这种情况需要加入其他策略去提高性能,如加入线程池,限制竞争锁的线程数;如果是读写分离的场景,可以考虑使用ReadWriteLock。从业务的实际情况去考虑。6 实践总结Java中的锁竞争问题一旦发生很难定位具体的代码位置,因为程序干扰因素比较多,但是可以根据线程转储去定位,其中的栈追踪信息提供了发生锁竞争的代码位置。 如果发现多个线程都试图锁住相同的锁地址,说明应用正面临锁竞争,在进行其他程序调优时,需要根据华为鲲鹏性能优化工具采集分析的实际结果和对应的优化建议进行调优操作。具体的调优思路可以参考本次实践。
-
209.BASE 理论是指?基本可用、软状态、最终一致性210.CPU 个数为 3,CPU 核数为 2,CPU 的线程数为 4(支持超线程技术),vCPU 的个数是多少?答案: vCPU 个数 = 物理 CPU 个数* 物理 CPU 核数* 单核线程数=3* 2 *4=24
推荐直播
-
华为云码道 × 仓颉编程:工程化AI编码探索2026/05/27 周三 19:00-21:00
刘俊杰-华为云仓颉语言专家/李炎-华为云码道技术专家/王智鹏-OpenCangjie开源社区发起人
本场直播围绕华为云仓颉语言与华为云码道的深度结合,展示华为云智能编程从零基础到高效落地的完整生态能力。以华为云码道为引擎,仓颉语言为载体,带给大家日常提效、趣味创新到极速量产的开发体验。
回顾中
热门标签