RedLock 在主从切换过程中,可能因为 Redis 异步复制机制而出现分布式锁失效问题:客户端 A 在主节点加锁成功后,锁信息尚未同步到从节点,此时主节点宕机并触发 failover,从节点被提升为新的主节点,客户端 B 再向新主节点加锁也会成功,最终导致两个客户端同时持有同一把锁。

异步复制导致锁失效的典型场景
Redis 主从复制默认采用异步方式。当执行 SET key value NX PX timeout 并成功返回时,主节点不会等待从节点完成复制确认,就会立即响应客户端。因此,如果此时主节点突然宕机,而从节点又被提升为新的主节点,之前那次加锁操作可能根本还没有同步过去。这样一来,客户端 B 就能够在新主节点上再次成功执行相同命令,造成两个客户端同时持有同一把锁。这并非单纯的理论风险,而是在生产环境中确实可能发生的数据一致性与分布式锁安全问题。
配置 min-sla ves-to-write 和 min-sla ves-max-lag 能否真正兜底
这两个参数确实可以在一定程度上限制写入行为:当可用从节点数量不足,或者复制延迟超过设定阈值时,主节点会拒绝新的写请求。不过需要重点注意以下几点:
min-sla ves-to-write必须与min-sla ves-max-lag搭配使用才会生效,单独配置前者没有实际意义- 延迟的统计单位是秒,
min-sla ves-max-lag 10代表最多允许 10 秒的复制滞后,对于金融、交易等要求秒级强一致性的场景来说通常仍然不可接受 - 该机制只针对主节点的写入路径生效,无法覆盖已经返回成功但尚未同步到从节点的命令,例如主节点崩溃前刚写入、还未来得及复制出去的那部分数据
为什么 sla ve-serve-stale-data yes 会加剧读不一致
这个默认配置意味着:当从节点发生网络中断或复制延迟时,仍然继续对外提供旧数据。问题在于,当它与异步复制同时存在时,客户端读到的数据可能既“过期”又“不完整”。例如:
- 主节点已经删除了某个 key,但对应的 DEL 命令尚未同步到从节点
- 从节点仍然返回该 key 的旧值,而且相关的
EXPIRE过期时间也没有及时更新 - 业务系统因此误判资源仍然可用,进而触发并发写入或重复操作
如果业务对读取一致性要求较高,必须确保读取结果能够反映最新写入状态,那么应考虑将其设置为 sla ve-serve-stale-data no。但这样做的代价也很明显:一旦从节点复制卡顿或同步异常,就会直接拒绝读请求,影响系统可用性。
真正影响决策的是复制积压缓冲区大小
repl-backlog-size 实际上是影响 Redis 断线重连后能否进行部分复制(PSYNC)的关键参数。如果这个值设置过小,一旦出现网络抖动、短暂断连或复制阻塞,从节点就可能无法继续增量同步,只能退化为全量同步。全量同步会显著拉高复制延迟,进一步扩大主从切换中的风险窗口。那么这个参数应该如何设置才更合理?通常建议结合实际写入吞吐来估算,计算公式可参考:每秒写命令数 × 预期最大断连时间 × 平均命令大小。在生产环境中,很多场景可以从 100MB 起步配置,而不建议继续使用默认的 1MB。
需要明确的是,异步复制本身并不能被彻底消除,能够做的更多是缩小风险范围、降低故障影响。真正重要的不是“是否使用主从架构”,而是明确哪些业务操作可以容忍复制延迟,哪些关键操作必须直接访问主节点。例如,分布式锁的获取、校验和释放这类强一致性敏感操作,就不应该依赖从节点处理。
