Redis

Redis 主从同步完整深度详解

·9 分钟阅读·3596 字
📋 目录

Redis 主从同步完整深度详解

核心概念 Redis 主从同步是全量同步和增量同步的组合,psync2.0 实现断点续传,避免全量同步风暴。

1. 主从复制基础概念

1.1. 作用

  1. 数据副本:主节点写数据,从节点完整同步,实现数据冗余备份;
  2. 读写分离:主负责写,从分担读请求,提升并发承载;
  3. 高可用基础:哨兵、Redis Cluster 集群底层依赖主从复制实现故障切换。

1.2. 核心架构

  • Master(主节点):唯一可写入,接收客户端写指令;
  • Slave / Replica(从节点):只读,自动同步主全量+增量数据;
    支持链式复制:Master → Slave1 → Slave2(级联从库,减轻主同步压力)。

1.3. 两种同步模式

  1. 全量同步(RDB 同步):新从库初次连接、长时间断连差距过大,主生成RDB全量文件传输;
  2. 增量同步(缓冲区repl_backlog):短时间断开重连,仅同步断开期间积压的命令日志。

2. 底层核心组件

2.1. replication-id(复制标识)

每个Redis实例启动生成唯一 replid(40位字符串),标识一套完整数据集。

  • 主从 replid 一致代表属于同一复制链;
  • 主节点重启、执行 flushall 会生成新replid,从库触发全量同步。

2.2. offset 复制偏移量

主节点每执行一条写命令,自身master_repl_offset自增;
从库同步完命令后,记录自身slave_repl_offset
对比两者offset差值,判断需要同步多少增量数据。

2.3. repl_backlog 复制积压缓冲区(关键)

主节点开辟一块环形内存缓冲区,存放最近执行的写命令:

  • 容量由 repl-backlog-size 控制,默认1MB;
  • 从库短暂断开,offset差距在缓冲区范围内 → 只做增量同步;
  • 断开太久,offset超出缓冲区 → 强制全量同步;

生产建议调大至64MB/128MB,避免频繁全量同步。

2.4. 从库复制缓冲区(client-output-buffer)

主给每个连接的从库单独分配输出缓冲区,同步RDB、增量命令时存放临时数据;
缓冲区溢出会直接断开主从,触发重同步,需调大:

client-output-buffer-limit slave 256mb 64mb 60

3. 完整主从同步全流程(新从库初次接入)

3.1. 阶段1:握手协商(建立TCP连接)

  1. 从库配置 replicaof 主IP 6379,主动发起TCP 6379连接主节点;
  2. 从发送 PING,主回复PONG,校验连通;
  3. 从发送 REPLCONF listening-port XXXX 上报自身端口;
  4. 从发送 REPLCONF capa eof capa psync2 协商新版同步协议PSYNC2;
  5. 从发送 PSYNC replid offset
  • 首次连接无历史数据:PSYNC ? -1
  • 断线重连:带上原有replid和自身offset

3.2. 阶段2:主判断同步方式

  1. replid 和主不一致 / offset超出backlog缓冲区:执行全量同步
  2. 若replid匹配、offset存在于backlog:执行增量同步,直接补发缺失命令,流程结束。

3.3. 阶段3:全量同步完整步骤

  1. 主执行 bgsave 后台生成当前全量RDB持久化文件;
  2. RDB生成期间,新写入的命令持续存入repl_backlog与该从库专属输出缓冲区;
  3. RDB文件通过TCP流式传输给从节点;
  4. 从库接收完成后:
  • 清空自身原有所有数据;
  • 加载RDB文件,恢复完整主节点快照数据;
  1. 主开始传输RDB生成期间积压在缓冲区的增量写命令;
  2. 从逐条执行增量命令,追上主当前offset;
  3. 同步完成,进入持续增量同步阶段:主每一条写命令实时同步发给从。

3.4. 阶段4:持续增量同步(稳定运行阶段)

主执行任何写命令(set/hset/lpush等):

  1. 命令先写入自身内存;
  2. 同步写入repl_backlog环形缓冲区;
  3. 异步发送给所有在线从库;
  4. 从接收并回放命令,保持数据与主完全一致。

4. PSYNC1 vs PSYNC2 协议区别

  1. PSYNC1(Redis 2.8 ~ 4.0)
    只支持简单增量,主重启后replid变更,强制全量同步。
  2. PSYNC2(Redis 5.0+ 默认)
    新增第二复制ID replid2,主重启会保存上一版replid到replid2;
    从库重连时带上旧replid,主可复用历史backlog,避免不必要全量同步,大幅优化稳定性。

5. 链式主从复制 Master → S1 → S2

  1. S1作为Master的从,同时作为S2的主;
  2. Master只同步一份数据流给S1,由S1分发同步给下游从库;
  3. 优势:大量从库场景减轻主节点网络、CPU压力;
  4. 风险:S1宕机,下游S2同步中断;层级越多同步延迟越高。

6. 主从数据一致性与复制策略

6.1. 同步复制策略(replica-sync-mode)

6.1.1. (1)异步复制(默认)

主写完本地内存立即返回客户端成功,异步发给从;
优势:主写入性能极高;
风险:主宕机,已写入主但未同步到从的数据丢失。

6.1.2. (2)半同步复制(replica_wait_acks)

开启 min-replicas-to-write N + min-replicas-max-lag 10
主写入成功后,等待至少N个从库ack确认同步完成,才返回客户端;
折中方案,平衡性能与数据安全,生产建议开启。

6.2. 从库只读控制

默认 replica-read-only yes,禁止从库写入,避免主从数据分裂;
业务读写分离只读查询走从,写统一走主。

7. 主从同步常见故障&原因

7.1. 频繁全量同步

  • repl-backlog-size 缓冲区过小;
  • 网络波动大,从频繁断开重连;
  • 主节点重启生成新replid;
  • 从库输出缓冲区溢出断开连接。
    优化:调大backlog、调大slave输出缓冲区、稳定机房网络。

7.2. 主从数据不一致

  1. 人为在从库执行写操作(关闭replica-read-only);
  2. 主开启RDB/AOF持久化失败,内存数据丢失重启;
  3. 网络丢包、同步命令截断;
  4. 低版本Redis同步BUG。

7.3. 主从断开同步

  1. 防火墙/安全组拦截6379端口;
  2. 主从时间不同步、TCP心跳超时;
  3. 输出缓冲区超限,主主动踢掉从库;
  4. 内存打满触发OOM杀死Redis进程。

7.4. 同步延迟过高

  1. 主写入QPS极高,单从库同步线程追赶不上;
  2. 从库磁盘性能差,回放命令刷盘慢;
  3. 链式复制层级过多;
  4. 主CPU耗尽,无法及时分发同步命令。

8. 生产优化最佳实践

  1. 调大repl-backlog-size,根据写入量设64M~128M,减少全量同步;
  2. 调整slave客户端输出缓冲区,避免同步连接被断开;
  3. 开启半同步min-replicas-to-write,降低数据丢失风险;
  4. 主节点必须开启持久化RDB+AOF,防止重启数据清空;
  5. 读写分离查询分摊至从库,降低主压力;
  6. 多从库场景使用链式复制,减轻主网络IO;
  7. 监控指标:master_repl_offsetslave_repl_offset、复制延迟、同步状态;
  8. 禁止手动在从库执行写命令,保持replica-read-only开启。

9. 主从复制与哨兵/集群的关系

  1. 哨兵Sentinel:基于主从,监控所有节点,主故障自动提升最优从为新主,自动切换其余从复制新主;
  2. Redis Cluster:每个分片内部一套主从,分片间通过槽位分片,主从负责分片数据备份与读分离。

10. 面试核心速记总结

  1. 主从同步分全量RDB同步增量backlog同步
  2. 核心标识:replid复制ID、offset偏移量、repl_backlog环形缓冲区;
  3. 新从库完整流程:TCP握手协商PSYNC → 全量RDB传输加载 → 回放积压增量命令 → 持续异步同步;
  4. PSYNC2支持主重启后复用旧缓冲区,减少全量同步;
  5. 复制模式:异步(高性能)、半同步(数据更安全);
  6. 高频问题:频繁全量同步根源是backlog过小/网络不稳定;
  7. 链式复制减轻主压力,但会增加同步延迟;
  8. 哨兵、集群均依赖主从复制实现数据冗余与故障切换。

关联文档