*Redis XAUTOCLAIM 命令

XAUTOCLAIM 用于自动扫描并将超时的 pending 消息转移给新的消费者,提供类似 SCAN 的流式消息重投递机制。


*语法

XAUTOCLAIM key group consumer min-idle-time start [COUNT count] [JUSTID]

*参数说明

参数 类型 必填 说明
key String Stream 键名
group String 消费组名称
consumer String 目标消费者名称
min-idle-time Integer 消息最小空闲时间(毫秒)
start String 扫描起始 ID,首次调用用 0-0
COUNT count Integer 每次最多扫描数,默认 100
JUSTID Flag 仅返回 ID 数组,不返回消息内容

*返回值

  • Array:包含三个元素
    • cursor:下次调用的起始 ID(完成时返回 0-0
    • claimed entries:成功认领的消息数组(XRANGE 格式)
    • deleted ids:已在 Stream 中被删除的消息 ID 数组(Redis 7.0+)
  • Error:参数错误、key 不存在、组不存在等

*时间复杂度

O(1)(当 COUNT 较小时)。


*示例

*基本用法

> XADD mystream * field value
"1609338752495-0"
> XGROUP CREATE mystream mygroup 0
OK
> XREADGROUP GROUP mygroup Alice COUNT 1 STREAMS mystream >
1) 1) "mystream"
   2) 1) 1) "1609338752495-0"
      2) 1) "field"
         2) "value"
# 1 小时后 Alice 未确认,Bob 尝试认领
> XAUTOCLAIM mystream mygroup Bob 3600000 0-0 COUNT 25
1) "0-0"
2) 1) 1) "1609338752495-0"
   2) 1) "field"
      2) "value"
3) (empty array)

*仅返回 ID(JUSTID)

> XAUTOCLAIM mystream mygroup Bob 3600000 0-0 JUSTID
1) "0-0"
2) 1) "1609338752495-0"
3) (empty array)

*游标迭代扫描

> XAUTOCLAIM mystream mygroup Charlie 60000 0-0 COUNT 10
1) "1610000000000-0"
2) 1) 1) "1609338752495-0"
   2) 1) "field"
      2) "value"
3) (empty array)
# 继续扫描
> XAUTOCLAIM mystream mygroup Charlie 60000 1610000000000-0 COUNT 10
1) "0-0"
2) (empty array)
3) (empty array)

*常见错误

错误 原因 解决
NOGROUP 消费组不存在 先创建消费组
ERR wrong number of arguments 缺少必填参数 检查 key/group/consumer/min-idle-time/start
min-idle-time 为负数 参数非法 传入非负整数

*最佳实践

  • 定时任务中周期性调用 XAUTOCLAIM,推荐间隔等于或略大于 min-idle-time
  • 首次调用 start 设为 0-0,后续使用返回值中的 cursor
  • 即使 cursor 返回 0-0,仍可继续调用以处理新满足条件的消息
  • 消费者崩溃恢复后,先调用 XAUTOCLAIM 再开始 XREADGROUP,避免重复消费
  • 使用 JUSTID 可降低网络开销,但注意 retry counter 不会递增

*FAQ

Q1: XAUTOCLAIM 和 XCLAIM 有什么区别? A: XAUTOCLAIM 自动扫描 PEL 中满足条件的消息并批量认领;XCLAIM 需要显式指定消息 ID。XAUTOCLAIM 更适合定时重平衡和故障恢复场景。

Q2: COUNT 参数有什么限制? A: COUNT 是尝试认领的上限,实际扫描上限为 COUNT * 10(硬编码)。返回的消息数可能小于 COUNT,因为部分消息可能不满足 idle 条件或已被删除。

Q3: 为什么返回的 claimed entries 为空但 cursor 不是 0-0? A: 说明当前批次中没有满足 min-idle-time 的消息,继续用该 cursor 调用即可扫描后续消息。