Redis Pub/Sub 不适合作为可靠分布式任务调度,因其无持久化、无ACK、无重试、不支持消息堆积与消费者组,仅适用于允许丢失的广播通知;应改用 Redis List(LPUSH/BRPOP)或 Streams(含ACK、消费者组、重试)。

不能直接用 Redis Pub/Sub 实现可靠的分布式任务调度。它缺少任务确认、重试、持久化和消费者状态跟踪等核心能力,只适合轻量、允许丢失的广播通知场景。
为什么 Pub/Sub 不适合作为任务队列
Redis 的 PUBSUB 是纯内存、无持久化的消息通道:发布者一发即忘,订阅者离线期间消息完全丢失;没有 ACK 机制,无法保证 Worker 真正执行成功;也没有消息堆积能力,高峰期消息直接被丢弃。
-
SUBSCRIBE连接断开后,未接收的消息不可恢复 - 多个 Worker 同时
SUBSCRIBE同一个 channel,消息会被广播给所有节点(不是负载均衡) - 没有内置的延迟、重试、死信处理逻辑
-
PUBLISH返回值仅表示“是否成功推送到 channel”,不反映消费结果
想用 Redis 做任务调度,该换什么方案
用 LPUSH + BRPOP(或 RPOPLPUSH)搭配 SET 锁或 Redis Streams 更靠谱。前者是经典队列模式,后者支持消费者组、ACK 和消息重传:
- 用
XADD task-stream * job "{\"id\":\"123\",\"type\":\"send_email\"}"写入流 - Worker 通过
XREADGROUP GROUP mygroup worker1 COUNT 1 STREAMS task-stream >拉取未分配任务 - 执行完必须调用
XACK task-stream mygroup <id>,否则消息会留在XPENDING中可重发 - 注意设置
XGROUP CREATE时的MKSTREAM参数,避免流不存在时报错
如果坚持用 Pub/Sub 触发 Worker,只能当“唤醒信号”
把 Pub/Sub 当成轻量事件总线:比如配置变更、缓存刷新、日志采集开关等不需要强一致性的动作。真正的任务数据仍走可靠队列(如 Redis List / Stream 或 Kafka)。
- 发布端发
PUBLISH trigger:reload_config "now" - Worker 订阅
SUBSCRIBE trigger:reload_config,收到后主动从config:version这个GETkey 拉取最新配置 - 绝不把任务参数 JSON 直接塞进
PUBLISHpayload——长度受限(默认 512MB 但实际网络/客户端有更严限制),且无法追溯 - 用
CLIENT SETNAME给订阅连接命名,便于运维时CLIENT LIST查看活跃 Worker
真正做分布式调度时,最容易被忽略的是“任务幂等性设计”和“消费者崩溃后的消息归属判断”——Pub/Sub 根本不提供任何上下文,这两点得全靠业务层兜底。


















