Valkey 9 深度实战:原子槽位迁移、哈希字段过期与十亿级 QPS 背后的工程真相
两年前 Redis 换了许可证,社区一怒之下拉了个分支叫 Valkey。当时不少人觉得这不过是又一次"政治正确"的 fork,热闹一阵就凉。但两年过去,Valkey 已经走到 9.1.1(2026-07-21 发布),backing 阵容是 AWS、Google Cloud、Oracle、Ericsson,遵循老实的 BSD-3-Clause,而且——它在集群模式下能扩到 2000 个节点、跑出每秒超 10 亿次请求。
这篇文章不打算复读发布公告。我想从一个天天在生产环境里跟缓存打交道的工程师视角,讲清楚 Valkey 9 到底改了什么、这些改动为什么重要、以及你该怎么在真实系统里用起来。重点讲三件事:原子槽位迁移(终于能睡个安稳觉的扩缩容)、哈希字段过期(省掉一堆恶心的拆 key 逻辑)、以及 9.x 的多线程性能内核(十亿 QPS 不是营销数字)。中间穿插大量可直接跑的命令和配置。
一、先把背景讲清楚:Valkey 不是"又一个 Redis"
1.1 分叉的来龙去脉
2024 年 3 月,Redis 把许可证从宽松的 3-Clause BSD 改成了 RSALv2 + SSPLv1 双许可。核心变化是:商业云厂商想直接拿 Redis 源码对外提供托管服务,得先拿授权。这条改动直接踩了 AWS、Google Cloud 这些云厂商的脚。
于是 Linux 基金会牵头,把原来的 BSD 版本代码 fork 出来,起名 Valkey(读音像 Valkyrie,女武神)。关键点在于:Valkey 保留了 Redis 7.2.4 那个开源快照的全部血统,原来一批 Redis 核心贡献者直接转场。所以它不是"模仿 Redis",它就是那条没有拐进商业许可的平行时间线。
对我们工程师最实际的意义是三点:
- 协议 100% 兼容:RESP2/RESP3 一字不差,现有 redis-py、Jedis、Lettuce、go-redis 客户端不用改一行代码,把连接地址一改就能跑。
- 数据格式兼容:RDB / AOF 文件可以直接在 Redis 和 Valkey 之间互导(同版本区间内)。
- 命令兼容:
GET/SET/ZADD/XADD那一整套原样保留,Valkey 只做加法。
所以迁移成本极低。很多团队的"迁移"就是把 Docker 镜像从 redis:7.2 换成 valkey/valkey:9.1.1,重启,完事。
# 拉起一个 Valkey 9.1.1 实例,跟你熟悉的 redis 一模一样
docker run --rm -p 6379:6379 valkey/valkey:9.1.1
# 客户端也是熟悉的味道,valkey-cli 就是 redis-cli 的孪生兄弟
valkey-cli -p 6379 PING
# PONG
1.2 版本节奏:8.0 打地基,9.0 上高度,9.1 精装修
理解 Valkey 9 之前,得先知道 8.0 干了什么,因为 9 的很多性能是站在 8 的肩膀上的。
- Valkey 8.0(2024 年底):这一版是性能分水岭。引入了异步 I/O 多线程(把命令解析、网络读写从主线程剥离)、双通道复制(dual-channel replication,同步 RDB 和复制积压 backlog 走两条连接,主节点内存压力骤降)、以及每槽位指标(per-slot metrics,能看到单个 slot 的热度)。8.0 在多核机器上相比单线程时代的 Redis 有数倍吞吐提升。
- Valkey 9.0(2025 年底):架构级升级。原子槽位迁移、哈希字段过期、集群模式下的编号数据库、扩展到 2000 节点、10 亿+ QPS。
- Valkey 9.1(2026 年中,最新补丁 9.1.1):精装修。安全、可观测性、效率再进一步,I/O 路径重新设计,并且——有一批 bug 修复是由 AI 智能体自动完成的(后面细讲,这事挺有意思)。
好,背景铺完,进正题。
二、原子槽位迁移:扩缩容从"惊险"变"无聊"
2.1 老方案为什么让人半夜惊醒
先复习集群分片模型。Valkey/Redis 集群把整个键空间切成固定的 16384 个 slot,每个 key 通过 CRC16(key) mod 16384 落到某个 slot,每个节点负责一批 slot。
key "user:1001" -> CRC16("user:1001") % 16384 -> slot 5798 -> 节点 B
扩容时你要把一部分 slot 从旧节点搬到新节点。9.0 之前,这个过程是逐个 key 迁移的,大致流程:
# 老式迁移(简化版),一个 slot 内的 key 一个个搬
CLUSTER SETSLOT 5798 MIGRATING <target-node-id> # 源节点:标记 slot 迁移中
CLUSTER SETSLOT 5798 IMPORTING <source-node-id> # 目标节点:标记 slot 导入中
# 然后循环:取出 slot 里的 key,一批批 MIGRATE 过去
CLUSTER GETKEYSINSLOT 5798 100
MIGRATE <target-ip> <target-port> "" 0 5000 KEYS key1 key2 ...
# 全部搬完,通知全集群 slot 归属变更
CLUSTER SETSLOT 5798 NODE <target-node-id>
问题出在中间那段"迁移中"的窗口期。在 key 一个个搬的过程中:
- 归属是模糊的:一个 slot 里有些 key 在源节点、有些已经到目标节点。客户端访问时,源节点可能回一个
-ASK重定向,客户端得跟着跳。 - 窗口可能很长:如果 slot 里有 bigkey(几百 MB 的 hash 或 zset),单个
MIGRATE会阻塞,整个迁移拖很久。 - 中途出错会留下烂摊子:迁移到一半源节点挂了,slot 处于半迁移状态,需要人工介入清理。
- 容量规划靠玄学:你没法准确预估迁移耗时,只能挑凌晨低峰期,捏着一把汗操作。
我自己经历过一次线上重分片,一个 800MB 的 hash 卡住了 MIGRATE,源节点主线程被阻塞了十几秒,上游服务连环超时。那次之后我对"在线扩容"这四个字有了心理阴影。
2.2 原子槽位迁移:整个 slot 一次性交接
Valkey 9.0 的原子槽位迁移(atomic slot migration)彻底换了思路。不再逐个 key 搬,而是把整个 slot 作为一个原子单元、以 AOF 格式一次性移动过去。 交接是原子的:要么完全在源节点,要么完全在目标节点,不存在中间态。
Valkey 开源负责人 Kyle Davis 的原话是:
在 Valkey 9.0 中,迁移不再是按键迁移,而是一次迁移整个 slot,并通过 AOF 格式进行原子移动。
这带来几个直接好处:
- 键路由始终一致:迁移期间客户端要么全被路由到源、要么全被路由到目标,不会出现一个 slot 内 key 归属分裂的混乱。
-ASK重定向的抖动大幅减少。 - 交接可预测:你能预估迁移耗时(正比于 slot 数据量 / 网络带宽),扩容变成一个能排期的工程任务,而不是一场赌博。
- 出错可回滚:因为是原子操作,中途失败不会留下半迁移的烂 slot,源节点保持权威直到交接完全成功。
Momento 的 CEO Khawaja Shams 和 AWS Hero Allen Helton 评价得挺到位:
对于在集群环境中运行 Valkey 的团队而言,这从根本上改变了容量规划和运维风险管理方式。扩容将变得可预测,而不再是痛苦的过程。
2.3 实操:一次可预测的在线扩容
假设你有一个 3 主 3 从的集群,现在要加一个新主节点分担压力。
# 1. 启动新节点并加入集群
valkey-cli --cluster add-node <new-ip>:6379 <existing-ip>:6379
# 2. 用 reshard 把一批 slot 原子迁移到新节点
# 9.0 起底层走原子迁移,工具层命令保持兼容
valkey-cli --cluster reshard <existing-ip>:6379 \
--cluster-from <source-node-id> \
--cluster-to <new-node-id> \
--cluster-slots 4096 \
--cluster-yes
# 3. 观察迁移进度和集群健康
valkey-cli --cluster check <existing-ip>:6379
valkey-cli -h <source-ip> CLUSTER NODES | grep migrating
迁移过程中,用每槽位指标盯着热点 slot 的状态:
# 8.0 引入的 per-slot 指标,迁移期间用来确认没有热 slot 被卡住
valkey-cli -h <node-ip> CLUSTER SLOT-STATS SLOTSRANGE 0 16383
一个实用建议:扩容前先用 slot-stats 找出最热的几个 slot,避免把热点集中迁到同一个新节点上,否则你只是把瓶颈搬了个家。原子迁移解决了"迁移过程的稳定性",但不会自动帮你做热点均衡,热点识别还得靠你自己。
三、哈希字段过期:终于不用拆 key 了
3.1 那个困扰所有人的老问题
Redis/Valkey 的 hash 一直有个憋屈的限制:TTL 只能设在整个 key 上,没法给 hash 里的单个 field 设过期。
举个再常见不过的场景——用户会话里存多个令牌,每个令牌过期时间不同:
session:1001 (hash)
├── access_token -> 15 分钟过期
├── refresh_token -> 7 天过期
└── device_id -> 永不过期
在 9.0 之前,你只能有两条烂路:
烂路一:拆成多个独立 key。 把每个 field 拆成 session:1001:access_token、session:1001:refresh_token,各自设 TTL。代价是丢掉了 hash 的原子性和内存紧凑性,key 数量爆炸,HGETALL 一次拿全部的能力也没了。
烂路二:自己在应用层维护过期时间戳。 hash 里存 access_token_exp 字段记时间戳,读的时候在应用层判断是否过期,再起个定时任务扫描清理。代码恶心、清理不及时、内存长期泄漏。
我见过太多项目在这两条路上反复横跳,最后代码里全是 if (now > token.expireAt) 这种防御性判断。
3.2 HEXPIRE 家族:field 级 TTL
Valkey 9.0(对齐 Redis 7.4 引入的能力)加入了完整的哈希字段过期命令族。核心是 HEXPIRE 及一系列兄弟命令:
# 建立会话 hash
HSET session:1001 access_token "at_xxx" refresh_token "rt_yyy" device_id "dev_zzz"
# 给 access_token 设 900 秒(15 分钟)过期
HEXPIRE session:1001 900 FIELDS 1 access_token
# 返回 (integer) 1 表示设置成功
# 给 refresh_token 设 7 天过期
HEXPIRE session:1001 604800 FIELDS 1 refresh_token
# device_id 不设过期,保持永久
# 查各 field 剩余 TTL(秒)
HTTL session:1001 FIELDS 3 access_token refresh_token device_id
# 1) (integer) 900
# 2) (integer) 604800
# 3) (integer) -1 -> -1 表示无过期时间
完整命令族,跟 key 级 TTL 命令一一对应,只是操作对象变成 field:
| 命令 | 作用 | 对应的 key 级命令 |
|---|---|---|
HEXPIRE | 设置相对过期(秒) | EXPIRE |
HPEXPIRE | 设置相对过期(毫秒) | PEXPIRE |
HEXPIREAT | 设置绝对过期(Unix 秒) | EXPIREAT |
HPEXPIREAT | 设置绝对过期(Unix 毫秒) | PEXPIREAT |
HTTL / HPTTL | 查剩余 TTL(秒/毫秒) | TTL / PTTL |
HEXPIRETIME / HPEXPIRETIME | 查绝对过期时间点 | EXPIRETIME / PEXPIRETIME |
HPERSIST | 移除 field 的过期时间 | PERSIST |
FIELDS N field1 field2 ... 这个语法是强制的:N 是你要操作的 field 数量,后面跟对应个数的 field 名。第一次用会觉得啰嗦,但它让批量操作和命令解析都更明确。
# 批量给两个 field 设过期
HEXPIRE session:1001 300 FIELDS 2 access_token refresh_token
# 带条件设置:NX(不存在过期才设) / XX(存在过期才改) / GT(仅当新TTL更大) / LT(仅当新TTL更小)
HEXPIRE session:1001 600 GT FIELDS 1 access_token # 只在延长时生效
# 移除某个 field 的过期,让它变永久
HPERSIST session:1001 FIELDS 1 refresh_token
3.3 底层实现:主动过期 + 可控内存开销
有人会担心:给每个 field 挂 TTL,内存会不会爆?清理会不会拖慢主线程?
AWS 高级软件工程师 Ran Shidlansik 给出的答案是否定的。Valkey 采用主动过期机制(active expiration)来清理过期 field——有一个共享的后台任务周期性扫描、回收过期字段,而不是等到访问时才被动删除(虽然被动删除也保留作为兜底)。
他给出的基准测试结论是:
字段级过期可以在不牺牲内存效率或延迟的情况下加入 Valkey。额外内存开销保持可控,指令吞吐未受影响,而共享的主动过期任务在高写入压力下仍能高效回收内存。
实现上的关键设计:
- 过期元数据紧凑存储:field 的过期时间以紧凑格式挂在 hash 结构上,不是每个 field 一个独立对象,所以额外开销可控。
- 主动过期共享任务:不为每个 hash 单独起清理逻辑,而是全局共享的过期扫描任务统一处理,避免任务数量随 hash 数量线性膨胀。
- 写压力下仍高效:高并发写入时,主动过期任务仍能跟上回收节奏,不会让过期 field 长期占着内存。
3.4 一个真实重构案例
拿前面的会话场景,看看代码前后对比。重构前(应用层维护,Python 伪代码):
import time
def get_valid_token(r, session_id):
data = r.hgetall(f"session:{session_id}")
if not data:
return None
# 应用层手动判断过期,恶心的防御性代码
exp = int(data.get(b"access_token_exp", 0))
if time.time() > exp:
r.hdel(f"session:{session_id}", "access_token", "access_token_exp")
return None
return data[b"access_token"]
# 还得单独起个定时任务扫描清理僵尸 field,此处省略 50 行……
重构后(交给 Valkey):
def set_token(r, session_id, token, ttl=900):
r.hset(f"session:{session_id}", "access_token", token)
r.hexpire(f"session:{session_id}", ttl, "access_token") # go-redis/redis-py 新版已支持
def get_valid_token(r, session_id):
# 过期的 field 已被 Valkey 自动清理,读到就是有效的
return r.hget(f"session:{session_id}", "access_token")
清理逻辑、过期判断、定时任务,全没了。这就是把复杂度下沉到数据层的价值——能让数据库干的脏活,就别在应用层重复造轮子。
四、编号数据库进集群:命名空间的回归
4.1 单机有、集群没有的尴尬
Redis 单机模式一直有编号数据库(numbered databases)——就是那个 SELECT 0 / SELECT 1,默认 16 个逻辑库,用来隔离数据、防止 key 冲突。
但集群模式下,Redis 和 9.0 之前的 Valkey 只允许用 0 号库。原因是集群的 slot 路由和多库语义会打架:一个 key 落哪个 slot 是按 key 名算的,跟它在哪个 db 无关,跨库的原子操作在分片下很难保证。
结果就是:想在集群里做逻辑隔离的团队,只能靠 key 前缀(app1:user:1、app2:user:1)硬凑命名空间,既丑又容易出错。
4.2 Valkey 9.0 的完整集群多库支持
9.0 取消了这个限制,集群模式下也能用编号数据库了。 Kyle Davis 把它定位成一种命名空间机制:
最直接的使用场景是需要逻辑上隔离数据,同时能够接受资源共享带来的影响。例如,将不同客户的数据分隔开,或在资源不成问题的情况下整合多个应用到同一个集群中。
典型用法:
# 集群模式下也能 SELECT 了
valkey-cli -c -h <cluster-ip> -p 6379
> SELECT 1
OK
> SET tenant_a:config "..."
OK
> SELECT 2
OK
> SET tenant_b:config "..." # 与 db1 完全隔离
OK
配置里调整可用库数量:
# valkey.conf
databases 64 # 默认 16,按需调整
一个重要提醒:多库是"逻辑隔离 + 物理共享"。同一个集群节点上的多个 db 共享同一份 CPU、内存、网络资源。所以它适合的是"逻辑上想分开、但资源可以合用"的场景(比如多租户 SaaS 的租户隔离、多个小应用合并部署省成本),不适合用它来做资源隔离或性能隔离——真要资源隔离,还是得上独立集群。
五、十亿 QPS 不是营销:9.x 的多线程内核
5.1 从单线程神话到多线程现实
Redis 早年"单线程也能快"是靠纯内存操作 + epoll 多路复用撑起来的。但单线程有天花板:一个核跑满了,剩下的核只能干看着。在动辄 64 核、128 核的现代服务器上,这是巨大的浪费。
Valkey 从 8.0 开始认真做多线程,到 9.x 已经是一套成熟的异步 I/O 多线程架构:
- 网络 I/O 多线程:把 socket 读写、协议解析/序列化从主线程剥离,分给多个 I/O 线程。主线程只专注执行命令(保证命令执行的串行语义和数据一致性)。
- 9.1 重新设计的 I/O 路径:进一步优化了 I/O 线程和主线程之间的任务分发,减少锁竞争和上下文切换。
Momento 团队的观察是,9.0 的性能提升"来自对现代 CPU 能力的智能利用",带来"更低的尾延迟、更高的单节点吞吐量,以及可量化的成本效率"。而 2000 节点集群跑出 10 亿+ QPS,是这套单节点吞吐 × 集群水平扩展的乘积结果。
5.2 开启并调优 I/O 线程
# valkey.conf
# I/O 线程数。经验值:物理核数的一半到 3/4,别超过核数
io-threads 8
调优要点,都是我踩过坑总结的:
- 不是越多越好。
io-threads设太高会因为线程调度和缓存失效反而变慢。816 核机器上,设 48 通常是甜点区。上线前务必用真实负载压测找拐点。 - 命令执行仍是单线程串行的。多线程加速的是网络 I/O,不是命令执行本身。所以一个
KEYS *、一个大SUNION、一个 O(N) 的 bigkey 操作,照样会阻塞主线程。多线程救不了慢命令。 - 配合 CPU 亲和性。生产环境建议把 Valkey 进程和 I/O 线程绑核,避免跨 NUMA 节点访问内存:
# 用 taskset 把 valkey 绑到 0-7 号核
taskset -c 0-7 valkey-server /etc/valkey/valkey.conf
5.3 用 valkey-benchmark 实测你自己的数字
别信任何人给的 benchmark 数字,包括我这篇。在你自己的硬件、你自己的数据模型上测才算数。
# 基础压测:100 并发,100 万请求,测 SET/GET
valkey-benchmark -h 127.0.0.1 -p 6379 -c 100 -n 1000000 -t set,get -q
# 更贴近真实:带 pipeline,随机 key,测 hash 操作
valkey-benchmark -h 127.0.0.1 -p 6379 -c 200 -n 2000000 \
-P 16 -r 100000 -t hset,hget -q
# 集群模式压测
valkey-benchmark -h <cluster-ip> -p 6379 --cluster -c 100 -n 1000000 -q
对比 I/O 线程开关前后的吞吐差异,你就能直观看到多线程在你的场景里到底值多少钱。我在一台 16 核机器上实测,io-threads 8 相比 io-threads 1,GET 的 QPS 大约有 2.5~3 倍提升——但这个数字强依赖网络包大小和 pipeline 深度,你的结果可能完全不同。
5.4 别忘了 fork 这个老大难
多线程再快,持久化时的 fork 依然是集群稳定性的隐形杀手。RDB 快照和 AOF 重写都要 fork 子进程,靠写时复制(COW)共享内存。内存越大,fork 时页表复制越慢,可能阻塞主进程几十甚至上百毫秒。
# 查看最近一次 fork 耗时(微秒)
valkey-cli INFO stats | grep latest_fork_usec
# latest_fork_usec:83000 -> 83ms,偏高了,得警惕
缓解手段(这些在 Valkey 里依然有效):
- 控制单实例内存,别让单节点无限膨胀,超过 20~30GB 的实例 fork 会很痛。集群本身就是最好的水平拆分手段。
- 开启 lazy-free:
lazyfree-lazy-eviction yes、lazyfree-lazy-expire yes,把大对象的内存释放丢到后台线程,避免删 bigkey 时阻塞主线程。 - 8.0 的双通道复制在这里也帮了大忙——全量同步时主节点内存压力更小,fork 的负担相应减轻。
- 物理机优于虚拟机:虚拟化环境下 fork 通常更慢,对延迟敏感的核心缓存尽量用物理机或高规格实例。
六、9.1 的彩蛋:AI 智能体在给数据库修 Bug
Valkey 9.1 里有个信息量很大的细节:这一版的一大批 bug 修复,是由 AI 智能体自动完成的。
这不是噱头。Valkey 是全球最核心的基础软件之一,跑在无数生产系统的关键路径上。一个内存数据库的 bug 修复,容错空间极小——改错一行内存管理代码,可能就是大规模数据损坏。在这种项目里放手让 AI agent 提交修复,本身就说明了两件事:
- AI 编程能力已经进入"可以碰核心基础软件"的阶段。从写业务 CRUD,到给 C 语言写的内存数据库修底层 bug,这个跨度是实打实的。
- 人类维护者的角色在上移。维护者不再是逐行写修复,而是审查、验证、把关 AI 的提交。9.1 那批 AI 修复的 bug 依然经过了人类 review 和完整 CI,AI 是加速器,不是甩手掌柜。
9.1 的其他改进也值得一提(从 RC 版本的 changelog 能看到脉络):
- failover 决策优化:当某个副本已经是排名最优的候选时,直接执行 failover,不再走完整的选举等待,故障切换更快。
cluster-config-save-behavior选项:让你控制nodes.conf的保存行为,在大规模集群里减少不必要的磁盘写。- Lua 脚本引擎默认静态链接:从动态链接改为默认静态链接,减少部署时的依赖问题和潜在的库版本冲突。
- 可观测性增强:更细粒度的指标,配合 8.0 的 per-slot metrics,让大集群的可观测性上了一个台阶。
从工程角度看,9.1 是典型的"成熟期版本"——没有惊天动地的新特性,全是把 9.0 的地基夯实、把运维体验打磨到位的活儿。这种版本往往最值得生产环境升级。
七、迁移与选型:你该不该上 Valkey 9
7.1 从 Redis 迁移到 Valkey
因为协议和数据格式兼容,迁移路径非常平滑:
# 方案 A:冷迁移(有停机窗口)
# 1. 在 Redis 上生成 RDB
redis-cli SAVE
# 2. 把 dump.rdb 拷到 Valkey 数据目录,启动 Valkey
cp /var/lib/redis/dump.rdb /var/lib/valkey/
valkey-server /etc/valkey/valkey.conf
# 方案 B:热迁移(几乎零停机)
# 让 Valkey 作为 Redis 的副本先同步数据
valkey-cli REPLICAOF <redis-master-ip> 6379
# 等待 master_link_status:up 且数据追平
valkey-cli INFO replication | grep master_link_status
# 追平后,切断复制,把流量切到 Valkey
valkey-cli REPLICAOF NO ONE
客户端侧几乎零改动。以 go-redis 为例,连接串一改就行:
// 从 Redis 切到 Valkey,唯一变化是地址
rdb := redis.NewClient(&redis.Options{
Addr: "valkey-host:6379", // 原来是 redis-host:6379
})
// HEXPIRE 等新命令,用新版客户端即可调用
rdb.HExpire(ctx, "session:1001", 900*time.Second, "access_token")
7.2 什么场景该升到 9.x
强烈建议升级,如果你:
- 跑集群且经常扩缩容 → 原子槽位迁移能救你的命。
- 有大量"hash 里 field 需要不同 TTL"的场景 → 哈希字段过期直接砍掉一堆应用层代码。
- 在多核大机器上被单线程吞吐卡住 → 9.x 多线程内核能压榨出硬件价值。
- 做多租户,想在集群里做逻辑隔离 → 集群编号数据库正对口。
可以再等等,如果你:
- 单机小实例、负载不高、没有集群 → 收益有限,8.x 甚至更早版本也够用,升级动力不强。
- 用了大量依赖 Redis 特定商业模块(RedisJSON、RediSearch 等闭源模块)的功能 → 这些模块 Valkey 生态有对应替代(如 valkey-json、valkey-search),但要单独评估兼容性和成熟度,别盲目切。
7.3 一句话选型建议
如果你在做新项目,且不依赖 Redis 的闭源商业模块,我会直接选 Valkey 9.x——开源许可干净、性能在线、社区活跃(AWS/Google/Oracle 真金白银在投)、协议完全兼容 Redis 生态。如果你有存量 Redis 7.2 及更早的开源版本,迁移成本极低,值得规划升级。真正需要谨慎的,只有重度绑定 Redis 商业模块的系统。
八、总结:基础软件的"平替"如何变成"更优解"
两年时间,Valkey 完成了从"被迫的分叉"到"主动的进化"的转变。回头看这条线:
- 8.0 用多线程和双通道复制解决了单线程时代的吞吐天花板;
- 9.0 用原子槽位迁移、哈希字段过期、集群多库,把集群运维和数据建模的老痛点一个个拔掉;
- 9.1 用 I/O 重设计、更快的 failover、AI 辅助的 bug 修复,把成熟度和可观测性推到生产级。
对我们工程师最实际的启示有三条:
- 能下沉到数据层的复杂度,就别在应用层硬扛。哈希字段过期就是最好的例子——一个数据库特性,消灭了无数个项目里重复造的过期清理轮子。
- 在线运维的"可预测性"比"极致性能"更值钱。原子槽位迁移没有让 Valkey 变得更快,但它让扩容从赌博变成排期,这种确定性对生产系统是无价的。
- 别信 benchmark,信你自己的压测。十亿 QPS 是集群上限,跟你单实例能跑多少、你的数据模型下能跑多少,是两码事。
valkey-benchmark在自己的硬件上跑一遍,才是唯一可信的数字。
许可证之争催生了 Valkey,但真正让它站稳脚跟的,是这两年扎实的工程迭代。它已经不是"Redis 的平替",在集群扩缩容、字段级过期、多核性能这些维度上,它就是当下更优的那个选择。
下次你准备给缓存层选型,或者被一次半夜扩容折腾得睡不着的时候,不妨认真看看 Valkey 9。