Dragonfly — 多线程 Redis 替代
是什么
Dragonfly 是 Roman Gershman 在 2022 年用 C++ 写的内存数据库——协议兼容 redis,但单实例多线程。原来连 Redis 的 client / SDK 完全不用改,连上去就能跑,但底层是一个能把多核机器吃满的服务端。
日常类比:
- redis 是单核厨师——再多客人来,菜还是一个人炒,第二个炉灶在那里也用不上
- Dragonfly 是分工厨房——每个 CPU 核坐一个厨师,客人按号分到不同厨师,吞吐量直接乘核数
一句话定位:「Redis 协议 + 多核并行 + 更省内存」的内存 KV。
为什么重要
不理解 Dragonfly 的存在,下面这些事都没法解释:
- 为什么 2022 年突然多一个「和 Redis 对标」的项目,云厂商跟进很快——单实例吞吐 25 倍是真金白银省钱
- 为什么「内存效率高 30%」也是卖点——大规模缓存集群里,每省一台机器都是月度账单的差距
- 为什么 redis 在 2024 年改 SSPL 许可后,Dragonfly 顺势接住了一批用户——Dragonfly 用 BSL(4 年后转 Apache 2.0),对很多团队更友好
- 为什么 valkey 出现后,「内存 KV」赛道变成了三家竞争(Redis / Valkey / Dragonfly),而不是一家独大
简单说:Dragonfly 把「Redis 协议」和「Redis 实现」解耦了——协议是公开标准,实现可以重写。
核心要点
Dragonfly 能比 redis 快这么多,靠三件事:
-
多线程 + shared-nothing 架构:每个 CPU 核绑定一个独立线程,每个线程管自己的一份 key 范围,互不抢锁。类比:分工厨房里每个厨师有自己的灶台和食材,不需要排队抢一口锅。
-
Dashtable(替代 Redis Dict 的哈希表):Redis 用的 Dict 是单线程时代的设计,扩容时会卡顿(一次性把所有 key 重新哈希一遍)。Dashtable 是分段式哈希,扩容只动一段、不阻塞其他段。内存碎片也更少,所以总体省 30%。
-
RESP 协议兼容:RESP(REdis Serialization Protocol)是 Redis 的网络协议。Dragonfly 完整实现了 RESP2/3,所以 redis-cli、jedis、ioredis、go-redis 这些 client 直接连,不用改一行代码。
实践案例
案例 1:30 秒跑起来
docker run -p 6379:6379 docker.dragonflydb.io/dragonflydb/dragonfly然后用任何 Redis client 连:
redis-cli SET foo barredis-cli GET foo体感和 redis 完全一致——这就是协议兼容的力量。
案例 2:性能对比
官方 benchmark(16 核机器,memtier_benchmark 压测):
- Redis 单实例:约 200k ops/s(瓶颈在单核)
- Dragonfly 单实例:约 4M ops/s(吃满 16 核)
差距是 20-25 倍。要在 Redis 上达到同样吞吐,得跑 Redis Cluster 16 个分片,运维复杂度立刻上一个台阶(管 cluster 拓扑、resharding、客户端要懂分片)。
案例 3:替换现有 Redis 的步骤
# 1. 停 Redis(或者保留旧实例做迁移期对照)# 2. 启 Dragonfly,监听同样的端口 6379# 3. 应用代码不动,重启即可如果原来用 RDB / AOF 持久化,需要规划迁移:Dragonfly 有自己的 snapshot 格式(DFS),不能直接读 Redis 的 RDB 文件——这是替换时第一个要踩的坑。常见路径有两条:双写 + 灰度切流(适合在线业务),或者 redis-cli —rdb 导出 + 自写脚本灌入新实例(适合离线缓存)。
案例 4:单实例代替小集群
假设原本用 3 个 Redis 节点做分片,每个吃满一个核:
- Redis 集群:3 实例 × 200k ops/s ≈ 600k ops/s,但要管 cluster 拓扑、resharding、客户端要懂分片
- Dragonfly 单实例(4 核机器):能跑 1M+ ops/s,无 cluster 复杂度
很多中等规模的场景,单实例 Dragonfly 可以替掉 Redis 小集群,运维成本下一个台阶。但注意:单实例的可用性上限就是这台机器——彻底冗余还是要主从复制或 cluster。
踩过的坑
-
部分 Redis 7 命令未完全实现:FUNCTION 系列、部分第三方 module(RedisJSON / RediSearch 等)在 Dragonfly 上行为不一致或不支持。换之前先把项目用到的命令清单跑一遍兼容性测试。
-
Lua 脚本 sandbox 略有差异:Dragonfly 的 Lua 实现和 Redis 不完全等价,复杂脚本(特别是依赖 Redis 内部状态的)需要回归测试。
-
持久化格式不通用:Dragonfly 的 DFS snapshot 不能被 Redis 读,反之亦然。从 Redis 迁移需要走「双写 + cutover」或者「redis-cli —rdb 导出 + 自写脚本灌入」。
-
BSL 许可的 4 年期:BSL(Business Source License)规定「4 年后自动转 Apache 2.0」,但前 4 年内某些商业用途(比如把 Dragonfly 包装成竞品 SaaS 卖)受限。自用 / 内部缓存场景没问题,但法务最好评估一下。
-
集群模式还在演进:单实例多线程已经能解决很多场景,但跨机器的 cluster 模式(v1.20 起加入)成熟度还在追赶 Redis Cluster。
-
shared-nothing 的代价:跨 key 范围的多 key 命令(MGET / MSET 跨分片、事务跨分片)需要在多个线程间协调,性能不如「同一个线程内」。设计 key schema 时尽量让相关数据 hash 到同一线程。
适用 vs 不适用场景
适用:
- 单实例 Redis 已经吃满 CPU,但还不想拆 Cluster——直接换 Dragonfly 立刻有 10 倍余量
- 大量内存缓存(几十 GB 起),省 30% 内存等于省钱
- 用标准 Redis 命令(SET/GET/HASH/LIST/ZSET/PUB-SUB)的场景,迁移成本最低
- 对许可敏感、不接受 SSPL 的团队
不适用:
- 重度依赖 Redis module(RedisJSON / RediSearch / RedisGraph 等)——module 生态还在 Redis 这边
- 已经用 Redis Cluster 大规模分片且没遇到瓶颈——切换收益小、风险大
- 需要和 Redis Enterprise 商业特性(Active-Active CRDT、Auto Tiering 等)对接的场景
历史小故事
- 2022 年:Roman Gershman(前 Google / RedisLabs 工程师)和 Roy Allen 创立公司,目标是「用现代多核硬件假设重写 Redis」。5 月开源第一版,几个月就拿到 4 万 star
- 2023 年:v1.0 GA,开始有公司在生产用
- 2024 年:redis 改 SSPL 许可,社区分裂——一部分人转 valkey,一部分人选 Dragonfly。Dragonfly v1.20 加入 cluster 模式和主从复制
- 趋势:内存 KV 赛道从「Redis 一家独大」变成「Redis / Valkey / Dragonfly 三足」,对用户是好事——选择多了,许可也更宽松
学到什么
- 协议是标准、实现是商品——RESP 协议是 Redis 留给社区的礼物,让重写实现成为可能
- 单线程的简洁性 vs 多线程的吞吐——Redis 用单线程换简单,Dragonfly 用 shared-nothing 换吞吐,两种设计哲学都对,看场景
- 数据结构选型决定上限——Dict → Dashtable 这一个改动就拿到 30% 内存收益,底层数据结构的影响比想象大
- 许可证是技术决策的一部分——SSPL 事件证明:选基础组件时,许可走向比性能更影响长期决策
- shared-nothing 不是免费的——单实例多线程把锁竞争换成了「跨线程协调」,跨 key 操作仍有代价
怎么读源码
如果想从代码层面理解 Dragonfly 是怎么做到「多核并发」的,建议这样切入:
- 先读 server/dragonfly_listener.cc:网络入口,看 RESP 请求怎么从 socket 到达每个 shard。
- 再读 server/engine_shard_set.cc:核心 shard 调度器,每个 shard 对应一个 CPU 核绑定的线程,理解「key 怎么映射到 shard」。
- 接着读 core/dash_table.h / dash_table.cc:Dashtable 的实现,看分段哈希怎么避免「stop-the-world rehash」。
- 最后读 server/transaction.cc:跨 shard 事务,理解 shared-nothing 架构下「多 key 命令」是怎么协调的。
读源码时一个常见误解:以为 shared-nothing 等于「零协调」。其实跨 shard 的事务依然要锁,但锁只在涉及的 shard 之间,不像 Redis Cluster 那样要跨网络。
延伸阅读
- 官方架构文档:Dragonfly Architectural Overview
- benchmark 复现脚本:仓库内 tools/benchmark/,可以在自己机器上跑出 25 倍数字
- Dashtable 论文背景:Pedrosa “Dash: Scalable Hashing on Persistent Memory”(VLDB 2020)