Redis主从-repl_backlog原理

一、前言:为什么主从断连后能快速恢复?

在 Redis 主从架构中,你是否曾好奇:

当从节点(slave)因网络抖动短暂断开后,为何能快速追上主节点(master)的数据,而无需全量同步(RDB)?

答案就在于 Redis 4.0 引入并优化的核心机制 ------ repl_backlog(复制积压缓冲区)

本文将带你:

✅ 深入 repl_backlog 的内存结构与工作原理

✅ 理解 PSYNC(部分重同步) 如何依赖它

✅ 掌握参数调优与故障排查方法

✅ 避免"主从全量同步风暴"导致服务雪崩


二、主从复制演进:从 SYNC 到 PSYNC

2.1 Redis 2.8 之前:SYNC(全量同步)

  • 从节点断连 → 重新连接 → 主节点生成 RDB 快照 → 全量传输
  • 问题:RDB 生成耗 CPU/IO,大实例同步慢(分钟级),带宽打满

2.2 Redis 2.8+:PSYNC(部分重同步)

  • 支持 Partial Resynchronization(部分重同步)
  • 核心依赖两个机制:
    1. replication ID + offset:唯一标识主从复制流
    2. repl_backlog:主节点维护的环形缓冲区,保存最近写命令

效果:从节点断连 10 秒后重连,只需同步断连期间的命令,毫秒级恢复!


三、repl_backlog 是什么?

3.1 定义

repl_backlog 是主节点在内存中维护的一个固定大小的环形缓冲区(circular buffer) ,用于存储最近执行的写命令(以 replication offset 为索引)。

3.2 核心作用

为断连的从节点提供"命令回溯"能力,避免全量同步

3.3 数据结构示意图

复制代码
主节点 repl_backlog(环形缓冲区)
┌───────────┬───────────┬───────────┬───────────┐
│ cmd@1001  │ cmd@1002  │ cmd@1003  │ cmd@1004  │ ← 写入指针 (master_repl_offset)
└───────────┴───────────┴───────────┴───────────┘
 ↑
 backlog 起始偏移 (repl_backlog_histlen)
  • 当缓冲区写满,旧命令被新命令覆盖(环形)
  • 每个从节点记录自己最后同步的 offset
  • 重连时,从节点上报 replication ID + offset,主节点判断是否在 repl_backlog 范围内

四、PSYNC 工作流程详解

4.1 正常同步流程

  1. 从节点启动,发送 PSYNC ? -1(首次同步)
  2. 主节点返回 FULLRESYNC <replication_id> <offset>
  3. 主节点生成 RDB 并传输,之后持续发送写命令

4.2 断连后重连(部分重同步)

  1. 从节点断连(如网络抖动 5 秒)
  2. 重连后发送 PSYNC <replication_id> <last_offset>(如 offset=1000)
  3. 主节点检查:
    • replication_id 是否匹配(防止主节点重启)
    • last_offset 是否 ≥ repl_backlog_start(即命令还在缓冲区中)
  4. 若满足 → 返回 +CONTINUE,并从 repl_backlog 中提取 offset+1 开始的命令发送
  5. 从节点接收命令并执行,完成同步

4.3 何时会触发全量同步?

以下任一条件成立,将 fallback 到 FULLRESYNC

  • replication ID 不匹配(主节点重启,ID 变更)
  • 从节点的 offset < repl_backlog_start(命令已被覆盖)
  • repl_backlog 被关闭(repl-backlog-size = 0

五、关键配置参数解析

参数 默认值 说明
repl-backlog-size 1MB repl_backlog 缓冲区大小
repl-backlog-ttl 3600 秒 主节点无从节点时,缓冲区保留时间(0=永久保留)

5.1 如何计算合理的 repl-backlog-size

公式:

复制代码
repl-backlog-size ≥ max(网络中断容忍时间 × 主节点写入吞吐量, 1MB)

举例

  • 业务可容忍从节点断连 5 分钟
  • 主节点写入峰值:10 MB/s
  • 则所需缓冲区 ≥ 5 × 60 × 10 = 3000 MB

💡 建议

  • 小型实例:默认 1~10MB 足够
  • 高写入场景:设为 100MB~1GB+
  • 多从节点环境:缓冲区由所有从节点共享,按最慢从节点计算

5.2 查看 repl_backlog 状态

bash 复制代码
127.0.0.1:6379> INFO REPLICATION
# Replication
role:master
connected_slaves:2
...
master_repl_offset:15000
repl_backlog_active:1
repl_backlog_size:1048576   # 1MB
repl_backlog_first_byte_offset:14000  # 缓冲区起始 offset
repl_backlog_histlen:1001   # 缓冲区实际数据长度
  • repl_backlog_first_byte_offset = master_repl_offset - repl_backlog_histlen + 1
  • 从节点 offset 必须 ≥ repl_backlog_first_byte_offset 才能部分同步

六、实战:模拟断连与恢复

6.1 场景:从节点断连 10 秒

bash 复制代码
# 主节点写入大量数据(模拟高负载)
while true; do redis-cli INCR counter; done

# 从节点断网(停 10 秒)
systemctl stop network

# 恢复网络
systemctl start network

6.2 观察日志

从节点日志

复制代码
* Reconnecting to MASTER 192.168.1.100:6379 after failure
* MASTER <-> REPLICA sync started
* Non blocking connect for SYNC fired the event.
* Master replied to PING
* Partial resynchronization request accepted. Sending reply.
* Successful partial resynchronization with master.

✅ 出现 Partial resynchronization 表示成功使用 repl_backlog

6.3 若缓冲区太小?

repl-backlog-size 过小,日志将显示:

复制代码
* Full resync requested by slave.
* Starting BGSAVE for SYNC with target: disk

→ 触发全量同步,服务可能卡顿!


七、生产环境最佳实践

✅ 1. 合理设置 repl-backlog-size

  • 监控主节点写入速率(INFO MEMORY + master_repl_offset 变化)
  • 最大可容忍断连时间 × 写入速率 × 1.5 安全系数 设置

✅ 2. 避免主节点频繁重启

  • 主节点重启会生成新的 replication ID,导致所有从节点全量同步
  • 使用 Redis Sentinel 或 Cluster 实现故障自动转移,而非直接重启主库

✅ 3. 监控关键指标

  • master_repl_offset 增长速度
  • repl_backlog_histlen 是否接近 repl_backlog_size
  • 从节点 lag(延迟)

✅ 4. 多从节点场景

  • 所有从节点共享同一个 repl_backlog
  • 同步最慢的从节点决定了缓冲区最小保留范围
  • 避免"慢从节点"拖垮主节点内存

八、常见误区澄清

❌ 误区 1:repl_backlog 是每个从节点独立的

正解:全局唯一,所有从节点共享同一个环形缓冲区

❌ 误区 2:repl_backlog 存储的是 RDB 数据

正解 :存储的是 写命令(如 SET、HSET)的原始协议数据,非 RDB

❌ 误区 3:增大 repl-backlog-size 会显著增加内存

正解 :是固定大小环形缓冲区,内存占用 = repl-backlog-size,可控


九、结语

感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!

相关推荐
Kethy__20 分钟前
计算机中级-数据库系统工程师-计算机体系结构与存储系统
大数据·数据库·数据库系统工程师·计算机中级
SHoM SSER22 分钟前
MySQL 数据库连接池爆满问题排查与解决
android·数据库·mysql
熬夜的咕噜猫1 小时前
MySQL备份与恢复
数据库·oracle
jnrjian1 小时前
recover database using backup controlfile until cancel 假recover,真一致
数据库·oracle
lifewange2 小时前
java连接Mysql数据库
java·数据库·mysql
大妮哟2 小时前
postgresql数据库日志量异常原因排查
数据库·postgresql·oracle
还是做不到嘛\.3 小时前
Dvwa靶场-SQL Injection (Blind)-基于sqlmap
数据库·sql·web安全
不写八个3 小时前
PHP教程004:php链接mysql数据库
数据库·mysql·php
Dylan~~~3 小时前
深度解析Cassandra:分布式数据库的王者之路
数据库·分布式
荒川之神4 小时前
Oracle HR 模式递归函数练习(基于 employees 表)
数据库·oracle