Redis 复制是异步的:主库写完就回复客户端。min-replicas-to-write 给主库加了一个保险:如果联系得上的「好从库」少于 N 个,就拒绝写入,免得把数据只写在一个没人备份的节点上。这篇把它的行为量出来:多久才拒绝、拒绝时的错误、什么时候恢复、to-write 与 max-lag 各起什么作用。
配置 第一条被拒(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 之内)的写入仍然只在主库上。下一篇看它对脑裂的实际效果。