bigywater.tech
Redis · 94

min-replicas-to-write

Redis 复制是异步的:主库写完就回复客户端。min-replicas-to-write 给主库加了一个保险:如果联系得上的「好从库」少于 N 个,就拒绝写入,免得把数据只写在一个没人备份的节点上。这篇把它的行为量出来:多久才拒绝、拒绝时的错误、什么时候恢复、to-write 与 max-lag 各起什么作用。

3403 ms
max-lag 3 s、从库全冻结时,主库第一次拒绝写入的时间
NOREPLICAS
被拒时的错误:Not enough good replicas to write.
456 ms
解冻从库后写入恢复所用的时间

四种配置

从库用 SIGSTOP 冻结、再用 SIGCONT 解冻;主库由一个客户端每 10 ms 写一次
实测 · 本机执行输出
配置                                      第一条被拒(ms)     此前被接受      解冻后恢复(ms)
要求 1 个从库,冻结全部 2 个从库                      3403       242            456   to-write=1 max-lag=3
要求 1 个从库,只冻结 1 个从库                        未拒绝       641              5   to-write=1 max-lag=3
要求 2 个从库,冻结 1 个从库                        3421       242            486   to-write=2 max-lag=3
要求 1 个从库,max-lag 6,冻结全部                  6437       454            438   to-write=1 max-lag=6
被拒时的错误: NOREPLICAS Not enough good replicas to write.
冻结期间 INFO min_slaves_good_slaves 采样(相对冻结的秒, 值)—第 1 组: [(0.0, 2), (1.0, 2), (2.1, 2), (3.2, 2), (4.3, 0), (5.3, 0), (6.4, 0), (7.5, 0)]

规律:主库并不是从库一冻结就停写,而是要等到「距上次收到从库应答」超过 min-replicas-max-lag(约每秒一次 REPLCONF ACK)才把它算作不好——所以被拒的时间约是 max-lag 加零点几秒(3403 ms 对 3 s;6437 ms 对 6 s)。冻结全部从库时,此前的 242 条写入都被接受了,这就是主库可能「只写在自己身上」的窗口。只冻结 1 个从库而要求 1 个时,始终不拒绝;要求 2 个时冻结 1 个就停写。

取舍

min-replicas-to-write 是拿可用性换数据安全:设得越严,越容易因为从库的暂时故障(网络抖动、重启、fork 卡顿)让主库停写。它也只是「限制窗口」,不是「消除丢失」——窗口内(max-lag 之内)的写入仍然只在主库上。下一篇看它对脑裂的实际效果。

分步演示:何时开始拒绝写入

min-replicas-to-write
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / Redis 8.10.2 独立实例(本机回环端口,save 关闭),redis-cli 风格输出由自写的 RESP 客户端打印;计时用 time.perf_counter,数字每次运行会有小幅抖动。一主两从;每种配置一个新实例;冻结 SIGSTOP、恢复 SIGCONT
    • 没有验证:从库网络断开(而非进程冻结)时的表现、复制延迟大但仍在应答时的判定(lag 的精度是秒)、min-replicas 与 WAIT 命令的组合
    京ICP备2026067502号-1京公网安备11010502063487号