不适合。redis pub/sub是纯广播模型,所有订阅者均收到同一条消息,无法保证“一个任务只被一个消费者执行”,既无ack机制、无持久化、不支持消费者组与积压缓冲,也不具备任务队列的基本语义;可靠异步任务应选用lpush+brpop或stream+xreadgroup。

不适合。 Redis Pub/Sub 是纯广播模型,所有订阅者都会收到同一条消息,无法保证“一个任务只被一个消费者执行”,这不是任务分发,是重复执行——轻则浪费资源,重则引发数据错乱。
为什么 SUBSCRIBE 不能当任务队列用
很多人误以为启动多个 worker 执行 SUBSCRIBE task_channel 就能自动实现负载均衡,但实际行为完全相反:
-
PUBLISH task_channel {"id":"1001","action":"send_email"}发出去后,所有已连接的 worker 都会立刻收到完整副本 - 没有 ACK 机制,你无法知道哪个 worker 真正处理成功,也无法重试失败任务
- worker 断开连接期间的消息直接丢失,
SUBSCRIBE不保存历史,也不支持重放 -
PUBSUB NUMSUB task_channel只返回当前在线订阅数,它不参与任何路由决策
真正适合任务分发的 Redis 方案
要让“一个任务只被一个消费者取走”,必须依赖原子出队能力。Redis 提供两种成熟路径:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- 用
LPUSH+BRPOP:生产者LPUSH task_queue {"job":"..."},每个 worker 执行BRPOP task_queue 0;Redis 保证并发下只有一个 client 拿到该元素 - 用
Stream+XREADGROUP:写入用XADD task-stream * {"job":"..."},消费用XREADGROUP GROUP mygroup worker1 COUNT 1 STREAMS task-stream >,处理完必须调用XACK,否则消息保留在XPENDING中可重试
二者都支持消费者组、失败重入队(业务层控制)、消息堆积,而 Pub/Sub 连最基本的任务语义都不具备。
Pub/Sub 唯一能“触发”任务的合理方式
如果你确实想保留 Pub/Sub 的低延迟特性,只能把它当“唤醒信号”,而非任务载体:
- 发布端只发轻量指令,比如
PUBLISH trigger:reload_cache "now" - worker 收到后,主动去读取真实任务数据,例如从
GET cache_config_v2拉配置,或从LRANGE pending_jobs 0 0取任务 - 绝不把任务参数 JSON 直接塞进
PUBLISHpayload——长度受限、不可追溯、无法重试
这个模式绕开了 Redis 的设计边界,增加了客户端协调逻辑和时钟/网络容错负担,稳定性远低于原生命令。真要调度任务,别硬凑 Pub/Sub。










