4. Redis 主从复制机制:全量复制与增量复制

Redis 主从复制是构建读写分离架构的基石。主节点(Master)负责处理写请求,从节点(Slave)通过复制机制同步数据,承担读请求。理解全量复制与增量复制的触发条件、流程及核心数据结构(复制偏移量、复制积压缓冲区),是设计高可用缓存系统的必备知识。

4.1 复制核心数据结构

在深入复制流程前,必须先掌握两个关键概念:复制偏移量和复制积压缓冲区。它们是增量复制能够高效工作的基础。

概念 位置 作用 关键特征
复制偏移量(Replication Offset) 主节点和从节点各自维护 记录主从复制的字节进度 主节点每发送 N 字节数据,偏移量 +N;从节点每接收 N 字节,偏移量 +N
复制积压缓冲区(Replication Backlog) 主节点内存中的环形缓冲区 缓存最近写入的命令数据,用于增量复制 固定大小(默认 1MB),可配置;当从节点断连后重新连接时,若偏移量仍在缓冲区内,则执行增量复制
设计要点:复制积压缓冲区的大小直接影响增量复制的成功率。如果缓冲区太小,从节点断连时间稍长,偏移量就会超出缓冲区范围,被迫触发全量复制。建议根据网络抖动容忍时间和写入吞吐量计算:buffer_size = 2 * (平均写入速率 × 最大容忍断连时间)。

4.2 全量复制(Full Resynchronization)

全量复制是主从节点建立复制关系或增量复制无法进行时的兜底方案。它传输整个数据集,资源消耗大,应尽量避免频繁触发。

触发场景

  • 从节点首次连接主节点。
  • 从节点断连时间过长,复制偏移量已不在主节点的复制积压缓冲区中。
  • 主节点主动触发 replconf sync 或从节点发起 SLAVEOF 命令。

全量复制流程(6 个步骤)

  1. 建立连接:从节点向主节点发送 PSYNC ? -1 命令,表示请求全量同步。
  2. 主节点响应:主节点返回 +FULLRESYNC <runid> <offset>,告知从节点主节点的运行 ID 和当前偏移量。
  3. 生成 RDB:主节点执行 bgsave 生成 RDB 快照文件。此过程不阻塞主节点正常服务。
  4. 传输 RDB:主节点将 RDB 文件发送给从节点。从节点清空旧数据,加载 RDB 文件。
  5. 缓冲增量命令:在 RDB 生成和传输期间,主节点将新写入的命令写入复制积压缓冲区,并发送给从节点。
  6. 增量同步:从节点加载完 RDB 后,主节点将缓冲区的增量命令发送给从节点,最终达到数据一致。
性能影响:全量复制期间,主节点需要执行 bgsave(fork 子进程,可能触发 COW 内存翻倍),并占用大量网络带宽传输 RDB 文件。从节点在加载 RDB 时会阻塞所有客户端请求。生产环境中应严格控制全量复制的频率。
Redis 全量复制流程 全量复制流程(6 步) 主节点(Master) 从节点(Slave) ① PSYNC ? -1 ② +FULLRESYNC runid offset ③ bgsave 生成 RDB ④ 传输 RDB 文件 ⑤ 缓冲增量命令 ⑥ 发送缓冲增量命令 清空旧数据 + 加载 RDB

4.3 增量复制(Partial Resynchronization)

增量复制是 Redis 主从复制的理想模式。当从节点断连后重新连接,如果复制偏移量仍在主节点的复制积压缓冲区范围内,则只需同步缺失的增量数据,无需全量传输。

触发条件

  • 从节点断连后重新发起 PSYNC <runid> <offset> 命令。
  • 主节点检查从节点发送的 runid 与自身一致,且 offset 在复制积压缓冲区中。

增量复制流程

  1. 从节点发送 PSYNC:从节点向主节点发送 PSYNC <master_runid> <slave_offset>。
  2. 主节点校验:主节点比较 runid 和 offset。如果 offset 在复制积压缓冲区中,返回 +CONTINUE。
  3. 发送增量数据:主节点从复制积压缓冲区中读取 slave_offset 之后的数据,发送给从节点。
  4. 从节点接收:从节点接收增量数据并更新本地偏移量,继续提供服务。
关键配置:增量复制的成功率完全取决于 repl-backlog-size 参数。如果从节点断连期间主节点写入的数据量超过缓冲区大小,则增量复制失败,自动降级为全量复制。建议将缓冲区大小设置为 峰值写入速率 × 最大容忍断连时间 × 2。
增量复制与全量复制决策流程 增量复制 vs 全量复制决策树 从节点断连后重连 发送 PSYNC runid offset 全量复制(FULLRESYNC) offset 不在缓冲区 / runid 不匹配 增量复制(+CONTINUE) offset 在缓冲区且 runid 匹配 增量复制:仅同步缺失数据,效率高,不阻塞服务 全量复制:传输整个 RDB,资源消耗大,应尽量避免

4.4 复制偏移量与积压缓冲区深度解析

复制偏移量(Replication Offset)

每个 Redis 实例(主/从)都维护一个 master_repl_offset。主节点每向从节点发送一个字节的数据,偏移量就增加 1。从节点每接收一个字节,偏移量也增加 1。通过对比主从偏移量,可以快速判断数据同步的滞后程度。

# 查看主节点偏移量
redis-cli -h master_host info replication | grep master_repl_offset
master_repl_offset:123456789

# 查看从节点偏移量
redis-cli -h slave_host info replication | grep slave_repl_offset
slave_repl_offset:123456789

复制积压缓冲区(Replication Backlog)

主节点维护一个固定大小的环形缓冲区,用于存储最近写入的命令。缓冲区由三个关键参数控制:

参数 默认值 说明 建议
repl-backlog-size 1MB 缓冲区大小 根据写入吞吐量调整,建议 64MB~512MB
repl-backlog-ttl 3600 秒 缓冲区存活时间(无从节点时) 保持默认或适当延长
repl-backlog-hist-len 自动计算 缓冲区中实际存储的数据长度 只读属性,用于监控
监控命令:使用 redis-cli info replication 可以查看主从偏移量差值和缓冲区状态。重点关注 master_repl_offset 和 slave_repl_offset 的差值,如果持续增大,说明从节点同步滞后严重,需要排查网络或从节点性能问题。

4.5 主从复制配置实战

以下是一个典型的主从复制配置示例,包含增量复制优化参数:

# redis.conf - 主节点配置
# 开启持久化,保证重启后数据不丢失
save 900 1
save 300 10
save 60 10000

# 复制积压缓冲区大小(关键参数)
repl-backlog-size 128mb

# 缓冲区存活时间(秒)
repl-backlog-ttl 7200

# 从节点超时时间(秒)
repl-timeout 60

# 从节点配置(slave.conf)
# 指定主节点地址
replicaof master_host 6379

# 从节点只读(默认开启)
replica-read-only yes

# 从节点是否写入磁盘(建议 yes,防止内存溢出)
replica-diskless-sync no

4.6 常见问题与避坑指南

  • 全量复制风暴:多个从节点同时断连并重连,导致主节点同时执行多次 bgsave 和 RDB 传输,CPU 和网络带宽瞬间打满。解决方案:设置 repl-backlog-size 足够大,避免从节点断连后触发全量复制;或使用 replica-serve-stale-data yes 让从节点在同步期间继续提供旧数据服务。
  • 复制偏移量不一致:主从偏移量长期不一致,可能是网络延迟或从节点性能不足导致。使用 redis-cli --latency 检测网络延迟,并确保从节点有足够的 CPU 和内存资源。
  • 缓冲区溢出:如果 repl-backlog-size 设置过小,从节点短暂断连就会触发全量复制。建议根据业务写入量动态调整,并设置告警监控 master_repl_offset 与 slave_repl_offset 的差值。
最佳实践:在读写分离架构中,建议至少部署 2 个从节点,并配置 repl-backlog-size 为 256MB 以上。同时,使用 redis-sentinel 或 redis-cluster 实现自动故障转移,避免主节点宕机导致写入不可用。