Redis主从-主从数据同步原理

一、前言:主从同步不是"简单拷贝"

很多开发者认为 Redis 主从同步就是"主节点把数据发给从节点",

真正的挑战在于

  • 如何在不停写的情况下完成全量同步?
  • 网络闪断后,如何避免重新全量同步
  • 从节点如何精确追上主节点的最新状态

Redis 通过 PSYNC 协议(Partial Synchronization) 实现了高效、可靠的复制机制。

本文将带你深入源码级实现,揭开主从同步背后的精妙设计。


二、主从同步的核心目标与演进

目标

让从节点(Replica)的数据状态最终与主节点(Master)完全一致,且对主节点性能影响最小。

协议演进

版本 协议 缺陷
Redis 2.8 之前 SYNC 每次断连都全量同步,效率极低
Redis 2.8 ~ 3.x PSYNC1 支持部分重同步,但主节点重启后仍需全量
Redis 4.0+ PSYNC2 支持主节点重启后的部分重同步(终极方案)

本文聚焦 PSYNC2(现代 Redis 默认协议)


三、主从同步全流程(含状态机)

整个过程分为两个阶段:

  1. 全量复制(Full Resynchronization)
  2. 增量复制(Partial Resynchronization)

四、阶段一:全量复制(首次同步 or PSYNC 失败)

触发场景

  • 从节点首次连接主节点
  • 主从断连太久,复制积压缓冲区已覆盖所需数据
  • 主节点重启且未开启 replid 持久化(旧版)

关键设计点

4.1 复制客户端(Replication Client)
  • 主节点为每个从节点创建一个虚拟客户端
  • BGSAVE 开始,所有写命令都会额外发送一份给该客户端
  • 命令暂存在客户端输出缓冲区,待 RDB 发送完成后立即推送

保证全量同步期间的数据不丢失

4.2 复制积压缓冲区(Replication Backlog)
  • 主节点维护一个固定长度的环形缓冲区(默认 1MB)
  • 存储最近执行的写命令(RESP 格式)
  • 用于后续部分重同步

配置项:

复制代码
repl-backlog-size 1mb  # 可根据网络稳定性调整(如 100mb)

五、阶段二:增量复制(PSYNC 成功)

5.1 核心机制:偏移量(offset) + 复制 ID(replid)

  • master_repl_offset:主节点已发送的字节数(全局递增)
  • slave_read_repl_offset:从节点已接收的字节数
  • master_replid:主节点的唯一标识(40 字节十六进制字符串)

📌 只要 replid 相同 + offset 在 backlog 范围内 → 可部分重同步

5.2 PSYNC2 的突破:持久化 replid

Redis 4.0+ 将主节点的 replidrepl_offset 持久化到 RDB 文件末尾

复制代码
RDB 文件结构:
[REDIS][...数据...][EOF][aux: repl-id=abc123][aux: repl-offset=12345]

效果

  • 主节点重启后,从 RDB 中恢复 replidoffset
  • 从节点断连重连时,携带旧 replidoffset
  • 主节点发现 replid 匹配 → 直接从 backlog 补发缺失命令!

彻底解决"主节点重启导致全量同步"的历史难题


六、PSYNC 命令交互详解

6.1 从节点发起同步

bash 复制代码
# 首次连接 or 不知道主状态
PSYNC ? -1

# 断连重连(携带上次的 replid 和 offset)
PSYNC abc123 12345

6.2 主节点响应

响应 含义 后续动作
+FULLRESYNC <replid> <offset> 需全量同步 从节点准备接收 RDB
+CONTINUE 可部分重同步 从节点准备接收增量命令
-ERR ... 协议错误 降级到 SYNC(旧版)

七、关键配置参数与调优

参数 默认值 说明 生产建议
repl-backlog-size 1mb 复制积压缓冲区大小 高延迟网络设为 100~500mb
repl-timeout 60s 复制超时时间 根据网络质量调整
client-output-buffer-limit replica 256mb 从节点输出缓冲区限制 避免大 Key 导致主 OOM
repl-diskless-sync no 是否无盘复制 SSD 环境可开启,减少磁盘 IO

💡 无盘复制(Diskless Replication)

RDB 直接通过 socket 发送给从节点,不落盘,适合高性能 SSD 环境。


八、主从同步的可靠性保障

8.1 心跳机制

  • 从节点每秒发送 REPLCONF ACK <offset> 给主节点
  • 主节点据此更新 slave_ack_offset,用于:
    • 计算从节点延迟(lag = master_offset - slave_ack_offset
    • min-replicas-to-write 安全写入控制

8.2 安全写入(防脑裂)

复制代码
# 至少有 1 个从节点在线且延迟 < 10 秒,才允许写入
min-replicas-to-write 1
min-replicas-max-lag 10

避免主节点网络分区时继续写入导致数据不一致


九、常见问题与排查

❓ Q1:为什么总是全量同步?

  • 原因1repl-backlog-size 太小,断连期间数据被覆盖
  • 原因2:主节点重启(旧版 Redis)
  • 排查INFO replication 查看 master_replid 是否变化

❓ Q2:主从延迟(lag)很高?

  • 可能原因
    • 从节点磁盘慢(加载 RDB 慢)
    • 网络带宽不足
    • 主节点写入突增(大 Key、FLUSHALL)
  • 优化 :增大 repl-backlog-size,升级从节点硬件

❓ Q3:从节点无法写入?

  • 正常现象 :从节点默认 replica-read-only yes
  • 如需写 (如临时调试):CONFIG SET replica-read-only no(重启失效)

十、结语

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

相关推荐
a1117762 小时前
Markdown生成思维导图(html 开源)
前端·开源·html
我命由我123452 小时前
React - state、state 的简写方式、props、props 的简写方式、类式组件中的构造器与 props、函数式组件使用 props
前端·javascript·react.js·前端框架·html·html5·js
钰衡大师2 小时前
Vue 3 源码学习教程
前端·vue.js·学习
C澒2 小时前
React + TypeScript 编码规范|统一标准 & 高效维护
前端·react.js·typescript·团队开发·代码规范
霖霖总总2 小时前
[Redis小技巧7]Redis Bitmaps 深度解析:从原理到用户签到实战
数据库·redis·缓存
时光少年2 小时前
Android 视频分屏性能优化——GLContext共享
前端
Keanu-2 小时前
Redis 安装与部署
数据库·redis
我爱小疯喵喵3 小时前
2 常用数据库命令行操作
数据库
七夜zippoe3 小时前
Docker容器化实战:核心概念、镜像制作与多阶段构建全解析
java·jvm·数据库·docker·oracle·容器化