likes
comments
collection
share

听《Node服务线上故障》分享的思考

作者站长头像
站长
· 阅读数 17

有任何问题都可以留言咨询。

思考1

写入量很大,导致redis的rdb持久化异常

一开始排查到问题,是访问Redis返回时长较长。

然后看到应用服务的报错信息:

MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.

再查看redis组件的日志:

can't save in background: fork: cannot allocate memory

说明是bgsave出错了,无法申请到内存。

思考

文章不易,请关注公众号 毛毛虫的小小蜡笔,多多支持,谢谢。

1、bgsave vs save

save直接调用rdbSave函数,阻塞redis主进程,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求。

如果数据量小,用此命令可能感觉不出有什么区别,但是当数据量很大的时候,就需要谨慎使用这个命令。

bgsave命令执行之后立即返回OK ,然后redis fork出一个新子进程,原来的redis 进程(父进程)继续处理客户端请求,而子进程则负责将数据保存到磁盘,然后退出。

2、rdb的缺点

1、如果您需要在 Redis 停止工作时(例如断电后)将数据丢失的可能性降到最低,那么 RDB 并不好。您可以配置生成 RDB 的不同保存点(例如,在对数据集至少 5 分钟和 100 次写入之后,您可以有多个保存点)。但是,您通常会每五分钟或更长时间创建一个 RDB 快照,因此,如果 Redis 由于任何原因在没有正确关闭的情况下停止工作,您应该准备好丢失最新分钟的数据。

2、RDB 需要经常 fork() 以便使用子进程在磁盘上持久化。如果数据集很大,fork() 可能会很耗时,并且如果数据集很大并且 CPU 性能不是很好,可能会导致 Redis 停止为客户端服务几毫秒甚至一秒钟。AOF 也需要 fork() 但频率较低,您可以调整要重写日志的频率,而不需要对持久性进行任何权衡。

思考2

是什么导致了redis故障?

显而易见的原因

故障发生的前几日客户调用量激增,由原本平均每日100万调用量激增至每日300-400万调用量。

激增的调用量使得redis短时间写入量增大,触发rdb持久化。

进程阻塞降低了redis服务性能。

思考

1、异步问题

在消费消息后,必须紧接着把消息pop掉,不然会有问题。

消费消息的代码insertDetail是异步的,一般情况下,应该是数据量比较少的情况下,执行很快,所以能顺利pop掉数据。

但如果数据量很大,那就很容易出现问题了。异步代码在写入数据,结果还没执行完,就把数据pop掉了。

如果此时写入失败,就会导致数据丢失。