问题
线上已经运行很久的一个 Redis (阿里云64节点集群版)经常会报 CPU 偏高,经确认后发现只有 13 节点 CPU 偏高,且是其他节点的 3 倍以上,即大部分节点的 CPU 占用率在 20% 到 30%,QPS 大约是 7000,问题节点的 CPU 占用率超过 80%,QPS 是 27000。
排查问题
初次定位
我们首先怀疑是大 key 问题引起的,于是使用 monitor 命令在业务低峰时进行了 monitor,发现某个 类型为 hash 的 key 拆分了100片,每个 hash 的长度大约是 30 万。我们观察了这 100 个 key,在每个节点分布的比较均匀,不应该引起如此严重的偏移问题。
所以结论是该节点的 CPU 偏高不是由于大 key 问题引起的。
再次排查
通过阿里云的 imonitor 命令,我对指定的节点进行了监听,并将结果保存为文本文件进行分析。
用 telnet 命令连接到阿里云的 Redis Server Cluster,在 telnet 中执行
imonitor 13
将结果保存为 redis-13.txt
。
对结果进行分析
cat redis-13.txt | grep -o -E "1561806\d+" | sort | uniq -c
结果为
可以看出该节点的 QPS 大概为 7000 多,远不及监控上的 27000。
因此,我们确定是阿里云的监控上对应的节点和 imonitor 的节点不对应。
发现这个问题后,我们尝试用 iinfo 命令找出来 CPU 比较高的节点。
#遍历每个节点
for i in {0..63}
do
redis-cli -h $host -a iinfo $i CPU
done
通过该方法找到 5 节点的 CPU 显著高于其他节点。
再次使用 imonitor 命令获取该节点的 QPS:
cat redis-5.txt | grep -o -E "1561807\d+" | sort | uniq -c
QPS 为 28000 左右,符合监控曲线。
然后我们通过使用 redis-faina 分析 Monitor 的结果。
首先要对结果进行处理,将 imonitor 接收到的每行开头的 "+" 号去掉,执行命令
sed -i "" "s/+//g" redis-5.txt
然后使用 redis-faina 分析结果,执行命令
python redis-faina.py redis-5.txt
得出来访问量较高的命令,发现有一个 hget
命令的 key 和 field 明显写反了,且 QPS 很高,正是这个 key 导致了 CPU 和 miss 曲线的升高。
我们在代码库中查找出问题的 key,逐行排查,发现在一个项目中确实存在 key field 写反的情况,于是通知了开发者进行修改。
第二天开发者修改了代码并进行了发布之后,曾经偏高的 CPU 节点稳定如他,问题终于算得到了解决。
结论
- imonitor 命令和阿里云后台的监控的节点不一致,导致问题迟迟未被发现(阿里云反馈仅在早期的 Redis 集群中有该现象,新版的 Redis 集群都是对应的)。
- 使用 imonitor 和 redis-faina 一起,可以方便地排查 redis 大 key 和热 key。
- 具体问题要具体分析,不能解决问题的时候要变通思路,通过各种方法去尝试解决问题。
本文首发于本人博客 记一次解决线上 Redis 集群单节点 CPU 偏高问题,非本人授权请勿转载。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。