当前位置:首页 > 文章列表 > 数据库 > Redis > Redis Stream 消费组怎样使用 NOACK

Redis Stream 消费组怎样使用 NOACK

来源:17golang原创 2026-10-15 00:54:23 0浏览 收藏

Redis Stream 消费组在 XREADGROUP 中加上 NOACK,可以让本次读取的新消息不进入 Pending Entries List(PEL)。典型写法是 XREADGROUP GROUP 组名 消费者名 COUNT 100 NOACK STREAMS 流名 >。代价是:它把读取视作已确认,不等业务处理完成;消费者随后失败时,这些消息没有该组的 Pending 记录可供接管。

如果只是允许偶发缺失的实时展示,我会考虑它;如果是必须补偿的订单处理,我会保留普通消费与成功后的 XACK。这里用一个假设的实时展示任务解释选择,不声称亲历了故障或完成了压测。

官方命令地址:https://redis.io/docs/latest/commands/xreadgroup/

我会先把处理成功单独计数

假设有一个活动看板,把消息交给多个消费者做短时展示。旧消息很快失去展示价值,但是否允许丢失仍然需要业务明确决定。我不会先问“能快多少”,而会先区分三个数量:消费端收到多少条、业务真正完成多少条、组内还有多少条 Pending。

NOACK 最容易造成的误判,是 Pending 变成零后就认为任务全部成功。对我而言,零 Pending 只说明没有相应待确认记录,不等于每条消息的业务动作已完成。测量基线应保留业务成功计数,而不是只保留 Redis 返回数量。

计数观察对象不能代替什么
读取条数客户端实际收到的消息业务完成条数
成功条数业务动作完成的消息 ID全部曾读取的消息
Pending 条数PEL 中的待确认记录NOACK 模式下的失败条数

NOACK 省下的是待确认记录

普通消费组会跟踪已投递但未确认的消息,业务成功后用 XACK 移除相应 PEL 记录。NOACK 则跳过新消息的这份待确认记录。因此它改变的是确认与恢复约定,不是把业务处理变成 Redis 内部的原子操作。

在这个区别里,我会把 Stream 消息本体、PEL 与业务处理结果分开看。NOACK 不是删除 Stream 条目的命令;即便消息仍在 Stream 中,也不代表业务知道哪些已成功、哪些需要重做。保留的条目可以按 ID 范围查询,另做重放则需要自己定义范围、完成记录和去重规则,不能当作 Pending 接管的等价替代。

有关确认职责可参照官方 XACK 说明:https://redis.io/docs/latest/commands/xack/;原始条目的范围查询见:https://redis.io/docs/latest/commands/xrange/。

Stream 消息本体、消费组、PEL 与 NOACK 的静态关系
图1:确认记录结构图。普通读取对应 PEL 记录,NOACK 不为新读取消息建立这份记录;两种方式都不代表业务成功。不是数据库截图或运行结果。

把 NOACK 放到新消息读取中

下面是 shell 中的命令片段,假设流与组已经存在。注意把 > 引起来,避免 shell 将它当作输出重定向。

# 读取该组尚未投递的新消息,最多等待 1000 毫秒;不建立新消息的 PEL 记录
redis-cli XREADGROUP GROUP display_group worker_a COUNT 100 BLOCK 1000 NOACK STREAMS display_events '>'

GROUP 后面依次是组名和消费者名;组内不同工作实例应使用不同消费者名。COUNT 是每条流的数量上限,并不是必须凑满的批量大小。BLOCK 控制无可读消息时的等待,1000 的单位是毫秒,不是业务处理超时。

这里没有使用 CLAIM 扩展,> 表示读取该组尚未投递的新消息。若改用 0 或其他具体 ID,含义变成读取当前消费者已有的 Pending;此时 NOACK 与 BLOCK 被忽略。不要靠 NOACK STREAMS 流名 0 清空历史待确认记录。以上范围以官方 XREADGROUP 规则为准。

用两个组比较同一批消息

下面的示例供读者在独立测试实例执行,未在本机运行。前提是 demo:noack:events 这个键此前不存在,没有其他生产者、消费者或裁剪操作;两个组使用相同起点,从而能分别消费同样的两条消息。固定 ID 只用于教学,不表示真实生成时间。

# 创建两个独立组;起点 0 允许读取从头保留的消息,MKSTREAM 创建空流
redis-cli XGROUP CREATE demo:noack:events fast_group 0 MKSTREAM
redis-cli XGROUP CREATE demo:noack:events tracked_group 0

# 在新建的空流中写入两条示例事件,固定 ID 便于后续引用
redis-cli XADD demo:noack:events 1-0 event_key screen_a value 17
redis-cli XADD demo:noack:events 2-0 event_key screen_b value 29

# 同一批消息由不同组分别读取;fast_group 不建立 Pending
redis-cli XREADGROUP GROUP fast_group fast_a COUNT 2 NOACK STREAMS demo:noack:events '>'
redis-cli XREADGROUP GROUP tracked_group tracked_a COUNT 2 STREAMS demo:noack:events '>'

# 比较各组 Pending,并单独查看仍保留的消息本体
redis-cli XPENDING demo:noack:events fast_group
redis-cli XPENDING demo:noack:events tracked_group
redis-cli XRANGE demo:noack:events - + COUNT 2

# 仅当对应业务处理成功时,普通消费组才确认这些 ID
redis-cli XACK demo:noack:events tracked_group 1-0 2-0

按命令语义预期,两个读取都可得到两条事件;fast_group 的 Pending 数量为 0,tracked_group 在确认前为 2。两条原始消息仍可通过 XRANGE 查询;最后的 XACK 移除普通组的待确认记录。这些是基于前提的预期,不是实测输出,也不是吞吐基准。

普通组最后的 XACK 演示确认动作的位置,不能照抄到业务失败分支。示例对象留在测试实例中,不自动清理其他键。若创建时返回 BUSYGROUP,说明组已存在,应停止并换未使用的测试对象,不能继续拿旧组状态作对照。

组起点与创建行为参照:https://redis.io/docs/latest/commands/xgroup-create/;Pending 查询参照:https://redis.io/docs/latest/commands/xpending/。

性能收益要和缺失代价一起量

少维护一份记录、少一次确认动作,可能减少开销,但我不会由此直接写出“性能提升一倍”。普通消费也可以批量 XACK,网络、业务耗时和批量大小都可能掩盖差异。真正的对比需要相同消息内容、消费者数量、并发、网络条件与持久化设置。

如果由我安排实验,会使用两轮隔离负载:一轮普通读取并在业务成功后批量确认,一轮 NOACK。每轮固定消息数量,记录相同观测窗口;除了读取速率,还要记录业务成功速率、端到端 P95 延迟、客户端和 Redis CPU,以及按实际成功 ID 计算的缺失情况。

指标普通读取+确认NOACK
业务成功条数/秒需实测需实测
端到端 P95 延迟需实测需实测
CPU 与资源开销需实测需实测
读取后进程退出的未完成 ID观察 Pending 与恢复结果观察业务缺失与外部补偿

故障实验也只应在测试环境进行:让消费者读取后、业务完成前退出,再比较未完成消息的可定位性。普通组虽然保留 Pending,仍要实现接管、重试和业务幂等;NOACK 则没有这些新消息的 PEL 依据。我的判断会同时看速度变化和缺失是否符合约定,而不是只挑吞吐好看的数字。

读取计数、成功计数、Pending 计数与业务 ID 的职责关系
图2:观测指标结构图。读取数量和业务成功数量必须分开记录,Pending 不能替代成功计数;图中没有性能数值,也不暗示已完成压测。

需要补偿时我会保留确认机制

对临时展示、允许明确范围内缺失的非关键数据,NOACK 可以是一个简化选择。但如果处理失败必须知道“哪一条没完成”,我会保留 PEL 与显式确认。业务要求不能因为 Pending 看起来更干净而被悄悄改变。

切换选项还要记住:NOACK 是本次读取的选择,不是永久关闭消费组的确认能力。之前积累的 Pending 不会被它自动清掉;后续不带 NOACK 的新消息仍按普通确认约定处理。混用前必须让监控能识别哪些消息采用了哪种处理策略。

常见问题

NOACK 的消息还需要 XACK 吗?对于该方式新读取且未加入 PEL 的消息,不需要用 XACK 移除不存在的记录;业务成功仍应自行记录。

Pending 为零能说明没有失败吗?不能。尤其在 NOACK 下,它没有收集这批消息的业务失败情况。

消息仍在 Stream 里,为什么不能直接补偿?原始事件不等于完成状态。重放前还需确定缺失范围与去重约定,不能把所有历史事件无差别重复处理。

我的取舍是:先明确可容忍的缺失,再衡量省下的开销。NOACK 解决的是“不需要维护待确认记录”,不是“可靠消费无需确认”。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
MySQL 只读事务怎样减少误写风险MySQL 只读事务怎样减少误写风险
上一篇
MySQL 只读事务怎样减少误写风险
Redis XAUTOCLAIM 怎样只取消息 ID 做恢复
下一篇
Redis XAUTOCLAIM 怎样只取消息 ID 做恢复
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    474次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    532次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    552次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    505次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    324次使用