*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 调用即可扫描后续消息。