编程 Valkey 9.0 与 9.1.x 混跑:listpack 编码不兼容让 RDB 加载失败,CLUSTER SLOTS 多出的字段会打挂旧客户端

2026-11-02 21:05:51

Valkey 9.0 与 9.1.x 混跑:两个会直接导致节点异常的兼容点

Valkey 9.1 于 2026-05-19 GA。滚动升级期间,9.0 与 9.1.x 在一段时间内混合运行是常态。在这个窗口里,有两个问题不涉及业务逻辑,却会让节点直接不可用;另外,9.1.3(2026-10-26,SECURITY 级别)中还有几条修复与线上运维直接相关。

listpack 编码在 9.0 与 9.1.x 之间对不齐

9.0 与 9.1.x 对某些长度的条目使用了不同的 listpack 编码。因此,跨版本传递 RDB 时,接收端加载会失败;主从复制同样经过这条编码路径,跨版本复制也会失败。9.1.3 修复了该问题(#4819)。

现场表现不是性能下降,而是连接中断:从库在加载 RDB 阶段报错退出,或复制链路根本无法建立;集群里则表现为某个分片的 cluster_state 无法回到 ok。

排查时先查看复制状态和集群状态:

valkey-cli INFO replication      # master_link_status、master_last_io_seconds_ago
valkey-cli CLUSTER INFO          # cluster_state、cluster_slots_assigned

再查看启动日志中与 RDB、AOF 相关的报错,找到加载失败的那一行:

journalctl -u valkey --since "10 min ago" | grep -iE "rdb|aof|listpack|corrupt|bad data"

规避思路是不要在 9.0 与 9.1.x 之间传递 RDB:要么先全部升级到 9.1.3 及以上,再开始滚动;要么在跨版本期间避免执行会触发全量同步的操作。valkey-check-aof 在 9.1.3 中也会识别带 VALKEY 签名的 RDB base 文件,不再把合法的 multipart AOF 误判为非法(#4739),这会影响升级后执行校验时的判断。

CLUSTER SHARDS / SLOTS 多出一个字段

从 9.1 起,CLUSTER SHARDS 与 CLUSTER SLOTS 的响应中,每个节点都会多出一个 availability-zone 字段。多数客户端会忽略未知字段,但严格解析响应体的旧客户端会对这种“意外的字段”直接拒绝,旧版 go-redis 就是一例;官方已经给 go-redis 提供了修复。

这个问题的表现很有欺骗性:服务端一切正常,valkey-cli 手动连接也能用,只有某些语言的客户端在连接池建立阶段失败,或连接后取到的槽位信息为空。确认方式是直接看原始响应里有没有这个字段:

valkey-cli CLUSTER SLOTS
valkey-cli CLUSTER SHARDS

升级顺序上,先升级客户端。把 go-redis 升到包含该修复的版本后,再推进服务端到 9.1;反过来先升服务端,等于把客户端兼容问题放大到整个混合窗口。

9.1.3 里几条与运维直接相关的修复

带有 cluster-databases>1 的部署要特别注意原子槽迁移:修复前,迁移不会在导入端复制驱逐(eviction),副本内存可能远超 maxmemory(#4920),迁移期间盯着 used_memory 与 maxmemory 的差值比看 QPS 更有用。集群配置保存的修复也值得关注(#4489):之前会写出被截断的 nodes.conf、首次保存后丢失启动锁,在 SMB 文件系统(如 Azure Files)上每次保存都失败;现在锁改到独立的 nodes.conf.lock。部署在 Azure Files 上的集群,之前大概率一直在带病运行。

hide-user-data-from-log 启用时,日志里的错误文本没有被脱敏,命令参数会泄漏到日志(#4815),使用这个开关前需要明确日志可见范围。

另外几处会导致数据或状态分叉的修复同样值得在升级说明里标出:被判定为已过期的字段不再随 HDEL/HGETDEL/HPERSIST/HEXPIRE 传播(#4772),COPY 一个 hash 时包含已过期但未回收的字段,使删除被正确传播(#4939),两者都是为了副本与 AOF 重载保持一致。RESTORE 声明的字符串长度溢出曾导致服务器 abort,现在按坏数据拒绝(#4733);ACL 文件里选择器括号不匹配会在启动时崩溃(#4214)。虚拟机上内核 clocksource 不是 tsc 时事件循环忙转的问题也已修掉(#4707)。

同日发布的 9.0.7 修了 GHSA-f4q9-j22m-xqq9:集群 Pub/Sub 消息构造中的堆缓冲区溢出,已认证客户端可通过发布超大消息潜在执行任意代码;另有 COMMAND GETKEYS EVAL 声明远大于实参的 key 数量导致巨量内存分配。9.0 分支的实例不要只盯着 9.1.3。

9.2.0-rc1 的行为变化

9.2.0-rc1(2026-09-16)有几点会改变现有监控基线。key 与 hash 字段的主动过期现在递增 dirty 计数器,保存点以及 BGSAVE 可能更频繁触发;如果 save 配置较激进,升级后会看到 rdb_changes_since_last_save 增长变快、fork 次数上升,需要用 INFO persistence 重新核对节奏。

新增可选的 repl-throttling-enabled:副本落后时放慢客户端写入,避免触发断连与全量同步,属于用写入延迟换复制稳定性的取舍。新增 priority-preemptive-poll-interval-us,让集群心跳、复制、槽迁移等系统关键事件优先于大量客户端流量,高负载下原本会被客户端请求挤压的集群事件有了调度空间。这两项都是可选配置,默认行为不变,但值得在压测环境先跑一轮。

复制全文 生成海报 Valkey Redis 集群运维 滚动升级

推荐文章

程序员茄子在线接单