先看现象。用 redis 7.2 的 list 做任务队列,LPUSH 生产 BRPOP 消费,监控显示积压从 200 涨到两万,消费进程没退出、CPU 也很低,日志停在半小时前的同一条记录。
这类报错背后常见的原因有几处,逐个排除就行。BRPOP 超时设成 0 后连接被中间层静默断开。还有一种是消费循环里异常被吞掉,线程卡在重试同一任务。
少数情况下是连接池耗尽,新连接一直排队。
不容易想到的是,阻塞命令占满了单线程客户端的读缓冲。
先看队列长度与消费者在线数
redis-cli llen task:queue; redis-cli client list | grep -c cmd=brpop
然后查阻塞连接的空闲时长
redis-cli client list | awk '{print $2, $8}' | head -10
给阻塞读取加显式超时并重连
python -c "import redis;r=redis.Redis();print(r.brpop('task:queue',timeout=5))"
末了把消费异常写进死信队列而不是吞掉
redis-cli lpush task:dead '[{"id":1,"err":"timeout"}]'
改完先别撤,确认这几项。积压条数持续下降并回到个位,消费者心跳正常,死信队列里能看到被拦下的异常任务。
BRPOP 设 0 看着省事,实际会被负载均衡和防火墙悄悄掐断,加超时是成本最低的保命手段。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。
