Redis集群降级需全局关闭cluster-require-full-coverage:所有节点配置设为no并持久化,客户端须捕获CLUSTERDOWN错误、禁用自动重定向、避免跨槽命令,否则降级无效。

Redis集群降级的核心机制是 cluster-require-full-coverage
默认情况下,只要集群中有任意一个槽(slot)不可用(比如对应主节点宕机且无从节点接管),整个集群就拒绝所有读写请求,返回 CLUSTERDOWN Hash slot not served 错误。这不是 bug,是 Redis 的强一致性保护策略。要让部分槽继续服务,必须关掉这个“全量覆盖”校验。
关键点在于:这个参数只影响客户端请求的准入判断,不改变实际数据分布或故障恢复逻辑。它不修复故障,只是绕过检查。
- 修改方式:在所有节点的
redis.conf中设cluster-require-full-coverage no,然后redis-cli -p或重启生效config rewrite - 注意:必须所有节点都改,哪怕只是临时降级——集群握手时会同步该配置,任一节点为
yes都可能导致行为不一致 - 线上热改可行,但
config set cluster-require-full-coverage no不持久,机器重启后失效
降级后读写行为变化与风险边界
设为 no 后,客户端发来的命令只要目标槽当前有可用节点(哪怕是只读从节点),就会被处理;否则才报错。这意味着:
- 对正常槽:一切照旧,读写都走主节点(或手动
READONLY后走从节点) - 对故障槽:如果该槽有从节点且未被标记为
fail,主节点又不可达,部分客户端可能把请求发到从节点并得到响应(取决于客户端是否支持重定向和重试) - 严重风险:若故障槽的主从全部失联,但客户端因网络抖动误判从节点存活,可能写入失败却无感知——Redis 不保证降级模式下的操作原子性或成功反馈
- 不解决脑裂:如果网络分区导致多个主节点同时认为自己拥有同一槽,降级后写请求可能落到不同节点,造成数据不一致
客户端侧必须配合的两个动作
服务端开了降级,客户端不调整等于白搭。常见 SDK(如 Jedis、Lettuce、redis-py)默认遇到 CLUSTERDOWN 就抛异常,不会自动跳过故障槽。
- 禁用自动重定向(
ASK/MOVED异常拦截):某些客户端在收到重定向响应时会强制刷新槽映射,而降级后槽映射已失效,刷新反而加剧错误 - 捕获并忽略特定错误:需显式 catch
ClusterDownError或匹配"CLUSTERDOWN"字符串,对失败 key 做本地缓存、异步落盘或降级返回默认值 - 避免使用
MSET/DEL等跨槽命令:这些命令在降级后大概率直接失败,不如拆成单 key 操作逐个 try-catch
为什么不能只改少数节点?
集群内部通过 Gossip 协议同步元数据,其中就包含 cluster-require-full-coverage 的取值。节点 A 认为可以降级,节点 B 仍坚持全量覆盖,当客户端请求经 A 转发到 B 时,B 仍会按自身配置拒绝——你看到的错误可能来自路径上的任意中间节点,而非目标节点本身。
更隐蔽的问题是:部分客户端(如早期 Lettuce 版本)会缓存首次获取的集群拓扑,即使服务端已改配置,客户端仍按旧拓扑路由,导致部分请求永远打不到已降级的节点。
真正起效的最小动作是:所有主节点 + 所有从节点同步改配置 + 客户端清空槽映射缓存(或重启连接池)——缺一不可。别指望“先改一台试试”。










