redis streams消费者组负载均衡依赖xack确认和pending状态,非心跳机制;漏xack或处理慢会导致负载倾斜与消息堆积;创建组需按需选起始位置(0或$);xpending用于监控pending分布;xack必须逐条及时执行;count和block参数需匹配处理能力。

Redis Streams 的消费者组负载均衡是自动发生的,但前提是每个消费者必须稳定完成“读 → 处理 → XACK”闭环。它不是靠心跳或注册机制驱动的,而是依赖消息确认状态和 pending 列表的实时反馈。一旦某个环节卡住,比如漏掉 XACK 或处理过慢,整个组就会迅速退化为单点消费或消息堆积。
消费者组创建要选对起始位置
新消费者收不到旧消息,不是因为负载不均,而是因为默认从最新消息($)开始消费。如果需要补读积压数据:
- 首次建组且需处理全部历史消息:用 XGROUP CREATE mystream mygroup 0
- 只关注实时流:用 XGROUP CREATE mystream mygroup $(推荐默认)
- 已有组新增消费者并想补读:必须显式调用 XREADGROUP GROUP mygroup newconsumer STREAMS mystream 0,但要注意这会干扰 pending 状态,建议仅用于初始化阶段
消息分发靠 pending 状态,不是连接数
Redis 不看消费者进程是否在线,只通过 XPENDING 中每条消息的 idle 时间判断是否“卡住”。只要一个消费者没及时 XACK,它的 pending 消息就会越积越多,其他消费者反而拿不到新任务。
- 用 XPENDING mystream mygroup 查整体 pending 分布,重点关注各 consumer 的 pending 数量和 idle 值
- idle 长期 > 30s,说明处理慢或没调 XACK;pending 数相差 5 倍以上,基本就是负载倾斜了
- 不要只数消费者数量——两个消费者,一个 pending 100 条、一个 pending 0 条,等于没负载均衡
每次处理完立刻 XACK,别攒批
重复消费和消息堆积的根源几乎全是 XACK 调用不当。Redis 不会自动标记消息为已处理,必须由业务代码显式确认。
- 成功处理一条,就立刻执行 XACK mystream mygroup
- 禁止批量处理完再统一 XACK——中间任意一步崩溃,整批都会重发
- 消费者宕机后,未确认消息保留在 pending 列表,默认 60 秒后可被其他消费者用 XCLAIM 接管,但这不替代及时 XACK
COUNT 和 BLOCK 要匹配实际处理能力
拉取消息的参数直接影响负载是否平滑。设得太大,单次处理太久,idle 累积;太小,频繁轮询浪费资源。
- 普通业务:COUNT 10~50 + BLOCK 5000(5 秒),兼顾吞吐与响应
- 低频事件(如人工审核通知):COUNT 1 + BLOCK 30000(30 秒)
- 避免 BLOCK 0——连接会永久挂起,调试时极易卡死
- BLOCK 超时返回空数组,不是错误,代码里要判断 len(result) == 0,而不是抛异常











