首先执行XPENDING mystream mygroup查看pending总数及消费者分布,若某消费者占99%则基本失联;再用XPENDING mystream mygroup - + 10查idle和delivery-count,idle超阈值或delivery-count>1表明卡死;接着用XINFO CONSUMERS确认消费者是否存活并检查idle值;最后用XCLAIM将idle超时的消息转交健康消费者,消费逻辑须幂等。

查 pending 消息总数和分布
消费者挂掉后,消息会滞留在 Pending Entries List(PEL)里,但 Redis 不会主动报警。第一反应不是翻日志,而是直连 Redis 执行 XPENDING mystream mygroup。它返回四行:待处理总数、最小 ID、最大 ID、各消费者持有量。如果某个消费者(比如 c1)占了 99% 的 pending 数,基本就能锁定它已失联。
看每条 pending 消息的 idle 时间和投递次数
用带范围的 XPENDING mystream mygroup - + 10 查最近 10 条 pending 消息详情。重点关注两个字段:idle(毫秒)和 delivery-count。如果 idle 超过你设定的超时阈值(比如 5 分钟 = 300000),说明这条消息卡在消费者手里很久没动;delivery-count > 1 表示已被重试过,大概率是消费者崩溃或卡死。
确认消费者是否还在活跃状态
Redis 本身不维护消费者“心跳”,但你可以间接验证:
- 用 XINFO CONSUMERS mystream mygroup 看当前注册的消费者列表,检查 c1 是否还在其中
- 如果还在,再查它的 idle 字段(该命令输出含此列)——若数值极大,说明它没发任何新请求,只是“挂着”没退出
- 若已不在列表中,但 pending 消息仍归属它,就是典型的进程被 kill 后未清理残留状态
用 XCLAIM 把卡住的消息转交给健康消费者
别等原消费者复活,直接接管:
- 执行 XCLAIM mystream mygroup c2 300000 1729543210000-0,把 ID 为 1729543210000-0 的消息转给 c2,且只认领 idle > 300000ms 的消息
- 生产环境建议写个定时脚本,定期扫 XPENDING ... IDLE 600000 并批量 XCLAIM,避免人工干预延迟
- 注意:转交后原消费者若突然恢复,可能重复处理同一消息,消费逻辑必须幂等
真实故障里最麻烦的不是发现堆积,而是误判“是不是真挂了”。比如消费者线程卡在慢 SQL 或第三方 HTTP 请求上,XINFO CONSUMERS 显示它还在线,但 idle 已飙升到几小时——这种静默卡死,光看连接状态根本看不出来。











