面试题答案
一键面试消息分配
- 概念:Redis Stream 消费组(Consumer Group)是一组消费者的集合,用于共同处理 Stream 中的消息。在消费组内,Redis 采用了一种类似队列的方式来分配消息,以确保每个消息只会被组内的一个消费者处理。
- 分配方式 - 基于游标:消费组使用
XREADGROUP
命令来读取消息。每个消费组有一个内部的游标,称为last delivered ID
。当一个消费者从消费组读取消息时,Redis 会从游标位置开始分配消息给该消费者。例如,消费者 A 执行XREADGROUP GROUP mygroup myconsumer COUNT 10 STREAMS mystream >
,这里的>
表示从当前消费组的游标位置开始读取,Redis 会从该位置取出 10 条消息分配给消费者 A。如果没有新消息,会阻塞等待新消息到来(可通过设置BLOCK
选项控制阻塞时间)。
消息确认
- 概念:消息确认机制用于告知 Redis 消息已经被成功处理,以便 Redis 可以将其从待处理队列中移除。
- 确认命令 - XACK:消费者在成功处理消息后,使用
XACK
命令来确认消息。例如,消费者处理完消息后执行XACK mystream mygroup <message_id>
,其中message_id
是已处理消息的 ID。Redis 接收到XACK
命令后,会将该消息标记为已确认,并从消费组的待处理队列(Pending Entries List,PEL)中移除。
故障恢复
- 消费者故障:如果一个消费者在处理消息过程中发生故障,它所领取但未确认的消息不会丢失。这些消息会保留在消费组的 PEL 中。当故障消费者恢复后,它可以通过
XREADGROUP
命令的RETRYCOUNT
选项再次获取这些未确认的消息(XREADGROUP GROUP mygroup myconsumer COUNT 10 STREAMS mystream 0
,这里0
表示从 PEL 中获取未确认消息)。其他消费者也可以通过执行XCLAIM
命令,将故障消费者未确认的消息转移到自己名下进行处理。例如,消费者 B 执行XCLAIM mystream mygroup myconsumer2 0 <min_idle_time> <message_id>
,其中myconsumer2
是当前消费者名称,<min_idle_time>
表示消息在 PEL 中闲置的最小时间,满足此条件的消息会被转移给消费者 B。 - Redis 实例故障:如果 Redis 实例发生故障,重启后消费组的状态会恢复。Redis 会将之前未确认的消息重新放入 PEL 中,等待消费者重新处理。这是因为 Redis 会将 Stream 和消费组的相关元数据持久化到磁盘(通过 RDB 或 AOF 方式),重启时可以恢复到故障前的状态。