编程 Valkey 9.2.0-rc1 运维笔记:forkless RDB、服务端热 key、给运维留连接位

2026-10-17 21:10:10

Valkey 9.2.0-rc1 运维笔记:forkless RDB、服务端热 key、给运维留连接位

项目:valkey-io/valkey Releases · 官网:valkey.io

9.2.0-rc1 于 2026-09-16 发布,是本系列首个 RC,升级紧急度 LOW。下面只讲三处运维会实际动手的东西:forkless RDB 快照、服务端热 key 检测、管理连接预留。其余条目在文末一句话带过。RC 阶段的配置名和 INFO 字段名仍可能变,上线前对照最终发布说明再确认一遍。

1. forkless RDB 快照

fork 在大内存实例上为什么要命

传统 BGSAVE 走 fork:子进程拿一份父进程页表的副本,之后父进程写时复制(COW)。代价有三块:

  • 页表复制发生在 fork 调用里,而 fork 跑在主线程上。实例内存越大,页表越大,这次停顿越长,客户端看到的就是一次延迟尖刺。
  • COW 让 RSS 上涨。fork 之后写入越密集,被复制的页越多,最坏情况内存占用接近翻倍。实例已经贴着 maxmemory 或者机器 overcommit 策略偏激进时,这就是 OOM 的直接来源。
  • 子进程写盘期间还要和父进程抢 CPU 与 IO,快照窗口内整体延迟分布会明显变差。

所以「内存越大越不敢做快照、越不做快照恢复越慢」是个真实存在的死循环。

开关与状态

forkless 是 opt-in,默认行为不变。两个配置配合使用:

# valkey.conf
forkless-infrastructure-enabled yes
bgsave-default-method
# 运行期切换(取值以 CONFIG GET 回显和官方文档为准,RC 阶段确认一次)
valkey-cli CONFIG SET forkless-infrastructure-enabled yes
valkey-cli CONFIG SET bgsave-default-method forkless

# 确认生效
valkey-cli CONFIG GET forkless-infrastructure-enabled bgsave-default-method

INFO persistence 新增了报告快照方式与进度的字段,切过去之后第一件事就是确认这些字段真的在动。forkless 具体怎么实现、额外占多少内存,以官方文档为准,不要在容量规划里假设它「零开销」。

验证方法

不要拿已经接近 maxmemory 的生产实例做第一次试验,先在影子实例或预发上跑一遍:

# 1. 基线:快照前的延迟分布
valkey-cli --latency -i 1 > latency-before.txt &
CLIENT_PID=$!

# 2. 触发快照
valkey-cli BGSAVE

# 3. 快照期间轮询状态,确认方式与进度字段在更新
while true; do
valkey-cli INFO persistence | grep -Ei 'save|progress|rdb_bgsave_in_progress'
sleep 1
done

# 4. 收尾
kill $CLIENT_PID

同一份数据集、同样的写入压力,把 bgsave-default-method 切回 fork 再跑一遍,对比两轮的 valkey-cli --latency 输出和 INFO latencystats,看的是 BGSAVE 窗口内的尾部延迟,而不只是 rdb_* 计数有没有涨。另外留意切换前后 INFO memory 的 RSS 峰值——那才是 COW 成本的直接体现。

2. 服务端热 key 检测:HOTKEYS

热 key 以前要么在客户端埋点,要么在代理层统计,多语言多客户端时口径还不统一;MONITOR 全量输出命令流,开销随 QPS 线性涨,只能短时间开;SCAN 遍历的是 keyspace,回答的是「有哪些 key」,不是「谁被访问得最多」。

9.2 把这件事挪到了服务端,用 hotkeys-top-k 开启:

# 开启检测,k 决定追踪多少个 key
valkey-cli CONFIG SET hotkeys-top-k 100

# 读取当前 Top-K
valkey-cli HOTKEYS GET

# 清空统计重新累积(改完 k、或者排查新时间段时用)
valkey-cli HOTKEYS RESET

它给出的是近似 Top-K:计数是估算值,榜外的高频 key 不保证出现,榜单内部也可能有偏差。适合用来定位「哪个 key 在打爆单个分片」「限流该按哪个前缀做」,不适合拿来做计费或精确 QPS 报表。k 调大意味着更多的内存和 CPU 开销,按实际排查需要给,不要习惯性设成几万。RESET 之后统计从零开始,隔一段时间再 GET 才有意义。

3. 管理连接预留:priority-subnets + maxclients-reserved

被打满 maxclients 之后最难受的不是业务报错,是运维自己也连不进去:新连接一律被拒,跳板机上的 valkey-cli 同样被拒,只能去重启进程或从 OS 层杀连接。这个特性就是给这种情况留出退路。

# 把运维网段标记为优先连接
valkey-cli CONFIG SET priority-subnets "10.20.0.0/16 10.30.0.0/16"

# 预留 32 个槽位:普通客户端上限变成 maxclients - 32
valkey-cli CONFIG SET maxclients-reserved 32
valkey-cli CONFIG SET maxclients 10000

# 查看优先连接数
valkey-cli INFO clients | grep connected_priority_clients

语义是两条:来自 priority-subnets 里 CIDR 的连接被标记为 prioritized;maxclients-reserved 把普通客户端(非优先连接)压到 maxclients 减去预留数。于是业务侧连接池打满时,预留槽位仍然对运维网段开放,INFO clients 的 connected_priority_clients 能直接看出当前有多少条优先连接在线。网段列表的分隔符和配置写法以 9.2 文档 / CONFIG GET 回显为准。

注意这是连接数维度的保护,不是内存维度的:预留槽位不解决 OOM,也不保证 maxmemory 打满时命令还能执行。

其余条目

  • ACL DIGEST:返回当前生效 ACL 规则的指纹,用来核对 ACL LOAD 到底加载进去了什么(#4446)。
  • ACL roles:具名、可复用的 ACL selector 集合,用 ACL SETROLE/DELROLE/GETROLE/ROLES 管理,通过 role: 前缀分配给用户,命令、ACL 文件和 valkey.conf 里都能用(#3967)。
  • repl-throttling-enabled:副本落后时主动放慢客户端写入,用降速换掉断连和全量同步(#4356)。
  • rdbcompression lz4:对整个 RDB 文件做 LZ4 压缩;默认的 per-string LZF 不变(#3531)。
  • XACKDEL / XDELEX:带 KEEPREF、DELREF、ACKED 模式的流命令,消费组不再需要消息时一次性确认并删除(#4629)。
  • INCREX:原子地按整数或浮点自增并设置过期时间,支持 NX/XX 条件(#3253)。
  • 其他:tls-alt-cert-file / tls-alt-key-file 支持第二张服务端证书(如 PQC 证书并存,配套 INFO TLS 字段,#3717);maxmemory-scripts 限制缓存 EVAL 脚本的内存,SCRIPT LOAD 标记为 DENYOOM(#866);新增 radix-tree 支撑的 Path Hash 与 PH* 命令,支持精确查找、最长前缀匹配和前缀遍历(#4506);系统关键事件(集群心跳、复制、槽迁移)可抢占重客户端流量,由 priority-preemptive-poll-interval-us 调节(#4076);cluster bus 的读写与 inbound accept 可跑在共享 I/O 线程池上,CLUSTER INFO 有 offload 统计(#3438);带字段过期的小 hash 改用 listpack 编码,不再无条件转 hashtable;MOVE 接受可选 REPLACE(#2993);EXEC 支持 IFEQ/IFNE/NX/XX 条件,多 key 事务不靠 WATCH 也能做乐观锁(#4019);持 CAPA REDIRECT 且未发 READONLY 的客户端,其 SCAN、FLUSHDB 这类无 key 命令会被集群副本重定向到主节点(#3505)。
复制全文 生成海报 Valkey Redis 运维 缓存

推荐文章

程序员茄子在线接单