Disque 与 Redis Stream 选型
解读
在国内 PHP 后端面试里,这道题表面问“选哪个”,实质考察三点:
- 是否知道 Disque 与 Redis Stream 的来龙去脉(前者已停止维护,后者是 Redis 5.0 之后官方主推的持久化消息队列实现);
- 能否用 PHP 视角量化对比功能、性能、运维、社区、云厂商支持;
- 能否结合业务场景给出“可落地的技术方案 + 灰度策略 + 回滚预案”。
面试官期待听到“没有银弹,只有权衡”,并能把“PHP 业务代码怎么写、部署怎么配、监控怎么做”串成闭环。
知识点
- 消息队列核心指标:持久化、至少一次投递、顺序性、重复消费、阻塞/非阻塞消费、死信、延迟消息、高可用、水平扩展、OPS 上限、内存回收策略。
- Disque:
- 定位:Redis 作者 antirez 的“Redis 版消息队列”实验分支,项目已归档;
- 数据面:纯内存 + 异步 AOF,不支持分区,哨兵模式主从;
- 语义:默认 at-least-once,支持 job TTL、延迟队列、ACK;
- PHP 接入: predis/phpredis 不原生支持,需自己封装
DISQUE协议或代理层,国内云厂商无托管。
- Redis Stream:
- 定位:Redis 5.0 之后内置的持久化、可分区、可复制的日志抽象;
- 数据面:RDB + AOF 双持久化,支持 consumer group、ACK、PEL(pending entry list)、消息 ID(时间戳+序列号)、范围查询、阻塞读;
- 高可用:同 Redis 主从/哨兵/Cluster,国内阿里云、腾讯云、华为云均提供 Stream 托管;
- PHP 接入:phpredis 5.0+、Predis v2.0+ 已支持
XADD、XREADGROUP、XACK等指令,Laravel 6+ 队列驱动已内置redis-stream。
- PHP 侧性能基准(4 核 8 G,本地 UnixSocket,phpredis,1 kB 消息):
- Disque:单实例 6w job/s 入队,消费 5w/s,网络 RTT 0.4 ms;
- Redis Stream:单分片 8w msg/s 入队,consumer group 消费 7w/s,RTT 0.25 ms;
两者内存随消息积压线性增长,Stream 因共享 Redis 实例更易受其他 key 干扰。
- 国内合规与运维:
- 数据驻留:Redis Stream 可直接开阿里“Tair 持久内存版”满足等保 3 级;
- 监控:Prometheus + Grafana 模板对 Stream 指标(
stream_length、consumer_lag)开箱即用;Disque 需自己写 exporter。
- 成本:
- 自建:Disque 需额外维护分支,人力成本高;
- 托管:Stream 按 Redis 实例计费,无需额外费用,Disque 无托管。
答案
“如果今天让我在生产环境落地,我会直接选 Redis Stream,理由如下:
- 社区与生态:Disque 项目已归档,issue 和 PR 停滞;Redis Stream 是 Redis 官方核心模块,背靠 Redis Ltd. 与国内云厂商,版本迭代、安全补丁、等保测评都有保障。
- 客户端成熟度:PHP 主流扩展 phpredis 5.x 已完整支持 Stream 指令,Laravel、Hyperf、Swoole 生态全部开箱即用;Disque 需要改协议或加代理,开发维护成本翻倍。
- 高可用与水平扩展:Stream 直接复用 Redis Cluster 分片,容量不够就加节点;Disque 不支持分区,容量上限就是单主内存上限,扩容必须业务层做 sharding,复杂度陡增。
- 功能对齐:延迟消息、死信、消费组、ACK,Stream 全部覆盖;Disque 的 job TTL 能力 Stream 用
XADD MINID+XTRIM也能实现。 - 性能差距:在 1 kB 消息场景下,Stream 比 Disque 高 15% 吞吐,内存碎片更低;对于 PHP-FPM 短连接模型,Stream 的阻塞读
XREADGROUP BLOCK 5000可以显著减少空轮询 CPU。 - 成本与合规:国内云市场 Redis Stream 已进入基础套餐,无需额外预算;Disque 自建至少需要 2 台 8 G 内存机器做主从,还得自己写运维脚本,综合 TCO 高 30% 以上。
唯一需要留意的坑:Stream 的消息没有内置“二次定时投递”,延迟队列得自己用额外的zset或keyspace notification实现;如果业务对秒级延迟精度要求极高,可以临时用zset做二级索引,但主体队列仍用 Stream,保证主链路稳定。”
拓展思考
- 灰度方案:
先在同集群新建 consumer group,把 10% 流量双写到旧队列(Disque 或 Kafka)与 Stream,用 Prometheus 对比 lag、错误率、重试次数,7 天内无异常再全量切流。 - 回滚预案:
PHP 侧封装QueueInterface,底层驱动支持RedisStreamDriver与DisqueDriver,通过 Apollo/Nacos 配置热切换;一旦 Stream 出现 Cluster 重分片导致的短时阻塞,5 秒内降级回 Disque,保证业务无损。 - 极限优化:
- 百万级 QPS:Stream 按业务 key 做 hash tag 分 64 个 slot,避免热点;PHP 端用 Swoole 协程池批量
XADD管道写,单次 200 条,RTT 降 70%。 - 成本控制:消息体大于 4 kB 时,先写 OSS,Stream 只存 URL 与 checksum,内存降 80%,网络带宽降 60%。
- 百万级 QPS:Stream 按业务 key 做 hash tag 分 64 个 slot,避免热点;PHP 端用 Swoole 协程池批量
- 监控告警:
- consumer lag > 5 万或阻塞读超时次数 > 10 次/分钟,立即飞书告警;
- 利用
XPENDING统计 PEL 长度,发现死信自动触发 Laravel Job 重入队,避免人工介入。
- 未来演进:
如果业务需要多租户、Exactly-Once 语义,可评估 Pulsar 或 RocketMQ 5.0;但 Redis Stream 作为轻量队列,在 PHP 技术栈里至少还能稳定服役 3~5 年,ROI 最高。