List 队列与 Stream 的分工
用 List 做队列的核心是 LPUSH 或 RPUSH 入队、BRPOP 或 LMOVE 出队,简洁高效但没有消费确认与重试语义;需要消费组、消息确认、按 ID 回溯、多播时应当用 Stream。选择标准是「消息丢了能不能接受」:不能接受就要么自建可靠机制,要么直接用 Stream 或专业消息队列。
对比与选型
| 维度 | List 队列 | Stream |
|---|---|---|
| 消费组 | 无,多个消费者靠竞争弹出 | XGROUP 原生支持消费组 |
| 消息确认 | 无,需用 LMOVE 自建处理中队列 | XACK 与 PEL 提供确认与重投 |
| 回溯 | 不支持,弹出即消失 | 可按 ID 范围重读历史消息 |
| 内存控制 | 靠 LTRIM 手工裁剪 | MAXLEN 近似裁剪 |
| 复杂度 | 极简,几行命令即可 | 功能完整但运维与理解成本更高 |
| 适用 | 内部低频任务、可容忍丢失 | 需要可靠投递或多样消费的场景 |
最小队列实现
最小队列实现
RPUSH q:jobs job1 job2 job3 # 生产者:尾部入队
BRPOP q:jobs 5 # 消费者:阻塞 5 秒取出,超时返回空
LLEN q:jobs # 积压监控:队列长度
LMOVE q:jobs q:processing LEFT RIGHT # 可靠队列:取出后先落到处理中队列
LREM q:processing 1 "job1" # 处理成功后从处理中队列移除
LTRIM q:jobs 0 9999 # 用 LTRIM 控制长度,避免无限增长典型使用场景
- 内部低频任务分发:发邮件、生成报表等可容忍重试的场景
- 削峰缓冲:突发写入先入队,由消费者按能力取走
- 轻量任务队列:不想引入外部组件的单体应用
- 可靠队列变体:用 LMOVE 移到处理中队列,崩溃后可人工回捞
- 积压监控:用 LLEN 与耗时指标判断消费能力是否不足
并发量上千、需要确认与重试的作业系统应选 Stream 或专业 MQ:用 List 补齐这套机制往往比直接换方案代价更高。
队列键没有长度上限,生产者突发流量会把内存吃光;上线前必须明确最大积压量并配置裁剪与告警。
运维注意事项
- 积压告警要同时看队列长度与单条处理耗时两个维度
- 直接用 DEL 清理队列会丢任务,优先通过消费者排空或转投死信队列
- 消费者数量与积压量要匹配,过多消费者只是空转占用连接