Lettuce 返回已删除 ID
Redis 7 的 XAUTOCLAIM 删除 ID 数组曾被旧版 Lettuce JUSTID 解析为已领取消息。Lettuce 7.8.0 修复后,用 getMessages 与 getDeletedIds 分开处理。
Redis Stream 中的消息已经删除,Lettuce 调用 XAUTOCLAIM ... JUSTID 后,getMessages() 却仍返回那些 ID,消息正文为 null。在 Redis 7 及以后版本配合受影响的 Lettuce 客户端时,应检查客户端是否把响应中的“已删除 ID”误当成了领取结果。
这一解析问题在 Lettuce 7.8.0 已修复。6.4.2 和 7.7.0 有相应的问题表现;使用已修复版本时,还需根据实际响应区分真正领取的消息、被删除的消息和普通空结果。
区分领取与删除 ID
Redis 7 起,XAUTOCLAIM 回复包含三个部分:下一次扫描的游标、实际领取的消息,以及本次扫描发现已经没有正文、因而从 PEL 移除的 ID。
下面是形状示例:没有任何消息被领取,但有两个已删除 ID 被移除了待确认引用。
1) "0-0"
2) (empty array)
3) 1) "1787564443438-0"
2) "1787564443439-0"
旧版 Lettuce 的解析器依靠嵌套深度区分 ID,JUSTID 的领取数组和删除数组恰好处于同一层,于是第三部分也进入了 getMessages()。不用 JUSTID 时,第三部分则没有通过单独字段交给调用者。
不能只用“正文为 null”过滤。JUSTID 本来就只返回真正领取消息的 ID,不附正文;这些合法结果同样可以没有消息体。
升级后把两类 ID 分开处理
采用与项目兼容的 Lettuce 7.8.0 或包含修复的后续版本,按项目的依赖管理方式升级,保留原连接、编码器与消费参数。已核对的 7.9.0 实现也按回复所属部分分别解析。
修复后,getMessages() 只包含实际领取的消息,getDeletedIds() 单独给出被 Redis 移除的缺失消息 ID。Redis 7 以前没有第三个回复元素,对应删除列表为空。
领取结果进入正常的重试或业务处理流程;删除列表进入消息丢失、保留策略或处理记录核对流程。它不证明业务曾经成功,也不能凭 ID 恢复已经删除的正文。
继续用 getId() 返回的游标推进扫描。当前批次没有领取到消息,不代表扫描一定结束;只有游标与服务器回复才能说明这次遍历的位置。游标到 0-0 后,后续仍可能有消息达到最小空闲时间,需要按原有消费策略再次检查。
在隔离 Stream 检查结果
保留实际 Redis 与 Lettuce 版本、协议模式和回复形状。在隔离 Stream 中安排正常待确认消息及已删除的待确认消息,比较 JUSTID 与带正文的领取结果。
这类验证会改变消费组的所有权与 PEL。不要直接对生产任务执行零空闲时间的领取、删除或批量确认,来制造一份诊断结果;原有最小空闲时间、消费组身份和幂等约定仍要保留。
验收应确认已删除 ID 不再算作领取成功,正常领取 ID 没有被错误过滤,游标继续推进。若旧版曾产生错误统计,还应单独核对这些记录,升级不会自动撤回之前的业务判断。
需要回退依赖时保留应用修订与原兼容构建,但不能恢复按空正文过滤的错误逻辑。已经被删除的消息内容,也不会因为回退客户端而重新出现。


