最近一个月没啥更新,身边发生太多事,毕业几年来霉运太多,虽然不信命,但我信有些人命的确好,有些人命的确差,其它不说也罢。(大家一定要注意身体啊,健康比任何东西都重要)
本文要监控的这个脚本,是在一个月前左右,对于线上redis中项指令操作需要进行统计分析时写的一个工具:
一.需求
由于是其于client的分布式缓存,需要知道每个结点,当前每秒所处理的指令有哪些,主要集中在哪些操作,哪些操作过多,可以进行优化等.基于这些需求,需要知道现在线上每个redis结点下有哪些操作。
二.背景
redis-monitor指令可以导出当前redis结点所有操作的二进制文件(此操作不建议常开,只是分析时用,对redis结点有性能影响)。
其中业界使用比较多的redis-live,此监控还基于图形化的方式部署,中间我也 部署过,安装的东西很多,一堆流程,而且我们不需要这么详细的监控,只是一个分析帮助工具,所以太笨重了,其也是基于redis-monitor的脚本分析来进行监控的。
三.工具
考虑到我们只是需要对redis-monitor所导出的二进制文件进行一些统计,因此这样就相对比较简单了,java,shell脚本都可以实现,当然如果要做shell是首选。
可是考虑到shell对处理文本的局限性,因此考虑使用python来实现(解析性语言,总体感觉是,简单,易用,还不需要像java那样烦锁的打包,发布等!)
四.主要流程
要对redis的执行指令进行统计主要分两步:
一.redis-monitor对应的输出进行重定向,统计某一段时间段的redis指令情况,保存为某个文件。
二.使用python对上面保存的monitor指令集进行处理,并输出统计结果。
shell脚本如下:
##此shell脚本用于获取指定的redis结点的monitor指令的监控信息。保存在db.txt文件中
#运行时执行脚本即可,可指定执行时间,如./monitor.sh 5s,如不指定,则默认执行2S
#!/bin/bash
lineno=1
cmd=/home/hmail/etc/redis/bin/redis-cli
host=xx.xx.xx.xx
port=xx
file=db.txt
time=$1
if [ -z $time ];then
time=2s
fi
echo "$cmd -h $host -p $port monitor run time $time "
`$cmd -h $host -p $port monitor > $file &`
sleep $time
pid=`ps aux | grep "monitor" | grep "redis-cli" | awk '{print $2}'`
echo "will kill redis monitor pid:$pid"
`kill -9 $pid`
echo "redis-cli monitor stopped"
对上面保存的db.txt文件进行处理的python脚本如下:
#coding=utf8
#此监控脚本为基于读取到的redis monitor file统计对应的redis操作情况。
import commands, sys, os, time, string
#取time 精确到秒暂时
def getSeconds(time):
index = time.find(".")
return time[0:index]
#every same seconds ope
class SecondRecords:
allcount = 0
#"set:1"
table = {}
#init方法为了实例属性与类属性
def __init__(self, table, count):
self.table = table
self.allcount = count
def get(self):
return "all count:", self.allcount," ",self.table
def add(self, ope):
if(ope not in self.table.keys()):
self.table[ope] = 0
count = self.table[ope]
count = count + 1
self.table[ope] = count
self.allcount = self.allcount + 1;
def printResults(results):
for key in results.keys():
print key, '\t', results[key].get()
#判定是否指定时间
length = len(sys.argv)
period = None
if(length < 2):
#默认2s
period = "2"
else:
period = sys.argv[1]
cmd='./monitor.sh ' + str(period) #此monitor.sh为上面提到的shell脚本
#not result
os.system(cmd);
#wait period时间,等待采集数据
period = string.atol(period)
time.sleep(period)
#all monitor records
results = {}
# read monitor file
f = open("db.txt")
#f = open("monitor.txt")
print "monitor per seconds ope:"
line = f.readline()
while line:
strs = line.split(" ")
#判断是否合格的字符
length = len(strs)
#去除非监控指令。
if(length < 2):
line = f.readline()
continue
time = getSeconds(strs[0])
if(time not in results.keys()):
results[time] = SecondRecords({}, 0)
results[time].add(strs[1])
line = f.readline()
#close
f.close();
print "monitor records:"
printResults(results)
如果系统中有python环境,直接执行python redis_monitor.py 即可(注意,shell脚本只是为了抓取重定向文件所用的,python脚本会执行此文件,同时监控多长时间的指令,在后面增加对应的参数即可)
五.说明
以上为整个监控脚本,运行,输出的结果如下:
通过上面图示,可以清晰的知道每个结点下每秒钟各条指令执行的数目情况,从而知道自己缓存对各个缓存的需求是多少,以及各个结点现在的性能是多少。
我们线上环境,每个结点平均每秒处理的redis指令在25000-30000左右的操作数左右(值得说明的是像一个multi-exec操作算两次操作,中间如果有批量提交,每个操作也算一次操作,这样实际业务场景中很有可能是某个业务逻辑会有多次的指令操作数,从而可以估算出相关缓存服务器性能等)
很多情况,我们在知道我们redis指令数后,会更加理解我们产品的业务逻辑,由怀疑redis的结点性能转化到优化相关逻辑上去。
希望对你有帮助。