因为直接停主节点会触发自动故障转移,导致槽位迁移、连接中断和写丢失;必须先升级从节点并确认完全同步后手动切换角色,确保每个分片始终有可用主节点在线。

Redis集群滚动升级时,为什么不能直接停掉主节点再升级?
因为直接停主节点会触发集群自动故障转移,可能引发槽位迁移、客户端连接中断、写丢失——尤其在高负载下,从节点复制积压没追平就切主,replica-repl-offset 落后会导致数据不一致。
滚动升级的核心逻辑是:**保持每个分片(slot range)始终有可用主节点在线**。所以必须先让从节点升到新版本、确认可服务、再手动切换角色,而非依赖故障转移。
- 升级前确保所有从节点
INFO replication中的master_repl_offset和slave_repl_offset差值为 0(即完全同步) - 禁止在升级过程中执行
CLUSTER FAILOVER或手动CLUSTER REPLICATE,避免槽位状态混乱 - 客户端需支持
MOVED/ASK重定向,且连接池要能自动刷新集群拓扑(如 JedisCluster 的refreshClusterNodes)
如何安全地把一个 Redis 从节点升级到新版本并接管主节点?
关键不是“升级”,而是“升级后验证+角色切换”。升级本身只是替换二进制、重启进程;真正风险在切换瞬间的状态一致性。
- 停掉目标从节点:用
redis-cli -p <port> shutdown</port>,不要 kill -9 - 替换
redis-server二进制,检查redis-server --version确认版本正确 - 用原配置启动:确保
slaveof配置仍指向旧主,且cluster-enabled yes未被意外关闭 - 等
INFO replication显示master_link_status:up且slave_repl_offset == master_repl_offset - 执行
redis-cli -p <port> cluster failover takeover</port>(注意:必须加takeover,否则只是模拟切换)
切换后立刻检查:CLUSTER NODES 中该节点 role 是否变为 master,且其负责的 slot 数与之前主节点一致。
升级过程中遇到 CLUSTERDOWN Hash slot not served 怎么办?
这是集群元数据没及时同步的典型表现,常见于切换后旧主还没退出集群视图,或客户端缓存了过期的 slots map。
- 在新主节点上执行
CLUSTER FORGET <old-master-node-id></old-master-node-id>(如果旧主已下线但仍在节点列表中) - 强制刷新集群状态:所有节点执行
CLUSTER RESET HARD(仅限维护窗口内,会清空本地 slots 缓存) - 客户端侧必须调用
redisClient.refreshClusterNodes()(Lettuce)或触发JedisCluster的reset(),不能靠超时自动恢复 - 检查
cluster-require-full-coverage no是否开启——生产环境建议设为yes,避免部分 slot 不可用时整个集群拒绝写入
升级后延迟突增或内存暴涨,可能是什么配置没对齐?
新旧版本默认配置差异常被忽略,比如 maxmemory-policy 在 Redis 6.2+ 默认是 noeviction,而老版本可能是 allkeys-lru;又比如 active-defrag-threshold-lower 在 7.0 后行为变更。
- 对比新旧版本的
redis.conf,重点关注:maxmemory-policy、repl-backlog-size、active-defrag-cycle-min、cluster-node-timeout - 升级后首次启动时加
--check-rdb参数验证 AOF/RDB 兼容性(尤其跨大版本如 5.x → 7.x) - 观察
INFO memory中的mem_allocator:若从jemalloc变成libc,可能因内存分配策略不同导致 RSS 暴涨
最易被跳过的一步:升级完所有节点后,必须在任意节点执行 CLUSTER INFO,确认 cluster_state:ok 且 cluster_known_nodes 等于预期总数——少一个节点,就少一份容错能力。










