记一次线上Redis故障恢复和分析(一)

起因

那天早上一到公司就有客服过来反应我们的App登录不了了,我赶紧试了一下登陆App,发现是可以登录的,就以为是个别现象没有在意。过了一会儿客服来反应更频繁了,这才意识到可能没有那么简单。

分析

一开始认为是服务器问题,检查了所有相关的应用服务器,应用是否正在运行,发现一切正常,cpu、内存、IO 都是正常的,没有异常;

然后考虑是否是代码层面问题(数据库问题被排除,因为一旦数据库出问题不可能只有一部分人受影响),于是去检查日志,发现有以下错误信息:

错误信息

然后登陆redis控制台,一台一台测试,终于发现了有问题的那台机器:

发现问题

接下来要做的就很简单了,redis是集群部署,并且每个节点都有master-slave,因此直接kill该节点,问题修复,一切正常。

寻找根本原因

但是这样做并不能解决根本问题,由于之前部署redis集群时考虑不够周全,没有配置redis日志,因此决定直接修改配置文件,逐个重启redis节点。这也就导致了再次故障,因为那个故障节点又被启动加入集群并且由于所有节点都经历了重启该节点又被设为master了。

这时去观察该节点redis的日志,终于发现了问题,满屏都是异常信息:

Can’t save in background: fork: Cannot allocate memory

通过Google得知是由于机器内存不足导致的,遂检查机器内存,发现内存已被占用超过90%,于是赶紧增大机器内存,毕竟redis 数据都是存储在内存中,才能做到这么快的读写。

基于此,对整个redis集群的内存占用情况进行了一次排查,增大了机器内存,并且增加了对机器内存使用情况的监控防止再出现此类情况。

又一个问题

好景不长,一个问题解决又来一个问题,对于redis操作出现了非预期结果,类似 incrBy +1 结果+2,执行expire 结果返回失败。

该问题的跟踪解决将在下一篇文章中介绍。