前置知识: Redis

主从复制缓冲区

00:00
2 min Advanced 2026/6/14

Redis 主从复制缓冲区机制:repl_backlog 环形缓冲区、全量同步与部分同步、缓冲区溢出与配置优化。

1. 复制缓冲区体系

1.1 三种复制缓冲区

缓冲区位置作用大小
repl_backlog存储最近写命令支持部分同步默认 1MB
replication buffer为每个从维护的输出缓冲区动态增长
replication backlog接收数据的临时缓冲动态

1.2 数据流

主库写入命令 → repl_backlog(环形缓冲)
             → replication buffer(每从库一个)
                 ↓ 网络传输
             从库接收 → 执行命令

2. repl_backlog 环形缓冲区

2.1 结构

repl_backlog 是一个定长环形缓冲区:

┌──────────────────────────────────────────┐
│  [cmd1][cmd2][cmd3]...[cmdN]             │
│     ↑                              ↑     │
│  repl_backlog_histlen         repl_backlog_idx
│  (有效数据起始)               (写入位置)
└──────────────────────────────────────────┘
  总大小: repl_backlog_size (默认1MB)

新数据写入 repl_backlog_idx 位置
写满后环绕到开头,覆盖最旧的数据

2.2 全局偏移量

repl_backlog_off: 缓冲区起始位置对应的全局偏移量
master_repl_offset: 主库当前的全局偏移量

有效数据范围: [repl_backlog_off, master_repl_offset]

2.3 部分同步(PSYNC)

从库断线重连时:
1. 发送 PSYNC {runid} {offset}
   - runid: 主库运行ID
   - offset: 从库最后收到的偏移量

2. 主库判断:
   - runid 匹配 且 offset 在 backlog 范围内 → 部分同步
   - 否则 → 全量同步

部分同步:
  主库从 backlog 中提取 [offset, master_repl_offset] 的数据
  发送给从库

2.4 部分同步判断

条件: offset >= repl_backlog_off

如果 offset < repl_backlog_off:
  说明从库缺失的数据已被覆盖 → 全量同步

示例:
  repl_backlog_size = 1MB
  repl_backlog_off = 1000000
  master_repl_offset = 1100000

  从库 offset = 1050000 → 1050000 >= 1000000 → 部分同步
  从库 offset = 900000  → 900000 < 1000000  → 全量同步

3. replication buffer

3.1 作用

为每个从维护一个独立的输出缓冲区,暂存发送的写命令

主库
├── replication buffer for slave1
├── replication buffer for slave2
└── replication buffer for slave3

3.2 缓冲区溢出

当从消费速慢于主写入速时,buffer 持续增长

写入速度: 100MB/s
从库消费: 10MB/s
每秒积压: 90MB

1分钟后: 5.4GB → 触发内存限制 → 从库被断开

3.3 缓冲区限制配置

# 客户端输出缓冲区限制(包括从库)
# 格式: client-output-buffer-limit <class> <hard> <soft> <soft_seconds>

# 从库缓冲区:硬限制 256MB,软限制 64MB 持续 60秒
client-output-buffer-limit replica 256mb 64mb 60

# 普通客户端
client-output-buffer-limit normal 0 0 0

# Pub/Sub 客户端
client-output-buffer-limit pubsub 32mb 8mb 60

触发断开条件

  • 缓冲区超过硬限制 → 立即断开
  • 缓冲区超过软限制持续 N 秒 → 断开

4. 全量同步流程

4.1 触发条件

  • 首次连接
  • 发送的 runid 不匹配
  • 请求的 offset 已被 backlog 覆盖

4.2 全量同步步骤

1. 从库发送 PSYNC ? -1(请求全量同步)
2. 主库执行 BGSAVE 生成 RDB
3. 主库将 RDB 发送给从库
4. 主库同时将新写入命令存入 replication buffer
5. 从库接收 RDB 后清空数据并加载
6. 主库发送 replication buffer 中的增量命令
7. 从库执行增量命令,数据一致

4.3 全量同步开销

BGSAVE: fork 子进程,COW 写时复制
RDB 传输: 网络带宽
从库加载: 阻塞服务(加载期间不可用)
增量缓冲: 内存占用

5. 配置优化

5.1 repl_backlog 大小

# 根据写入速度和断线时间估算
# 假设: 写入速度 10MB/s,最大断线时间 60s
# backlog 大小 >= 10MB/s × 60s = 600MB

repl-backlog-size 600mb

计算公式

5.2 关键参数

# repl_backlog 大小
repl-backlog-size 256mb

# repl_backlog TTL(无从库时多久删除)
repl-backlog-ttl 3600

# 从库发送 PING 的频率
repl-ping-replica-period 10

# 复制超时(包括SYNC、PING)
repl-timeout 60

# 禁用 TCP_NODELAY(启用后延迟更低但带宽更大)
repl-disable-tcp-nodelay no

# 从库优先级(Sentinel 选举用)
replica-priority 100

5.3 监控命令

# 主库查看复制信息
INFO replication

# 关键指标:
# repl_backlog_active: 1
# repl_backlog_size: 268435456
# repl_backlog_first_byte_offset: 12345
# repl_backlog_histlen: 268435400
# connected_slaves: 3
# master_repl_offset: 9999999

知识检测

学习进度

-- 已学文档
--% 知识覆盖率

学习推荐

专注模式