4. Redis 主从复制:主从架构原理、全量复制与增量复制、复制偏移量与积压缓冲区

主从复制是 Redis 高可用架构的基石,也是实现读写分离缓存一致性的核心机制。本章深入剖析主从复制的底层原理,包括架构拓扑、全量与增量复制流程、以及关键的偏移量与积压缓冲区机制。

4.1 主从架构原理与拓扑

Redis 主从复制采用 一主多从 的星型拓扑。主节点(Master)负责处理写请求,从节点(Slave)通过复制主节点的数据来提供读服务。这种架构实现了数据的冗余备份与读写流量的分离。

核心原则: 主节点是唯一写入点,从节点默认只读(slave-read-only yes)。主节点将写操作异步或半同步地传播到从节点,保证最终一致性。

4.1.1 主从复制拓扑结构

Redis 主从复制拓扑结构 Master 主节点(读写) Slave-1 从节点(只读) Slave-2 从节点(只读) Slave-3 从节点(只读) 复制方向:Master → Slave(单向) 写请求必须发往 Master,读请求可分散到任意 Slave

4.1.2 主从复制核心配置

配置项 作用 默认值
replicaof <masterip> <masterport> 设置从节点的主节点地址 无
slave-read-only yes 从节点只读,防止误写入 yes
repl-backlog-size 1mb 积压缓冲区大小,影响增量复制能力 1MB
repl-timeout 60 复制超时时间(秒) 60

4.2 全量复制(Full Resynchronization)

全量复制发生在从节点首次连接主节点,或从节点与主节点断开过久导致增量复制无法继续时。这是数据量最大、耗时最长的复制阶段。

4.2.1 全量复制流程

  1. 从节点发起连接: 从节点向主节点发送 PSYNC ? -1 命令,请求全量同步。
  2. 主节点生成 RDB: 主节点执行 bgsave 生成 RDB 快照文件,同时将新写入命令缓存到复制积压缓冲区。
  3. 传输 RDB: 主节点将 RDB 文件发送给从节点,从节点清空旧数据并加载 RDB。
  4. 发送缓冲区数据: 主节点将 RDB 生成期间缓存的写命令发送给从节点。
  5. 建立增量复制: 从节点开始接收并执行主节点的持续写命令流,进入增量复制阶段。
性能风险: 全量复制对主节点 CPU(bgsave)、网络带宽(RDB 传输)、内存(复制积压缓冲区)均有较大消耗。生产环境应避免多个从节点同时发起全量复制。

4.2.2 全量复制触发条件

触发场景 说明
首次连接 从节点从未复制过该主节点
断连超时 从节点断开时间超过 repl-backlog-ttl,积压缓冲区数据被覆盖
复制偏移量不匹配 从节点发送的偏移量不在主节点积压缓冲区范围内
手动触发 执行 REPLICAOF NO ONE 后重新 REPLICAOF

4.3 增量复制(Partial Resynchronization)

增量复制是 Redis 主从复制的核心优化,用于处理从节点短暂断开后的数据同步,避免全量复制的巨大开销。

4.3.1 增量复制核心机制

增量复制依赖两个关键组件:复制偏移量(Replication Offset) 和 复制积压缓冲区(Replication Backlog)。

  • 复制偏移量: 主节点和从节点各自维护一个单调递增的字节偏移量,记录已复制的数据位置。主节点偏移量(master_repl_offset)表示主节点已发送的总字节数;从节点偏移量(slave_repl_offset)表示从节点已接收并执行的字节数。
  • 复制积压缓冲区: 主节点维护一个固定大小的环形缓冲区(默认 1MB),缓存最近写入的命令。当从节点断连后重新连接,主节点检查从节点偏移量是否仍在缓冲区范围内,若是则只发送缺失部分。

4.3.2 增量复制流程

增量复制流程与偏移量校验 Master master_repl_offset = 102400 积压缓冲区:[80000 ~ 102400] Slave slave_repl_offset = 90000 缺失数据:[90001 ~ 102400] PSYNC 90000 校验结果:90000 在 [80000 ~ 102400] 范围内 执行增量复制,发送缺失数据 CONTINUE + 增量数据(12400 字节) 若 slave_repl_offset 小于积压缓冲区起始偏移量,则触发全量复制

4.3.3 增量复制关键参数

参数 默认值 优化建议
repl-backlog-size 1MB 根据网络波动时长 × 写入速率估算。例如:网络中断 30s,写入速率 10MB/s,则 backlog 应 ≥ 300MB
repl-backlog-ttl 3600s 从节点断连后,积压缓冲区保留时间。超时后释放内存
repl-timeout 60s 主从之间心跳超时时间,影响断连检测速度

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

4.4.1 复制偏移量工作机制

主节点每向从节点发送 N 字节数据,master_repl_offset 就增加 N。从节点每接收并执行 N 字节数据,slave_repl_offset 也增加 N。通过对比两个偏移量,可以精确判断主从数据差异。

监控命令:
redis-cli info replication 输出中查看:
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.1.10,port=6379,state=online,offset=102400,lag=0
slave1:ip=192.168.1.11,port=6379,state=online,offset=102400,lag=0
master_repl_offset:102400
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:80000
repl_backlog_histlen:24400

4.4.2 积压缓冲区环形结构

积压缓冲区是一个固定大小的环形字节数组。主节点持续将写命令写入缓冲区尾部,当缓冲区写满时,新数据覆盖最旧的数据。因此,缓冲区只保留最近一段时间内的写操作。

  • repl_backlog_first_byte_offset: 缓冲区中第一个字节对应的全局偏移量。
  • repl_backlog_histlen: 缓冲区中当前有效数据的长度。
  • 有效范围: [repl_backlog_first_byte_offset, repl_backlog_first_byte_offset + repl_backlog_histlen - 1]

4.4.3 偏移量校验决策树

从节点偏移量状态 主节点决策 原因
偏移量在缓冲区范围内 增量复制(CONTINUE) 只需发送缺失的增量数据
偏移量小于缓冲区起始偏移量 全量复制(FULLRESYNC) 从节点数据太旧,缓冲区已覆盖
偏移量大于主节点当前偏移量 全量复制(FULLRESYNC) 从节点偏移量异常,可能为错误状态
从节点发送 PSYNC ? -1 全量复制(FULLRESYNC) 从节点无任何复制历史

4.5 主从复制一致性保障实践

最佳实践:
  • 合理设置 backlog 大小: 根据业务写入峰值和网络波动时长计算。公式:repl-backlog-size = 平均写入速率 × 最大容忍断连时间 × 2(留有余量)。
  • 监控复制延迟: 使用 INFO replication 中的 lag 字段,正常情况下 lag ≤ 1s。若 lag 持续增大,需排查网络或主节点负载。
  • 避免全量复制风暴: 多个从节点同时重连时,使用 repl-backlog-ttl 控制缓冲区保留时间,或采用树形复制拓扑(从节点级联复制)。
  • 读写分离一致性: 读请求允许读取到稍旧的数据(最终一致性)。若业务要求强一致读,需将读请求路由到主节点。

4.5.1 主从复制常见问题排查

问题现象 可能原因 解决方案
从节点一直处于 SYNC 状态 网络带宽不足,RDB 传输慢 压缩 RDB(rdbcompression yes),或升级网络
主节点内存持续增长 积压缓冲区过大或 bgsave 频繁 调整 repl-backlog-size,优化 bgsave 策略
从节点数据与主节点不一致 网络闪断导致部分命令丢失 检查 repl-timeout,增大 backlog 避免全量复制
主节点 CPU 飙升 多个从节点同时发起全量复制 错峰重启从节点,或使用级联复制