现网程序运行一段时间后,经常发现收不到redis订阅消息。输入client list查询redis连接信息,输出如下信息:
其中两个关键字段 idle=563 连接空闲563s,按理说不可能空闲,因为对端在不停发消息。继续查看 omem=12734654,输入缓冲区内存占用竟然达到12G。服务器内存被耗尽,不再向客户端发布消息。
看看redis.conf配置项:
client-output-buffer-limit pubsub 32mb 8mb 60 #当缓冲区数据达到硬限制32M时,连接会关闭;当缓冲区数据达到软限制每60秒8M时,连接也会关闭。 client-output-buffer-limit pubsub 0 0 0 #可将hard limit和soft limit同时置0,关闭该限制。该操作官方不推荐。
经排查发现上述问题是由于关闭了订阅/发布输出缓冲区内存限制,程序操作阻塞,没有及时取走发布的消息,导致消息在服务端不断缓存,最终耗尽服务端内存,客户端无法接收到订阅消息。
解决方案: 将订阅消息读取到本地队列中,防止阻塞订阅消息的读取;单独启动一线程扫描队列消息即可。