背景
线上redis部署的是三主三集群,昨天中午,线上各服务接连告警,提示服务已下线,过一段时间又上线了(springboot-admin+企业微信服务下线、上线告警),赶紧放下手中外卖排查。
排查
1. 查看各服务的错误日志,发现是redis集群挂了。
2. 查看redis集群状态,发现是正常的,使用命令cluster nodes查看集群状态,发现集群是正常的,但是有一个之前的主机,变成了备机,之前的备机变成主机了。
3. 查看redis日志,发现是主备之间数据同步可能存在问题,但后来日志又正常,应该是主备自动切换就正常了。
原因分析
刚开始也不知道怎么分析原因,redis集群之间走的内网,一般来说网络问题的可能性不大,看了下那个阶段各服务器节点的内存、cpu、带宽之类的,也比较正常,一时也不知道什么原因。
直到在网上看到这篇文章 关于Redis集群故障的分析-php教程-PHP中文网,猜测我们的redis集群主备切换是不是也是因为使用了keys *类似的慢语句。
使用slowlog get命令查看我们redis慢查询日志,果然是这个原因。
slowlog日志显示的参数解释如下:
1) (integer) 8 》该条慢日志的唯一编号
2) (integer) 1676551515 》该命令执行时的时间戳
3) (integer) 1081610 》该命令执行的总耗时,单位为微秒。1秒=1000毫秒,1毫秒=1000微秒
4) 1) "keys" 》命令和命令的参数
2) "*"
5) "127.0.0.1:41978" 》发起该命令的客户端的ip和端口号
6) "" 》客户端的名称
可以发现,我们的命令虽然不是keys *,是keys _____*,但是每个命令执行时间也需要0.6秒,由于redis是单线程执行命令的,1秒钟才能执行2个不到的命令,公司并发是比较高的,并发高了,redis性能完全跟不上,从而导致redis集群主从切换了。
改进
1. 让对应业务部门立即停用这种处理方式,换一种其他实现方式,强调代码规范。
2. 在生产环境禁用redis 的keys命令,可参考