研究报告 · 约 22,456 字 · 预计推送 3 部分

Redis 使用边界:缓存、队列、锁、限流、发布订阅分别适合什么场景 未开始

目录

题记与说明

本文由同日两份章节报告综合而成:纵轴章节(发展脉络)与横轴章节(横向对比),撰写日 2026-10-31。两份章节的全部关键事实均来自当日网络检索与官方文档直接读取(WebSearch / webReader / WebFetch),未依赖纯模型记忆;无法核实出处的厂商宣称与社区报告均已标注口径。两章节之间的事实冲突(如 Valkey 分叉基线版本、Valkey 9.0 特性清单)已在综合时以官方来源为准合并为更精确的表述,并在正文相应处就地注明(见纵轴第五节 Valkey 分叉基线一处)。撰写时 Redis 最新稳定版为 8.10.2(2026-09-17 发布,见 Wikipedia: Redis)。

TL;DR

Redis 的五种经典用法(缓存、队列、锁、限流、发布订阅)不是设计出来的,而是从 2009 年的内存 list 结构里"长"出来的民间 hack。十七年里每种用法都经历同一螺旋:社区拼命令造模式 → 生产事故与理论质疑 → 官方用新原语(Lua、SET NX PX、Streams、Sharded Pub/Sub)收编 → 新共识。2026 年的边界已收敛:缓存与限流是主场;队列是甜点区,且内部分三档:任务队列 List/BullMQ → 要 ACK/回溯/中等保留升 Streams(不离开 Redis)→ 长保留/日亿级/绝对不丢才出走 Kafka/RabbitMQ;锁与发布订阅边界最硬——锁只用于效率型互斥,正确性场景换 etcd/ZooKeeper,Pub/Sub 是 at-most-once,不许丢消息就换 Streams/NATS JetStream/MQTT。判断式一句:先问数据丢失或双主的代价,再问延迟收益,代价高就出 Redis。Valkey 分叉后模式与产品已分离:学模式,绑产品要谈许可。


纵轴:发展脉络——民间 hack、官方收编与理论划界的十七年

"Redis 使用边界"这个课题的实质,是一部民间 hack 如何被官方收编、被理论质疑、再被内建原语修正的历史。五种用法不是先后添加的功能,而是同一套原子命令在不同人手里的不同读法;而"边界"不是写进文档的静态条款,而是一条螺旋线在每一年的切面。

第一阶段(2009–2012):用法先于边界——五个模式的蛮荒起源

2009 年 2 月 26 日,意大利程序员 Salvatore Sanfilippo(网名 antirez)发布 Redis。项目源于他为自家初创公司 LLOOGG 做实时网页访问日志分析:传统数据库撑不住"每秒追加 + 实时聚合"的负载,他先用 Tcl 写概念原型,再用 C 重写,实现的第一个数据类型是 list——也就是说,Redis 生命中第一个"用法"就是今天队列模式的雏形(Wikipedia: Redis)。antirez 把它开源发布到 Hacker News 后迅速在 Ruby 社区走红,GitHub 和 Instagram 是最早的用户。从第一天起,Redis 就同时扮演三个角色:实时数据缓冲区(缓存的近亲)、追加型 list 队列、以及被 antirez 称为 "data structure server" 的新型数据库。

本阶段的特征:五种用法全部可用,但边界无人讨论,每种用法都埋着后来爆雷的种子。驱动因素是 NoSQL 浪潮、Rails 生态爆炸与云计算早期对"轻量共享状态"的需求。

第二阶段(2012–2015):官方收编——从民间 hack 到文档模式

转折点是原子性基石。2012 年 10 月 Redis 2.6.0 引入 Lua 脚本与毫秒级过期 PX;2013 年 3 月 2.6.12 让 SET 直接支持 NX/XX/EX/PX——SET lock_key unique_value NX PX 30000 从此成为单命令加锁的标准姿势,埋葬了两步 SETNX+EXPIRE。2013 年的 Redis 2.8 带来 keyspace notifications,"缓存失效通知""过期事件驱动任务"第一次有了官方通道,把 pub/sub 与缓存两条线缝合起来(Keyspace notifications)。

同期背景:2015 年 4 月 Redis 3.0 发布 Cluster(Wikipedia);2015 年 6 月 Redis Labs 接替 Pivotal 赞助 Redis(antirez.com/news/81)。生产事故倒逼模式文档化,antirez 亲自下场写"官方模式"页面。

第三阶段(2016–2018):理论清算——边界第一次被系统性质疑

世纪之争:Kleppmann vs antirez(2016)。 2016 年 2 月 8 日,《DDIA》作者 Martin Kleppmann 发表《How to do distributed locking》公开炮轰 Redlock:它既不是"效率锁"(出错多等一下无妨)也不是"正确锁"(用于守护正确性);依赖各节点时钟的假设在异步系统里站不住;GC 停顿或时钟跳变会让旧持有者继续写入脏数据;而 Redlock 无法生成单调递增的 fencing token,无法让存储层拒绝过期持有者的写入——正确性场景应改用 ZooKeeper/etcd(martin.kleppmann.com)。次日 antirez 回击《Is Redlock safe?》逐点反驳(antirez.com/news/101)。争论没有裁判宣判,但深刻改变了行业认知——"锁分两种:只求效率的可以用 Redis,关乎正确性的请用专用协调服务"自此成为社区默认边界,这也是本课题史上最重要的一次边界划定。

修成正果:Streams(2018)。 2018 年 10 月 Redis 5.0 引入十年间公认的最重要的全新核心数据类型 Streams:append-only 日志 + 消费组 + XACK 确认 + pending entries 崩溃恢复(Redis 5.0 is here!)。官方明确将 Streams 定位为对"用 List 或 Pub/Sub 凑合"的替代:list 队列没有消费组、不能回溯;pub/sub 是 fire-and-forget,掉线的订阅者直接丢消息。队列和发布订阅两条线的边界至此重画:要求不丢消息的用 Streams,允许丢失、只要低延迟广播的才用 pub/sub。

缓存与限流同步深耕:2017 年 Redis 4.0 GA 带来 LFU 淘汰策略(承认"频率比新近度更符合缓存规律")、Modules 系统与 LAZYFREE(Hacker News 讨论);2018 年 Brandur 把 GCRA 做成 Rust 编写的 Redis 模块 redis-cell,一条 CL.THROTTLE 原子完成限流(brandur/redis-cell)。驱动因素:DDIA 出版与 Jepsen 测试让分布式理论大众化;云托管 Redis 让正确性焦虑上升;云厂商白嫖开源引发许可警觉——2018 年 8 月 Redis 模块改用 Apache 2.0 + Commons Clause,2019 年 2 月换成 RSALv2(Wikipedia)。

第四阶段(2019–2023):平台化时代——官方接管边界叙事

2020 年 4 月 Redis 6.0 GA,antirez 称其为"史上最大版本":ACL、RESP3、多线程 I/O,以及客户端缓存——数据变更时服务端主动推送失效消息,让客户端本地缓存保持一致(redis.io blog: Redis 6.0 GA;antirez.com/news/130)。当"缓存之王"开始帮你在客户端再做一层缓存,说明缓存场景已卷到极致。同年 6 月 30 日 antirez 发表《The end of the Redis adventure》正式退位(antirez.com/news/133;The Register 报道)——个人英雄时代结束,边界叙事从此由公司接管。

2022 年 4 月 Redis 7.0 GA:Functions 取代手管 Lua 脚本,让限流/锁等原子模式可随库部署、版本化管理;对本课题更重要的是 Sharded Pub/Sub——普通 pub/sub 在集群模式下要向所有节点广播,扩展性差;分片 pub/sub(SSUBSCRIBE/SPUBLISH)按 key 的 slot 分配 channel,消息只在本分片传播(redis.io pub/sub 文档)。pub/sub 的"大集群广播风暴"边界问题被官方原语正面修复。 驱动因素:企业级用户(银行、电商)把 Redis 用在远超最初设想的位置,官方被迫把每种用法都做成"可以放心买"的企业功能。

第五阶段(2024–2026):分叉与回归——边界之外的战争

第六阶段:2026 年的边界共识

十七年轮回后,五种用法的边界已基本收敛(对上述史实的归纳,属社区共识性判断):

用法适合不适合 / 边界红线
缓存读多写少、可容忍回源、需要 LRU/LFU 淘汰与 TTL;6.0 起还能下推到客户端缓存把唯一数据副本放进来;要求强一致的读
队列轻量任务队列(List/BRPOP 或 Resque/Sidekiq/BullMQ 类库);需要消费组、ACK、回溯时用 Streams(5.0+)海量堆积、严格事务/顺序/幂等语义、审计级不丢消息——交给 Kafka/RabbitMQ
锁效率型互斥(防止重复工作):SET NX PX + 随机令牌 + Lua 释放正确性关键路径(资金、库存扣减):时钟假设与无 fencing token 的缺陷意味着应选 ZooKeeper/etcd
限流固定窗口(INCR+EXPIRE)、滑动窗口(ZSET)、GCRA(redis-cell 或手写 Lua)跨大集群的全球精确配额、计费级精确性——需中心化账本或专用限流服务
发布订阅低延迟、可容忍丢失的实时广播;大集群用 7.0 sharded pub/sub任何"不能丢"的消息——pub/sub 是 fire-and-forget,掉线即丢,须改用 Streams 或 MQ

贯穿全程的规律:Redis 的每一次边界修正都遵循同一条路径——社区 hack → 生产事故/理论质疑 → 官方原语收编 → 新共识。list 队列催生 Streams,SETNX 竞态催生 Lua 与 SET NX PX,pub/sub 丢消息催生 Streams 与 sharded pub/sub,Redlock 之争催生"效率锁/正确性锁"二分法,INCR 限流的粗糙催生 redis-cell 与原生 GCRA 提案。


横轴:横向对比——2026-10-31 时间截面上的生态位

(许可风波与版本史已在纵轴交代,本节只把它作为选型前提引用,不再重复时间线。)

研究对象与竞品的三类划分

Redis 在 2026 年的官方定位早已不是"缓存",而是"实时数据平台":内存数据结构服务器,附带 JSON、时间序列、概率结构、向量检索等 Stack 级能力。因此它的"竞品"必须拆成三类,单一对比表会把问题搅浑:

类别成员竞争关系本质
A. 同构竞品(内存 KV)Valkey、Memcached、Dragonfly、KeyDB、Microsoft Garnet抢同一份"内存 KV"工作负载
B. 异构替代(各场景的专业工具)队列:Kafka、RabbitMQ、NATS JetStream、云 SQS;锁:etcd、ZooKeeper、数据库约束;限流:nginx limit_req、Envoy RLS、云 API 网关;发布订阅:NATS、MQTT、Kafka在单一场景上用"专门的正确性/规模"换 Redis 的"顺手"
C. 托管形态AWS ElastiCache、GCP Memorystore、Redis Cloud、Upstash决定"谁替你运维它"以及计费模型

当下格局:许可证风波尘埃落定后的三个阵营

小结:Redis 不再独占"开源内存 KV"心智,但依然独占"功能全 + 生态最厚"的位置。Valkey 是协议级平替(尤其对云厂商客户),Memcached 是极简缓存的守护者,Dragonfly/Garnet 是性能特化选项。

总对比表(2026-10-31 时间截面)

维度Redis 8.xValkey 9.xMemcachedDragonflyKafkaRabbitMQetcd/ZooKeeperNATS Core/JetStreamMQTT Broker
定位多面手数据结构服务器Redis 协议平替纯缓存多线程内存 KV分布式事件日志消息代理共识协调/锁轻量 pub/sub(可选持久)IoT 消息总线
许可AGPLv3/RSAL/SSPL 三选一BSD-3BSD-3BSL→Apache-2.0(已转)Apache-2.0MPL-2.0Apache-2.0Apache-2.0各家不一
持久化RDB/AOF 可选同 Redis无可选快照/AOF强(log)强强(WAL+快照)Core 无 / JetStream 有视 broker
投递语义Pub/Sub 至多一次;Streams 至少一次同 Redis——至少一次(可幂等近精确一次)可靠投递+复杂路由串行化保证(CP)Core 至多一次 / JetStream 至少一次QoS 0/1/2 可选
运维重量低~中低~中极低低~中高中中~高(3/5 节点共识)低(单二进制)低~中
生态/客户端最厚直接复用 Redis 客户端极厚但极简复用 Redis/Memcached 客户端最厚(流生态)厚成熟增长快IoT 域成熟
一句话边界什么都能干、强保证要掂量要 BSD/云厂商支持时的 Redis只做缓存时更快更省大核多线程时换它不丢、要回放、海量扇出复杂路由+任务队列锁的正确性兜底Redis Pub/Sub 的升级位IoT/离线设备

五大场景逐项对比

缓存:Redis vs Memcached vs 本地缓存 vs Dragonfly

维度RedisMemcached本地缓存(Caffeine/Guava)Dragonfly
数据类型String/Hash/Set/ZSet/Stream 等丰富结构仅字符串对象(进程内)兼容 Redis 常用命令
线程模型命令执行单线程(6+ 有 I/O 线程)原生多线程进程内零网络thread-per-core
持久化/复制有无无(进程重启即失)有(可选)
适合结构化缓存、排行榜、会话、计数小 value、超高读吞吐、不求持久亚微秒级热点读大核机器上的超大规模缓存

要点:Memcached 在"小而简单、纯读放大"的负载上吞吐强、行为可预期,AWS 官方对比页明确把"简单 KV 缓存"留给它(AWS: Redis vs Memcached);但缓存里一旦出现 ZSet 排行榜、Hash 会话、原子计数、击穿保护(SET NX 互斥重建),Memcached 无力承担——这是 Redis 缓存份额远超 Memcached 的主因。本地缓存不是竞品是互补:Redis 自身网络往返(约 0.2~1ms)就是"每请求都打 Redis"架构的新瓶颈,业界标准做法是进程内 L1 + Redis L2 多级缓存——这是 Redis 的物理边界。Valkey 在缓存场景与 Redis 基本无差别,选它通常是商业/许可决定而非技术决定。

场景结论:缓存是 Redis 最安全的主场,但"纯字符串 + 极高吞吐"可换 Memcached,"百万级 QPS 少节点"可试 Dragonfly,"每请求都要读缓存"必须加本地 L1。

本文不展开的相邻课题:缓存与数据库的一致性(cache-aside 回源、延迟双删、基于 binlog 的 CDC 失效同步)以及穿透/雪崩/击穿的成套防护(空值缓存、布隆过滤器、TTL 随机化;击穿互斥仅在本文缓存要点与速查表中带过)各自都是独立课题,边界结论另需专门研究,本文只回答"缓存这个角色该不该交给 Redis"。方向上一句话:默认 cache-aside + TTL,强一致的失效同步走 binlog/CDC 通道——6.0 的 client-side caching 与 2.8 的 keyspace notifications 是官方为这类方案预留的钩子(见纵轴第二、四阶段),但完整方案仍需应用层自行设计。

队列:Redis(Lists/Streams/BullMQ)vs Kafka vs RabbitMQ vs NATS JetStream

维度Redis ListsRedis StreamsBullMQ/SidekiqKafkaRabbitMQNATS JetStream
抽象简单阻塞队列日志 + 消费组应用层作业队列分区日志交换机/队列路由流式 pub/sub
ACK/重试无(BRPOP 取走即丢)XACK + XAUTOCLAIM内置重试/退避/死信offset 提交per-message ack消费者 ack
回放不可能可以(按 ID + XTRIM)不适用核心能力不支持支持
堆积容忍受内存限制受内存限制(需 XTRIM)依赖 Redis 内存磁盘,TB 级常态磁盘文件流
延迟最低(亚毫秒)极低低十毫秒级典型毫秒级极低
运维已有 Redis 即零增量同左同左重中轻

要点:Lists 是陷阱区——LPUSH+BRPOP 没有任何确认机制,worker 崩溃即丢任务,只适合"丢了无所谓"的轻量任务,这是最常见的 Redis 越界使用,而修复的第一站是升 Streams,不是直接换 MQ。作业队列(发邮件、转码、回调重试)是甜点区:BullMQ(bullmq.io)与 Sidekiq/Resque 用 Redis 实现了重试、退避、优先级、限速、仪表盘。官方文档对 Streams 的推荐场景就是"需要更强投递保证时从 Pub/Sub 升级",同时诚实承认其与 Kafka 的差距在"海量扇出 + 长保留 + 严格有序分区"(Redis Streams 教程)。至此,Redis 队列的升级路径是清晰的三档阶梯:List/BullMQ 甜点区 → Streams(要 ACK/回溯/中等保留,不离开 Redis)→ Kafka/RabbitMQ/NATS JetStream(长保留/大消息/绝对不丢/日亿级)。什么时候必须离开 Redis(第三档):消息需要天级以上的长保留回放(Streams 能按 ID 回放,但数据在内存里,XTRIM 掉即不可回溯,撑不住长保留)、单一主题每天数亿条以上、消费者要与主题解耦扩容、消息体积大(≈1MB 级)、或"绝对不能因 Redis OOM 丢事件"——满足任一条,选 Kafka(记录)或 RabbitMQ(路由),NATS JetStream 是"比 Kafka 轻、比 Redis Pub/Sub 稳"的中间带。一条社区经验法则:"要路由用 RabbitMQ,要大规模记录用 Kafka,中等规模又不想加运维用 Redis Streams。"

场景结论:Redis 适合"低价值快任务 + 已有 Redis + 中等规模"三条件同时成立;任一条件松动,先升 Streams/BullMQ 这一档——要 ACK、回溯、中等保留,仍在 Redis 内;只有长保留回放、日亿级、大消息、绝对不丢这类第三档信号出现,才升级到 Streams 之外的专门 MQ。

锁:Redis SET NX vs Redlock vs etcd/ZooKeeper vs 数据库

维度单实例 SET NX PX + Lua 解锁Redlock(多节点过半)etcd / ZooKeeper数据库唯一约束/事务
定位效率型互斥宣称的容错互斥正确性型协调(CP)以数据为中心的防重
共识无5 独立节点多数派Raft/ZAB 共识存储引擎事务
fencing token无无有(zxid/revision 单调递增)版本号/自增 id
典型故障翻车主从切换后锁丢失长 GC 停顿/时钟跳变后双持锁罕见,需正确处理会话租约依赖正确建模
成本一条命令5 个独立实例3~5 节点共识集群零新增组件

要点:2016 年 Kleppmann vs antirez 之争(纵轴第三节)到今天仍是权威边界,其结论是二分法——锁为了效率(偶尔失效只是多做一遍工作),单实例 Redis 锁 + 过期时间足够,Redlock 是多余的复杂度;锁为了正确性(失效即数据损坏),则不要用 Redlock,用共识系统并配合 fencing token(Kleppmann 原文;antirez 回应)。十年下来工业界实操共识更接近 Kleppmann 的版本——这是本文对上述材料与行业实践的归纳判断,争论本身并无权威裁决。fencing token 是锁问题的真正解药:Redlock 的随机 value 不携带单调顺序,GC 停顿后的旧持锁者无法被存储层拒绝;etcd 的 revision 天然提供这一性质。这也是很多团队"直接用数据库乐观锁/唯一索引防重"的原因——多数业务其实不需要分布式锁,需要的是幂等。Redis 锁的正确姿势清单:唯一随机值 + SET key value NX PX ttl 一条原子命令;解锁用 Lua 校验 value;TTL 设为临界区安全上界并加看门狗续期(Redisson 的做法);持锁操作必须幂等,把锁当"尽力而为的优化"而非正确性来源。

场景结论:Redis 锁的边界 = 效率型互斥。正确性场景(资金、库存、强一致 leader)换 etcd/ZooKeeper,或下沉为数据库约束。

限流:Redis+Lua vs nginx limit_req vs Envoy RLS vs 云网关

维度Redis + Luanginx limit_reqEnvoy RLS(global)云 API 网关
状态分布跨实例共享(天然分布式)单机内存,不共享集中式 gRPC 服务(后端多为 Redis)平台内置
算法固定/滑动窗口、令牌桶、漏桶全可写漏桶(毫秒精度 + burst)本地令牌桶 + 全局配额通常令牌桶/配额
失败模式Redis 挂了要决定 fail-open/closed无外部依赖多一跳 gRPC;RLS 后端同为 Redis,同样面临 fail-open/closed 决策平台托管

要点:Redis 官方教程的结论是五种主流限流算法——固定窗口计数器、滑动窗口日志、滑动窗口计数器、令牌桶、漏桶——都可以用 Lua 原子实现,综合评估后推荐滑动窗口计数器作为精度/复杂度/内存的最佳平衡,需容忍突发时用令牌桶(Redis 限流教程)。五种算法与纵轴第二阶段 Brandur 归纳的"固定窗口/漏桶/GCRA"三类口径可以对上:教程五类中未单列 GCRA——按 Brandur 的口径,GCRA 可视为漏桶的高效变体(无 drip、每键只存一个时间戳)。nginx 的 limit_req 依赖节点内共享内存,状态不跨机器——多台 nginx 各限各的,集群总配额失控,它适合做边缘第一道闸而非精确分布式配额(nginx 限流博客)。Envoy 的定位是分层:本地限流吸收突发 + 全局限流调用 gRPC 服务,而后者(envoyproxy/ratelimit)的典型后端正是 Redis——反直觉但重要:Redis 在限流场景不是被替代者,而是被基础设施封装的存储层。实践共识是分层而非二选一:边缘做粗粒度保护 + 应用层(Redis+Lua)做细粒度按租户配额;Redis 的失败模式必须显式决策——常见取舍是 fail-open 以保可用性,代价是限流短暂失效;此为本文基于实践观察的判断而非统计数据,无论选哪一侧都应写进设计文档(见文末建议 5)。

场景结论:分布式精确限流是 Redis 五大场景里最没有争议的主场——竞品要么不做分布式(nginx),要么底层仍用 Redis(Envoy RLS)。边界只在"边缘粗保护"与"平台托管配额"两处让位。

发布订阅:Redis Pub/Sub vs Streams vs NATS vs MQTT vs Kafka

维度Redis Pub/SubRedis StreamsNATS CoreNATS JetStreamMQTTKafka
投递语义at-most-once(官方原话)at-most/least-onceat-most-onceat-least-onceQoS 0/1/2 每消息可选at-least-once
离线订阅者消息直接丢失从未消费位置读丢失从流读QoS≥1 可补发从 offset 读
持久化无有(XTRIM 控长度)无有broker 依赖有
集群广播成本全集群 bus 广播(7.0 起有 Sharded Pub/Sub 收敛)按 key 分片极轻轻轻重

要点:Redis 官方文档是边界最清晰的一手来源——"Redis' Pub/Sub exhibits *at-most-once* message delivery semantics … the message is forever lost. If your application requires stronger delivery guarantees, you may want to learn about Redis Streams."(Redis Pub/Sub 官方文档)。Sharded Pub/Sub(7.0+,见纵轴)把消息限制在 key 所属 shard 内广播,是集群模式下的官方扩展路径。与 NATS 的正面对比:Core NATS 与 Redis Pub/Sub 几乎同构,NATS 优势在 subject 拓扑表达力与单二进制运维;需要持久时 NATS 升级 JetStream,对应 Redis 升级 Streams——两个生态是"同一条产品阶梯"(NATS vs Kafka)。MQTT 的不可替代区在 IoT:QoS 每消息可选、为弱网/低功耗设备设计、retained message 与遗嘱消息。Kafka 不是 pub/sub 而是 log:无消费者在线就堆积而非丢弃,适合"事件即资产"的场景。Redis Pub/Sub 在聊天 presence、行情 tick、配置失效广播这类"丢一条不心疼"的流量上仍是延迟与成本最优解。

场景结论:Redis Pub/Sub 的边界 = at-most-once。判断句式只有一句:这条消息丢了你心疼吗?心疼 → Streams/NATS JetStream/MQTT QoS1;不心疼 → Redis Pub/Sub/NATS Core。

成本与运维:一台 Redis 顶五个组件的算账

决策速查表

场景用 Redis 的信号越界信号越界后换谁
缓存结构化 value、原子计数、击穿保护纯字符串超高读;每请求必打缓存;超大单机吞吐Memcached / Caffeine / Dragonfly
队列同栈异步任务、中等吞吐、允许秒级堆积要 ACK/回溯/中等保留(先升这一档);长保留回放/严格有序/大消息/绝对不丢(才出走)先 Redis Streams;仍不满足 → Kafka、RabbitMQ、NATS JetStream
锁防重复执行等效率型互斥失锁即资损/数据损坏、需要 fencingetcd、ZooKeeper、数据库唯一约束/乐观锁
限流分布式按用户/租户精确配额仅边缘粗保护;平台级托管配额nginx limit_req、Envoy RLS、云网关
发布订阅实时推送、丢一条无妨、在线即用消息不许丢、离线要补发、每消息 QoSNATS JetStream、MQTT、Kafka、Redis Streams

各结论适用的最低版本(速查)

正文各条结论的版本前提散落各处,这里按结论汇总——手上是 6.x/7.x 的读者按行自查:

结论 / 特性最低版本对应正文
Lua 脚本(原子限流/原子解锁的前提)2.6.0(2012-10)纵轴第二阶段
SET NX PX 单命令加锁2.6.12(2013-03)纵轴第二阶段、锁的场景结论
keyspace notifications(缓存失效监听)2.8(2013)纵轴第二阶段
LFU 淘汰策略4.0(2017)纵轴第三阶段
Streams——队列三档阶梯的第二档(消费组/XACK/回溯)5.0(2018-10)纵轴第三阶段、队列场景
Cluster(pub/sub 全集群广播问题仅在此形态出现)3.0(2015-04)纵轴第二阶段
client-side caching / RESP3 / 多线程 I/O6.0(2020-04)纵轴第四阶段
Functions / Sharded Pub/Sub(大集群 pub/sub 收敛)7.0(2022-04)纵轴第四阶段
向量/检索并入核心(AGPLv3 回归)Redis 8.0(2025-05)纵轴第五阶段
hash 字段过期、原子 slot 迁移Valkey 9.0(2025-10)纵轴第五阶段

两个注脚:原生 GCRA 限流命令在任何已发布版本中都不存在(截至撰写时仍是提案 issue #17274);Redis 与 Valkey 各自新增的特性互不回补,上表最后两行不可互换。


交叉洞察:两轴合在一起说明了什么

把纵轴(十七年边界如何形成)与横轴(2026 年竞品如何分布)叠在一起,会看到四个单轴看不到的东西。

洞察一:竞品地图是历史争议的沉积层

横轴上每一个"越界后换谁"的格子,都能在纵轴上找到触发它的事件:Kleppmann 2016 年对 fencing token 的批评,沉积为今天 etcd/ZooKeeper 在"锁"格子的稳固生态位;Disque 自曝与 list 队列的丢任务事故,沉积为 Kafka/RabbitMQ 在"队列"格子的分工;pub/sub 的 fire-and-forget 语义,沉积为 NATS JetStream 与 MQTT 的"至少一次"阶梯。换句话说,2026 年的竞品地图不是市场自由竞争的快照,而是 Redis 十七年边界争议的地质剖面——每个专业工具的存在理由,都对应着 Redis 曾被证明"做不到"的一件事。反过来说,读横轴对比表时若不知道纵轴上的事故与争论,就无法理解"越界信号"那一列为什么这么写。

洞察二:边界由一个变量统一决定——丢失/双主的代价 vs 延迟收益

纵轴的每次关键争论(Redlock 之争、Disque 自省、Streams 诞生)表面上分属不同场景,实际上都在测量同一个变量:当系统出错时,你损失的是"多干一遍活"还是"数据本身"? 横轴五个场景的对比也收敛到同一判断式。两条轴在 2026 年汇合成一句可操作的口诀:先问数据的丢失/双主代价,再问延迟收益;代价高就出 Redis,代价低就留在 Redis。 缓存丢了可以回源(代价低→主场),限流失效可以 fail-open(代价低→主场),作业队列丢了重跑(代价低→甜点区),锁的双主意味着资金错账(代价高→出走),事件流丢失意味着审计断裂(代价高→出走)。五种用法的"边界硬度"差异,本质上是"出错代价"的连续谱,而非五种独立的经验规则。

洞察三:官方修补过的地方边界软,没修补的地方边界硬

把两轴按"官方是否出手"重新排列,会发现一个清晰的分层:凡是官方用新原语修补过的场景,边界内侧都留有升级路径,用户可以不离开 Redis;凡是官方从未修补的场景,边界是硬的,必须出走。 缓存(LRU→LFU→client-side caching)与队列(list→Streams 消费组)是纯官方收编;限流则是官方与社区共同推进——官方 Lua 教程收编了原子化算法模式,社区模块 redis-cell(Brandur 个人编写,见纵轴第三阶段)把 GCRA 工程化,原生 GCRA 命令仍是提案(issue #17274,未发布)——三者共同点在于修补都落在 Redis 边界内侧,所以"越界"更多是规模问题而非正确性问题;而锁的正确性缺口十七年从未被官方修补——Redlock 至今拿不出 fencing token,官方文档只是把 Kleppmann 的警告原样收录;pub/sub 的 at-most-once 也从未改变,官方文档直接承认"the message is forever lost",Sharded Pub/Sub 修的只是广播风暴这个性能问题,不是投递语义。对用户的含义:遇到"该不该用 Redis 做锁/pub/sub"的疑问,不要期待下一个版本会帮你解决——这两个缺口是架构级的,等不来补丁。

洞察四:"Redis 模式"与"Redis 产品"已分离:学模式,不绑定产品

纵轴的许可证地震(2018 Commons Clause → 2019 RSALv2 → 2024 RSALv2/SSPLv1 → 2025 AGPLv3 回归)与横轴的阵营分布(Valkey 被 AWS/Google/Oracle 接纳、KeyDB 停更、Garnet 无模块生态)合在一起指向同一个事实:五种用法构成的模式知识是可迁移资产,而具体产品是可替换的选型项。 五种用法涉及的核心命令与 RESP 协议在 Redis 与 Valkey 两边保持兼容,各自新增的特性互不回补(Redis 8 的向量/检索与 Valkey 9.0 的 hash 字段过期、原子 slot 迁移分属两条线,见纵轴第五节);RESP 协议的稳定使 Valkey/Dragonfly/Garnet 全部直接继承 Redis 的客户端生态——你按本文边界学到的"什么时候用 Streams、什么时候出走到 Kafka",在分叉之后依然成立;变化只发生在"谁替你运维、按什么计费、许可是否安心"这一层。因此团队技能投资的正确姿势是:把本文的边界判断写成团队的选型文档(与具体产品解耦),把"Redis vs Valkey"留给采购与法务去决策。

对用户的判断与建议

综合两轴,给出一份可执行的决策流程:

  1. 默认姿势:中小系统直接用一个 Redis 承担缓存 + 限流 + 作业队列(BullMQ/Sidekiq)+ pub/sub,享受组件收敛收益——这是十七年历史反复验证的默认架构。
  2. 立刻检查三处硬边界:(a) 有没有用 SETNX+EXPIRE 两步加锁或拿 Redlock 守资金/库存——有则换数据库唯一约束或 etcd;(b) 有没有用 List 队列跑"不能丢"的任务——有则升级 Streams 或 MQ;(c) 有没有拿 pub/sub 传"不许丢"的消息——有则换 Streams/JetStream。
  3. 规模触发出走,而非功能触发:队列要天级保留/回放/日亿级消息才上 Kafka;缓存纯字符串超高读才换 Memcached;这些出走决定由横轴的量化信号触发,不由"听起来更专业"触发。
  4. 按"心疼程度"拆实例:一个 Redis 挂掉不应同时引发缓存击穿、队列停摆、限流失效、推送中断——队列与锁必须独立实例,缓存与 pub/sub 可以共用("锁的独立实例"仅指效率型锁;正确性场景直接执行建议 2(a) 的 etcd/ZooKeeper/数据库约束,根本不建"Redis 锁实例")。
  5. 限流显式决策 fail-open/closed:Redis 不可用时放行还是拒绝,必须写进设计文档,而不是等故障现场临时决定。
  6. 压测验证厂商宣称:Dragonfly 的 25 倍 QPS 是厂商口径,目前可查的独立基准(横轴所引 Reddit 社区基准帖)只复现出 1.2~3 倍量级,且样本有限——任何"换掉 Redis"的性能决定,用你自己的负载实测后再做。

参考来源

发展史(纵轴)

  1. Wikipedia: Redis(版本史、许可证史、antirez 任职与离任时间线)
  2. antirez 旧博客: Redis as an LRU cache
  3. Instagram Engineering: Storing hundreds of millions of simple key-value pairs in Redis
  4. Ruby Toolbox: resque
  5. Linux.com: Redis 2.6.0 released with Lua scripting support、antirez.com/news/52
  6. redis.io: 分布式锁页面、antirez.com/news/101: Is Redlock safe?(本会话直接抓取核实)
  7. antirez.com/news/88: Adventures in message queues(Disque)
  8. brandur.org/rate-limiting(本会话直接抓取核实)、brandur/redis-cell
  9. Martin Kleppmann: How to do distributed locking
  10. redis.io/blog/redis-5-0-is-here、Devopedia: Redis Streams
  11. redis.io/blog/redis-6-0-ga、antirez.com/news/130: Client side caching in Redis 6
  12. antirez.com/news/133: The end of the Redis adventure、The Register 报道
  13. redis.io/blog/welcome-back-to-redis-antirez、antirez.com/news/151: Redis is open source again、redis.io/blog/agplv3
  14. redis.io/blog/redis-82-ga、redis.io/blog/redis-8-4-open-source-ga
  15. Phoronix: Linux Foundation Valkey、Linux Foundation: A Year of Valkey

横向对比(横轴)

  1. redis.io/blog/redis-8-ga、Redis 8.0 发布说明
  2. redis.io: Pub/Sub 官方文档(at-most-once 原文、Sharded Pub/Sub——横轴章节直接读取全文)、Keyspace notifications
  3. Redis Streams 官方教程
  4. Redis 限流官方教程
  5. Linux Foundation: Valkey 9.0 新闻稿、valkey.io、valkey-io/valkey
  6. AWS: Redis vs Memcached、ScaleGrid 2025 对比
  7. AWS: Kafka vs RabbitMQ、bullmq.io、Judoscale: Node.js 作业队列选型
  8. Medium: RabbitMQ / Kafka / Redis 对比
  9. antirez 回应(HN #11022176)、实现分布式锁的正确姿势(fencing token 综述)
  10. nginx 限流官方博客、limit_req 模块文档
  11. Envoy 全局限流架构文档、envoyproxy/ratelimit
  12. Dragonfly 官网(25x/内存/成本宣称)、Reddit 社区基准:Redis vs Valkey vs DragonflyDB vs KeyDB
  13. arXiv 2510.19805《Next Generation Cloud-native In-Memory Stores》(KeyDB 停更、Garnet/Valkey 评估)
  14. NATS vs Kafka 对比、Reddit: Kafka/Rabbit/NATS 讨论
  15. Redisson: Kafka vs Redis 可靠 Pub/Sub
  16. Hacker News: Redis 4.0 讨论、antirez.com/news/81: Thanks Pivotal, Hello Redis Labs

思考题(读完后想一想,参考答案可展开)

  1. 本文对 Redis 五种经典用法(缓存、队列、锁、限流、发布订阅)在 2026 年给出的边界结论分别是什么?作者用哪句统一判断式解释这些边界的差异?
    参考答案

    文章的核心论点:缓存与限流是主场;队列是甜点区,分三档(List/BullMQ、Streams、Kafka/RabbitMQ);锁与发布订阅边界最硬,锁只用于效率型互斥,正确性场景换 etcd/ZooKeeper,Pub/Sub 是 at-most-once。统一判断式:先问数据丢失或双主的代价,再问延迟收益,代价高就出 Redis。边界硬度差异本质是出错代价的连续谱。

  2. 在队列场景中,Redis 的三档升级阶梯怎么走?与 Kafka/RabbitMQ 相比的取舍核心是什么?什么信号出现才必须离开 Redis?
    参考答案

    队列分三档:轻量任务用 List/BullMQ(甜点区);要 ACK、回溯、中等保留时升 Streams,不离开 Redis;出现天级以上长保留回放、日亿级消息、约 1MB 级大消息或绝对不能因 OOM 丢事件,才出走 Kafka/RabbitMQ/NATS JetStream。取舍是内存经济 vs 磁盘经济:Redis 用内存价格换亚毫秒延迟,堆积受内存限制;Kafka 用磁盘价格买长保留吞吐。

  3. 用 Redis 做分布式锁有哪些风险?为什么文章说“锁的正确性缺口十七年从未被官方修补”?
    参考答案

    风险有三层:早期 SETNX+EXPIRE 两步加锁,客户端在两条命令间崩溃会留下永不过期的死锁键;单实例锁在主从切换后丢失;Redlock 无 fencing token,GC 停顿或时钟跳变后会双持锁写脏数据。文章指出锁的正确性缺口十七年从未被官方修补:Redlock 至今拿不出 fencing token,官方文档只原样收录 Kleppmann 的警告——这是架构级缺口,等不来补丁。

  4. 对个人开发者或中小系统,文章推荐的默认架构是什么?有哪些必须立刻检查的硬边界?
    参考答案

    默认姿势:中小系统用一个 Redis 同时承担缓存、限流、作业队列和 pub/sub,享受组件收敛收益。但需检查三处硬边界:两步加锁或拿 Redlock 守资金/库存,换数据库唯一约束或 etcd;用 List 跑不能丢的任务,升 Streams 或 MQ;用 pub/sub 传不许丢的消息,换 Streams/JetStream。限流的 fail-open/closed 决策要写进设计文档。

← 资料库今日播报 →