用min-replicas-to-write排查切换丢数据

先确认当前唯一主并阻断旧主继续接写,再核对 min-replicas-to-write、min-replicas-max-lag 与复制状态;参数只能缩小异步复制的暴露窗口,不能保证零丢数。

“主从切换后订单丢了一页”通常对应两条链路:一条是主节点已经向客户端返回成功,但写入尚未复制到从节点,主节点随即宕机;另一条是 Sentinel 已提升新主,客户端却仍向旧主写入,旧主恢复后重新同步时,独有数据被新主数据覆盖。排查时不要急着让旧主重新同步,先隔离写入并保留现场。

min-replicas-to-write 到底有没有生效?

分别在当前主、旧主和候选主上检查运行时配置:

redis-cli -h <node> -p <port> CONFIG GET min-replicas-to-write
redis-cli -h <node> -p <port> CONFIG GET min-replicas-max-lag
redis-cli -h <node> -p <port> INFO replication

CONFIG GET 只能证明参数值,不能证明当前真的存在合格副本。还要看 INFO replication 中的副本连接状态、复制偏移量和延迟:副本数量门槛仍为 0、运行时配置没有持久化、从库断连或延迟超限,都可能让保护失效或让主节点直接拒绝写入。

旧资料常把它写成 min-slaves-to-write、min-slaves-max-lag。应以目标版本的 CONFIG GET 返回结果为准,而且所有候选主都要有同样的配置,否则下次提升的节点仍可能裸奔。

Redis 切换前最后几次写入复制出去没有?

Redis 主从复制默认是异步的。主节点可以先把成功响应返回给客户端,再把写入发送给副本;如果此时主节点宕机,新主提升后就缺少尚未复制的部分。

redis-cli -h <node> -p <port> INFO replication
redis-cli -h <node> -p <port> ROLE

最可靠的取证方式,是把应用确认成功的订单号或业务主键与新主数据逐条对照,再结合旧主 Redis 日志、Sentinel 切换记录和应用写入目标还原时间线。当前时刻的 INFO replication 只能说明现在的复制状态,不能单独证明故障前最后几笔订单已经复制成功。

min-replicas-to-write 也不会把异步复制变成“每笔写入落盘后才返回成功”,它只是决定副本不足时还能不能继续写。

这是脑裂,还是旧主恢复后覆盖了新数据?

查询 Sentinel 当前认定的主节点和 Sentinel 列表:

redis-cli -p <sentinel-port> SENTINEL GET-MASTER-ADDR-BY-NAME <master-name>
redis-cli -p <sentinel-port> SENTINEL SENTINELS <master-name>
redis-cli -h <node> -p <port> ROLE

如果 Sentinel 已经提升新主,但应用在切换后仍向旧主发送写请求,同时两个节点曾显示主角色,就符合脑裂特征。旧主降级并重新同步新主时,它持有的独有写入可能被覆盖。

处理顺序不能反:先停止旧主接写并保留数据现场,再让客户端通过 Sentinel 或服务发现获取当前主地址,最后才允许旧主重新同步。ROLE 也能帮助识别写请求误落到从节点的情况。

参数改成多少,改完以后怎么验收?

资料中的 1 和 10 只是示例,不应直接当作生产阈值。副本数量应结合实际拓扑确定,延迟阈值则要参考实测复制延迟和写入 SLA。以下仅适用于一主一从、允许运行时修改配置的示例部署:

redis-cli -h <node> -p <port> CONFIG SET min-replicas-to-write 1
redis-cli -h <node> -p <port> CONFIG SET min-replicas-max-lag 10
redis-cli -h <node> -p <port> CONFIG REWRITE

CONFIG REWRITE 只能持久化成功设置的值;托管服务或特殊启动方式应按自身配置流程修改并重启。参数应尽量覆盖所有候选主,否则切换后保护条件可能改变。

设置这组参数后,合格副本不足或复制延迟超限时,主节点会拒绝写入,可用性会因此下降。客户端必须准备好失败处理,不能把拒绝写入当成普通网络错误无限重试。

验收时先确认副本状态正常:

redis-cli -h <node> -p <port> INFO replication
redis-cli -h <node> -p <port> INFO keyspace

再使用隔离的测试键验证复制:

redis-cli -h <primary> -p <port> SET tkmiss:replica-check ok
redis-cli -h <replica> -p <port> GET tkmiss:replica-check
redis-cli -h <primary> -p <port> DEL tkmiss:replica-check

计划内切换还应检查 Redis 日志和依赖服务日志。INFO keyspace 的键数量只能辅助判断,不能证明两边内容完全一致。

已经丢掉的订单还能补回来吗?

先保留旧主,再从数据库、消息队列或业务日志中幂等回放缺失订单。旧主仍有独有数据时,可以先做快照并导出差异,再只补缺失记录,不能直接用旧主的整份数据覆盖新主。

单独开启 RDB 或 AOF 并不能消除故障转移窗口。如果旧主独有数据已经被覆盖,同时没有其他持久化副本或可重放的数据源,这部分订单通常无法恢复。

我的判断是:min-replicas-* 只能缩小异步复制的暴露窗口,不能保证零丢失;旧主隔离、客户端切换和业务侧可重放能力,才决定切换后能否把订单补回来。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容