redis是一個單線模型的nosql類型的數據庫,而目前接觸到的服務器大都是多核的,比如8c,16c,32c,64c等等。為了充分利用主機,在一台主機上必然會部署多個redis實例,默認情況cpu會隨機選擇,但經過觀察自動選擇的時候很大情況下會選擇同一邏輯cpu,這樣導致cpu使用不均衡,撐得死了,餓的餓死了,怎么破。
其實可以對指定的進程id進行cpu綁定,綁定前的情況如下:
27001 instance bind on cpu 0-7 27002 instance bind on cpu 0-7 27003 instance bind on cpu 0-7 27004 instance bind on cpu 0-7 27005 instance bind on cpu 0-7 27007 instance bind on cpu 0-7 27008 instance bind on cpu 0-7
生成綁定的命令
ps aux|grep redis-server |grep -v grep |awk 'BEGIN {i=0}{i++}{print "taskset -pc " i, $2}'
綁定后的情況如下:
27001 instance bind on cpu 1 27002 instance bind on cpu 2 27003 instance bind on cpu 3 27004 instance bind on cpu 4 27005 instance bind on cpu 5 27007 instance bind on cpu 6 27008 instance bind on cpu 7
綁定后獲取cpu綁定情況的確認腳本如下:
ps -ef |grep redis-server |grep -v grep | awk '$NF~/cluster/{print $2,$(NF-1);next}{print $2,$NF}' > pid_instance cat pid_instance | while read line do pid=$(echo $line | awk '{print $1}') port=$(echo $line | awk -F':' '{print $2}') echo "$port instance bind on cpu `taskset -pc $pid | awk -F':' '{print $2}'`" done rm -rf pid_instance
如果有很多台redis實例,可以通過ansible分發該腳本到對應的主機上,然后跑一下sh redis_cpu.sh xxx腳本,xxx文件中是以all為分組的redis主機列表,例如:
cat >redis_cpu.sh <<EOF #!/bin/bash ansible -i $1 all -m copy -s -a "src=./get_redis_bind_cpu.sh dest=/tmp/get_redis_bind_cpu.sh" ansible -i $1 all -m shell -s -a "sh get_redis_bind_cpu.sh" EOF cat >get_redis_bind_cpu.sh <<EOF #!/bin/bash ps -ef |grep redis-server |grep -v grep | awk '$NF~/cluster/{print $2,$(NF-1);next}{print $2,$NF}' > pid_instance cat pid_instance | while read line do pid=$(echo $line | awk '{print $1}') port=$(echo $line | awk -F':' '{print $2}') echo "$port instance bind on cpu `taskset -pc $pid | awk -F':' '{print $2}'`" done rm -rf pid_instance EOF
添加一下輸出優化,直觀看出來是不是綁定了cpu
ps -ef |grep redis-server |grep -v grep | awk '$NF~/cluster/{print $2,$(NF-1);next}{print $2,$NF}' > pid_instance cat pid_instance | while read line do pid=$(echo $line | awk '{print $1}') port=$(echo $line | awk -F':' '{print $2}') bind_current=$(taskset -pc $pid | awk -F':' '{print $2}') total=$(cat /proc/cpuinfo |grep processor |wc -l) start=0 let end=total-1 bind_default="$start-$end" if [[ $bind_current -ne $bind_default ]];then echo "$port instance bind on cpu $bind_current ok" else echo "$port instance not set bind cpu default $bind_default,please check!!!" fi done rm -rf pid_instance
如果沒有綁定:
[root@testdb1 ~]# sh c.sh 6379 instance not set bind cpu default 0-23,please check!!! 29009 instance not set bind cpu default 0-23,please check!!! 29095 instance not set bind cpu default 0-23,please check!!! 27000 instance not set bind cpu default 0-23,please check!!! 27001 instance not set bind cpu default 0-23,please check!!! 29001 instance not set bind cpu default 0-23,please check!!! 29002 instance not set bind cpu default 0-23,please check!!! 29003 instance not set bind cpu default 0-23,please check!!! 29004 instance not set bind cpu default 0-23,please check!!! 29005 instance not set bind cpu default 0-23,please check!!! 29006 instance not set bind cpu default 0-23,please check!!! 29007 instance not set bind cpu default 0-23,please check!!! 29008 instance not set bind cpu default 0-23,please check!!! 29000 instance not set bind cpu default 0-23,please check!!!
如果有綁定
27183 instance bind on cpu 1 ok 27184 instance bind on cpu 2 ok 27185 instance bind on cpu 3 ok 27186 instance bind on cpu 4 ok 27187 instance bind on cpu 5 ok 27188 instance bind on cpu 6 ok 27189 instance bind on cpu 7 ok 27190 instance bind on cpu 8 ok 27191 instance bind on cpu 9 ok 27192 instance bind on cpu 10 ok 27193 instance bind on cpu 11 ok 27194 instance bind on cpu 11 ok 27195 instance bind on cpu 10 ok 27196 instance bind on cpu 9 ok 27197 instance bind on cpu 8 ok
@20190509
cat >get_redis_bind_cpu.sh <<EOF #!/bin/bash ps -ef |grep redis-server |grep -v grep | awk '\$NF~/cluster/{print \$2,\$(NF-1);next}{print \$2,\$NF}' > pid_instance cat pid_instance | while read line do pid=\$(echo \$line | awk '{print \$1}') port=\$(echo \$line | awk -F':' '{print \$2}') bind_current=\$(taskset -pc \$pid | awk -F':' '{print \$2}') total=\$(cat /proc/cpuinfo |grep processor |wc -l) start=0 let end=total-1 bind_default="\$start-\$end" if [[ \$bind_current -ne \$bind_default ]];then echo "\$port instance bind on cpu \$bind_current ok" else echo "\$port instance not set bind cpu default \$bind_default,please check!!!" >> no_bind.log fi done rm -rf pid_instance EOF cat >redis_cpu.sh <<EOF #!/bin/bash ansible -i \$1 all -m copy -s -a "src=./get_redis_bind_cpu.sh dest=/tmp/get_redis_bind_cpu.sh" > /dev/null ansible -i \$1 all -m shell -s -a "cd /tmp;sh get_redis_bind_cpu.sh" > /dev/null ansible -i \$1 all -m shell -s -a "ls -l /tmp/no_bind.log 2>/dev/null" EOF PS: 1.執行前確保ansible到目標所有redis實例的機器可以跑通。 2.執行sh redis_cpu.sh redis_host |grep -v FAILED 3.有輸出的即是對應主機上redis實例存在沒有綁定cpu的,具體實例端口在對應機器的/tmp/no_bind.log