突然收到告警,提示redis挂了,同时大群也在说某某redis连接超时了,过了一会儿就恢复了。这时登上服务器,查看监控。首先看看qps:
可以看到qps并不高,但是中间有段时间没取到数据是怎么回事?那么继续看看redis的cpu使用率:
可以看到cpu已经饱和,这也就能解释为何断图了,因为redis是单线程,在使用cpu 100%以后,就无法处理其他的命令了,zabbix也就无法执行info命令取qps了。那么已经知道是cpu使用饱和造成的问题,那么到底是什么原因呢?那么继续查看,cpu使用高的这段时间有没有慢日志:
好像也不是导致cpu高的凶手,这就难排查了,这个实例是1主1从。那么我看看从库的cpu使用情况看看:
卧槽,怎么回事,从库没有使用的怎么cpu也用到了74%?这不科学啊?管他的,看看从库有没有慢日志:
卧槽,怎么回事?从库没人使用啊。看看是否只读:
127.0.0.1:6103> CONFIG GET "slave-read-only" 1) "slave-read-only" 2) "yes" 127.0.0.1:6103>
看来是只读的,这把我给整懵了。最后突然想到是主库在这个点有big key过期,而主库过期key操作慢是不会记录慢日志的,从库的key过期是由主库发起DEL指令删除的。这时从库就会记录慢日志,从上面慢日志可以看到这些DEL操作最大的335ms,怪不得会有应用连接超时的。
总结:
redis由于的单线程,单个耗时过大命令,导致阻塞其他命令。key尽量的控制大小。那么key的过期最好是手动写脚本删除,比如删除大set键,使用sscan命令,每次扫描集合中500个元素,再用srem命令每次删除一个键。当然还可以合理的设置过期时间,设置过期时间不在业务的高峰期,业务高峰期一般每天都在同一时间,那么过期时间设置整数天+8个小时左右就是凌晨了,就避免了在业务高峰期过期。