Redis Stream 做异步任务:先想清消费组和重试语义
Redis Stream 可以用来做轻量异步任务队列,适合独立服务或中等规模后台任务。但它不是把消息 XADD 进去就完事。消费组、Pending 列表、ACK、重试、死信都要设计清楚,否则任务失败后会悄悄堆积。
异步任务系统的核心不是投递,而是失败后还能被正确处理。
一、基本消费链路
flowchart TD
A[XADD Task] --> B[Stream]
B --> C[Consumer Group]
C --> D[Worker]
D --> E[XACK]
D --> F[Pending]
Worker 成功后 ACK,失败则留在 Pending。Pending 不处理,任务就会卡在那里。
二、创建 Stream 和消费组
XGROUP CREATE ai_jobs workers $ MKSTREAM
XADD ai_jobs * job_id 123 type summary
消费时使用 XREADGROUP。每个 worker 属于同一个 group,共同分担任务。
三、Pending 要定期扫描
XPENDING ai_jobs workers
如果某个 worker 挂了,它拿到但没 ACK 的消息会留在 Pending。需要用 XAUTOCLAIM 把超时消息转移给健康 worker。
XAUTOCLAIM ai_jobs workers worker-2 60000 0-0 COUNT 10
这一步不做,Redis Stream 就不是可靠队列,只是看起来像队列。
四、重试和死信要有上限
同一个任务失败太多次,就应该进入死信,而不是无限重试。
retry_policy:
max_attempts: 3
backoff: exponential
dead_letter_stream: ai_jobs_dlq
死信不是垃圾桶,而是人工排查入口。要记录失败原因和最后一次错误。
还要考虑消息幂等。Redis Stream 可能因为重试或认领让同一任务被执行多次。任务处理逻辑必须能识别重复。
CREATE TABLE job_result (
job_id VARCHAR(64) PRIMARY KEY,
status VARCHAR(32),
result_uri TEXT
);
写结果时用 job_id 做唯一键,已经完成的任务直接返回。这样重试不会生成两份结果。
五、总结
Redis Stream 可以做轻量异步任务队列,但要设计消费组、ACK、Pending 扫描、超时认领、重试和死信。
先想清失败语义,再选队列。否则任务不是执行了,而是丢在 Pending 里没人管。
Redis Stream 适合轻量任务,但如果需要复杂调度、延迟任务和更强事务语义,就要评估专门队列。工具要匹配问题,不要为了省组件把边界做模糊。
还要监控 Stream 长度、Pending 数和最老消息时间。队列系统最怕“还有消费”但其实已经落后很多。
stream_metrics:
stream_length
pending_count
oldest_pending_age
dead_letter_count
这些指标要有告警。否则任务堆积到用户投诉时,后台早就欠了一堆债。
如果任务有优先级,也不要把高低优先级混在同一个 Stream 里硬排队。可以拆 Stream,或者在消费者侧先处理高优先级任务。优先级策略越晚补,越容易影响已有消息语义。
1793

被折叠的 条评论
为什么被折叠?



