必须先创建消费者组,否则xreadgroup直接报nogroup错误;这是redis stream的强制前提,因消费者组不会自动创建,需用xgroup create显式声明,且推荐带mkstream避免竞态。

必须先创建消费者组,否则 XREADGROUP 直接报 NOGROUP 错误——这不是配置问题,是 Redis Stream 的强制前提。
为什么 XREADGROUP 一用就报 NOGROUP
这个错误不是网络或权限导致的,而是因为 Redis Stream 的消费者组(Consumer Group)不会自动创建。哪怕 XADD 已经写入了消息,order_stream 这个 key 存在且有数据,XREADGROUP GROUP order_group consumer1 STREAMS order_stream > 依然会失败。
根本原因是:XREADGROUP 不负责建组,只负责读组;它要求组必须由 XGROUP CREATE 显式声明。
-
XGROUP CREATE order_stream order_group $ MKSTREAM:推荐带MKSTREAM,避免先查流是否存在再创建的竞态 -
$表示从最新消息开始消费(跳过历史),0表示从头开始;两者语义完全不同,选错会导致漏消息或重复处理 - 组名和流名大小写敏感,
OrderStream和orderstream是两个不同流
XREADGROUP 的阻塞与非阻塞行为怎么控制
默认不加 BLOCK 是非阻塞模式:没消息立刻返回空数组,适合轮询场景但浪费 CPU;加 BLOCK 后变成阻塞等待,更省资源,但要注意超时设置是否合理。
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
-
XREADGROUP GROUP g1 c1 BLOCK 5000 STREAMS mystream >:最多等 5 秒,期间有新消息就立即返回 -
BLOCK 0表示无限等待,生产环境慎用——万一消费者挂了,连接会一直 hang 住 - 多个流同时监听时,
STREAMS mystream otherstream > >,>必须一一对应,顺序不能错 - 如果用了
COUNT 1却长期没消息,BLOCK超时后仍返回空,不是 bug,是设计如此
如何用多个消费者实现“主从”式分发逻辑
所谓“主从”,实际是利用 Stream 消费者组的内置负载均衡机制:同一组内的不同消费者(如 master 和 slave)自动分摊消息,每条消息只会被组内一个消费者拿到。
- 启动两个进程,都执行
XREADGROUP GROUP mygroup master ...和XREADGROUP GROUP mygroup slave ...,它们会自动协商分配 ID 区间 - 消息一旦被某个消费者读出,就会进入该消费者的 PEL(Pending Entries List),其他消费者无法再读到它,直到被
XACK - 若
master崩溃未XACK,可用XPENDING查出卡住的消息,再用XCLAIM转移给slave继续处理 - 不要手动删消费者(
XGROUP DELCONSUMER),否则其 PEL 里未确认的消息会永久滞留
XACK 必须在业务成功后调用,且只能确认自己读到的消息
这是最容易被忽略的可靠性断点。不调 XACK,消息永远留在 PEL;调错了 ID 或跨消费者确认,Redis 会静默忽略(不报错)。
- 确认前务必校验消息 ID 是否属于当前消费者刚读出的那批,比如从
XREADGROUP返回的数组中取[0][0]字段 -
XACK mystream mygroup 1601372323627-0中的1601372323627-0必须严格匹配,多一个空格或少一位都会失败 - 批量确认时,
XACK mystream mygroup 1601372323627-0 1601372323627-1比逐条发更快,但任一 ID 错误整条命令无效 - PHP/Python 客户端封装常把
XACK写成可选,上线前一定要检查是否真被调用
真正难的不是语法,是消息生命周期管理:从 XADD 写入、XREADGROUP 分发、到 XACK 确认,中间任何一环掉链子,都会导致消息堆积或重复。尤其是消费者重启时,得靠 XPENDING + XCLAIM 主动捞回待处理消息,而不是依赖自动重试。










