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+ 将主节点的 replid 和 repl_offset 持久化到 RDB 文件末尾!

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

效果:

  • 主节点重启后,从 RDB 中恢复 replid 和 offset
  • 从节点断连重连时,携带旧 replid 和 offset
  • 主节点发现 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:为什么总是全量同步?

  • 原因1 :repl-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(重启失效)

十、结语

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

相关推荐
honsor7 分钟前
以太网温湿度传感器:RJ45直连机房的环境监控新方案
运维·网络·数据库·物联网·安全·云计算·github
西索斯coding8 分钟前
Kimi k2.7-code-highspeed 接入 Cline 教程:baseURL 路由变更 + model_id 正确写法
java·服务器·数据库·ai
szial17 分钟前
JavaScript 的 call、apply 和 bind:如何控制函数调用
开发语言·前端·javascript
浪子明X23 分钟前
MongoDB 迁移方案评审:用双写窗口和回放样本控制切换风险
数据库·mongodb
stark张宇27 分钟前
InnoDB锁机制全景图:全局锁、表锁、行锁、意向锁到底怎么用?
数据库·后端
CopyCode29 分钟前
Agent 开发不是模型训练:一个前端的入门认知
前端·llm·agent
坊钰37 分钟前
【LangChain框架入门级】10. 文本向量与向量数据库(Embedding / Redis / Pinecone / MMR)
数据库·python·langchain·embedding
吠品39 分钟前
HTTPS 真身:HTTP 套了层 TLS
java·服务器·前端
JYeontu42 分钟前
实现一个「曲线滑块验证」功能
前端·javascript·html
Csvn43 分钟前
组件库(从 API 契约到 Headless 内核)
前端