Redis全量同步原因排查:如何解决复制积压与网络闪断问题?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1218个文字,预计阅读时间需要5分钟。
根本原因并非主从断开了,而是从节点重连时,由于主节点上的主节点的位置无法找到,导致没有对应的偏移量。这通常发生在缓冲区太小或网络中断时间过长,导致缓冲区无法覆盖中断窗口的情况。
现象很典型:日志里反复出现 Partial resynchronization not possible (no cached master),接着就是 Starting BGSAVE for SYNC,CPU 和带宽瞬间拉高,从节点长时间不可用。
- 主节点的
repl-backlog-size默认只有 1MB,对中等以上流量(比如每秒写入 50KB)撑不过 20 秒 - 一次持续 30 秒的网络抖动(如交换机瞬断、云厂商 VPC 路由收敛),就足以让积压缓冲区被新命令覆盖掉旧数据
- 从节点重启或配置变更后重连,如果没保存好自己的
run_id和offset,也会被当成“全新从节点”强制全量
怎么确认是 repl-backlog-size 不够
别猜,直接查主节点当前状态和配置。重点看三个值是否匹配:
-
redis-cli info replication | grep -E "backlog|offset"查当前积压缓冲区实际使用长度(repl_backlog_active)、总大小(repl_backlog_size)、以及主节点当前偏移量(master_repl_offset) -
redis-cli config get repl-backlog-size看配置值是否生效(注意:config set 是运行时生效,但重启后会丢失,除非写进redis.conf) - 对比从节点的
slave_repl_offset(同样在info replication输出里)和主节点的master_repl_offset差值;如果差值 >repl_backlog_size,那必然全量
例如:主节点 master_repl_offset=124890000,从节点 slave_repl_offset=124780000,差值为 110000 字节 ≈ 107KB;而 repl_backlog_size=1048576(1MB),看起来够——但这是静态快照。真实瓶颈常出现在闪断期间的突发写入,导致缓冲区被快速填满并覆盖。
repl-backlog-size 设多大才安全
不能拍脑袋定 1GB。要结合你的最大中断容忍时长 × 峰值写入吞吐量来算:
- 先用
redis-cli --latency-history -i 1观察网络延迟毛刺频率和持续时间,取常见中断上限(比如 95% 分位是 45 秒) - 再用
redis-cli --stat或监控系统(如 Prometheus + redis_exporter)查过去 1 小时内每秒写命令字节数峰值(关注used_memory_rss增速和instantaneous_ops_per_second的乘积) - 公式:
repl-backlog-size ≥ 中断容忍时长(秒) × 峰值写入字节数/秒。例如:容忍 60 秒中断,峰值写入 2MB/s → 至少设为125829120(120MB) - 线上建议留 1.5 倍余量,且不要超过 512MB(过大会拖慢 fork 性能,尤其在内存紧张时)
执行命令:config set repl-backlog-size 268435456(256MB),然后立刻验证:config get repl-backlog-size 必须返回相同数值,否则说明配置被拒绝(比如内存不足)。
网络闪断比你想象中更常见
云环境里,TIME_WAIT 连接堆积、安全组策略刷新、宿主机迁移、甚至某台机器的 systemd-resolved 服务卡住 DNS 解析,都可能造成看似“无异常”的秒级连接中断。这种中断不会报错,但从节点的 master_link_status:down 会在 info replication 里暴露。
- 检查从节点日志:搜
"Connection with master lost"和紧随其后的"Trying a partial resynchronization"是否失败 - 主节点看客户端连接数波动:
redis-cli info clients | grep connected_clients,闪断时会出现明显跌落再回升 - 用
tcpdump -i any port 6379 -w redis.pcap抓包分析重传和 RST 包,比单纯 ping 更准 - 临时缓解:把从节点的
repl-timeout从默认 60 秒调大到 120 秒(config set repl-timeout 120),给网络恢复留出缓冲,但治标不治本
真正稳定的主从,从来不是靠调大缓冲区硬扛,而是靠缩短中断窗口(比如用 Keepalive + 更激进的探测间隔)+ 控制单实例写入压力(拆 key、分片、读写分离粒度细化)——缓冲区只是最后一道保险,不是主干通路。
本文共计1218个文字,预计阅读时间需要5分钟。
根本原因并非主从断开了,而是从节点重连时,由于主节点上的主节点的位置无法找到,导致没有对应的偏移量。这通常发生在缓冲区太小或网络中断时间过长,导致缓冲区无法覆盖中断窗口的情况。
现象很典型:日志里反复出现 Partial resynchronization not possible (no cached master),接着就是 Starting BGSAVE for SYNC,CPU 和带宽瞬间拉高,从节点长时间不可用。
- 主节点的
repl-backlog-size默认只有 1MB,对中等以上流量(比如每秒写入 50KB)撑不过 20 秒 - 一次持续 30 秒的网络抖动(如交换机瞬断、云厂商 VPC 路由收敛),就足以让积压缓冲区被新命令覆盖掉旧数据
- 从节点重启或配置变更后重连,如果没保存好自己的
run_id和offset,也会被当成“全新从节点”强制全量
怎么确认是 repl-backlog-size 不够
别猜,直接查主节点当前状态和配置。重点看三个值是否匹配:
-
redis-cli info replication | grep -E "backlog|offset"查当前积压缓冲区实际使用长度(repl_backlog_active)、总大小(repl_backlog_size)、以及主节点当前偏移量(master_repl_offset) -
redis-cli config get repl-backlog-size看配置值是否生效(注意:config set 是运行时生效,但重启后会丢失,除非写进redis.conf) - 对比从节点的
slave_repl_offset(同样在info replication输出里)和主节点的master_repl_offset差值;如果差值 >repl_backlog_size,那必然全量
例如:主节点 master_repl_offset=124890000,从节点 slave_repl_offset=124780000,差值为 110000 字节 ≈ 107KB;而 repl_backlog_size=1048576(1MB),看起来够——但这是静态快照。真实瓶颈常出现在闪断期间的突发写入,导致缓冲区被快速填满并覆盖。
repl-backlog-size 设多大才安全
不能拍脑袋定 1GB。要结合你的最大中断容忍时长 × 峰值写入吞吐量来算:
- 先用
redis-cli --latency-history -i 1观察网络延迟毛刺频率和持续时间,取常见中断上限(比如 95% 分位是 45 秒) - 再用
redis-cli --stat或监控系统(如 Prometheus + redis_exporter)查过去 1 小时内每秒写命令字节数峰值(关注used_memory_rss增速和instantaneous_ops_per_second的乘积) - 公式:
repl-backlog-size ≥ 中断容忍时长(秒) × 峰值写入字节数/秒。例如:容忍 60 秒中断,峰值写入 2MB/s → 至少设为125829120(120MB) - 线上建议留 1.5 倍余量,且不要超过 512MB(过大会拖慢 fork 性能,尤其在内存紧张时)
执行命令:config set repl-backlog-size 268435456(256MB),然后立刻验证:config get repl-backlog-size 必须返回相同数值,否则说明配置被拒绝(比如内存不足)。
网络闪断比你想象中更常见
云环境里,TIME_WAIT 连接堆积、安全组策略刷新、宿主机迁移、甚至某台机器的 systemd-resolved 服务卡住 DNS 解析,都可能造成看似“无异常”的秒级连接中断。这种中断不会报错,但从节点的 master_link_status:down 会在 info replication 里暴露。
- 检查从节点日志:搜
"Connection with master lost"和紧随其后的"Trying a partial resynchronization"是否失败 - 主节点看客户端连接数波动:
redis-cli info clients | grep connected_clients,闪断时会出现明显跌落再回升 - 用
tcpdump -i any port 6379 -w redis.pcap抓包分析重传和 RST 包,比单纯 ping 更准 - 临时缓解:把从节点的
repl-timeout从默认 60 秒调大到 120 秒(config set repl-timeout 120),给网络恢复留出缓冲,但治标不治本
真正稳定的主从,从来不是靠调大缓冲区硬扛,而是靠缩短中断窗口(比如用 Keepalive + 更激进的探测间隔)+ 控制单实例写入压力(拆 key、分片、读写分离粒度细化)——缓冲区只是最后一道保险,不是主干通路。

