问题描述:
最近做的项目用redis订阅了一个消息,消息的每秒都会发,在我程序运行了一晚上之后,第二天发现消息丢失了,看了日志发现平均2秒丢26条消息。
解决办法:
在网上找到了这个描述:来自https://blog.csdn.net/luyaoying001/article/details/80264347
使用Redis缓存行情数据,发现程序运行一段时间后,出现subscribe线程不再能够接收到订阅的行情数据,发现是由Redis的输出缓冲机制导致的。
Redis为了解决输出缓冲区消息大量堆积的隐患,设置了一些保护机制,主要采用两种限制措施:
- 大小限制,当某一客户端缓冲区超过设定值后直接关闭连接;
- 持续性限制,当某一客户端缓冲区持续一段时间占用过大空间时关闭连接。
对于Pub/Sub客户端(也就是发布/订阅模式),大小限制是8M,当输出缓冲区超过8M时,会关闭连接。持续性限制是,当客户端缓冲区大小持续60秒超过2M,则关闭客户端连接;
然后发现Redis的发布订阅是不可靠的,会存在数据丢失的问题。验证一下是不是上面这个原因,我去查看了日志,看了日志之后发现这个问题是在系统运行了7、8个小时后出现的,经查找发现做的定时删除没启动,从而造成数据量过大,在订阅事件的处理中,因为数据量过大,拖慢了处理订阅的消息时间,消息的处理时间超过了1秒。从而导致了消息的延迟,越推时间越长,导致缓冲区过大,最后数据丢失。
个人建议:如果订阅的消息接收时间间隔短并且数据量过大的情况下,还是不要用这种方式了,如果发布者发送消息过快,而且在这一时刻数据量很大,那么会存在数据丢失问题。
网上给了一种设置缓冲区大小的设置,可以参考一下。
- client-output-buffer-limit pubsub 32mb 8mb 60 #当缓冲区数据达到硬限制32M时,连接会关闭;当缓冲区数据达到软限制每60秒8M时,连接也会关闭。
- client-output-buffer-limit pubsub 0 0 0 #可将hard limit和soft limit同时置0,关闭该限制。该操作官方不推荐。