高级篇 08. 分布式缓存 - Redis 主从全量同步原理

4 阅读5分钟

📚 高级篇 08. 分布式缓存 - Redis 主从全量同步原理

一、 核心概念:大哥如何认出小弟?

在讲解同步流程前,必须先掌握两个极其关键的底层身份证号。如果没有它们,主从节点之间根本无法交流。

  1. Replication Id (简称 replid): 数据集的唯一标识。

    • 每个 Redis 启动时都会生成一个属于自己的唯一的 replid
    • 当小弟(Slave)认大哥(Master)成功后,小弟会把自己的 replid 修改为和大哥一模一样
    • 作用: Master 通过对比 replid,就能瞬间判断出“这个小弟是不是之前就跟着我混的”。如果不一样,说明是新来的,必须进行全量同步
  2. Offset (偏移量): 数据同步的进度条。

    • 随着 Master 不断接收新的写命令,它的 offset 会不断累加递增。
    • Slave 在拉取数据时,自己的 offset 也会跟着递增。
    • 作用: 如果 Master 的 offset 是 1000,Slave 的 offset 是 900,说明 Slave 落后了 100 个进度,需要补齐。

二、 全量同步的核心流程 (分为三个阶段)

触发时机: 通常发生在 Slave 第一次连接 Master,或者 Slave 宕机太久导致数据脱节极其严重时。

🚩 第一阶段:建立连接与协商同步

这是双方互换底牌的阶段,决定了接下来是大动干戈还是小修小补。

  1. 小弟请求同步: Slave 向 Master 发送 psync ? -1 命令。

    • ? 表示:我是新来的,我还不知道大哥你的 replid 是多少。
    • -1 表示:我是一张白纸,我的 offset 进度是未知的。
  2. 大哥判断身份: Master 收到命令,一看 replid?,立刻断定这是个纯萌新。

  3. 大哥下达指令: Master 回复 +FULLRESYNC <大哥的replid> <大哥目前的offset>

    • 意思就是:“确认执行全量同步!记住,从现在起,你的归属 ID 是这个,你要追赶的进度目标是这个。”
  4. 小弟领命: Slave 收到回复,立刻把大哥的 replidoffset 保存到自己的内存中。

🚩 第二阶段:RDB 核心数据传输

这是全量同步中最耗时、最核心的阶段。

  1. 大哥生成快照: Master 立刻在后台执行 bgsave 命令,利用 fork 子进程生成当前完整内存数据的 RDB 快照文件。(此时 Master 的主进程依然在飞速处理客户端的新写请求)。

  2. 发送快照: Master 将生成的 RDB 文件通过网络发送给 Slave。

  3. 小弟清空重载: Slave 收到 RDB 文件后,先清空自己本地的所有旧数据,然后把 RDB 文件加载到内存中。

    • 至此,小弟的数据状态恢复到了大哥执行 bgsave 那个精确的历史瞬间。

🚩 第三阶段:增量命令补偿 (极其精妙的防漏设计)

💥 致命漏洞填补:

在大哥执行 bgsave 生成 RDB、并把 RDB 传给小弟的这几秒甚至几十秒的时间差里,大哥又接收了无数个新的写命令。这些新命令根本不在 RDB 文件里!如果不管它们,小弟的数据就永远比大哥少一块。

  1. 大哥的记事本 (repl_baklog): 在第二阶段 bgsave 开始的那一刻起,Master 会把期间接收到的所有新写命令,全部悄悄记录到一个叫 repl_baklog (复制积压缓冲区) 的内存队列中。

  2. 发送补偿日志: 当小弟加载完 RDB 醒来后,Master 会把 repl_baklog 里的这些新命令打包发送给 Slave。

  3. 小弟执行追赶: Slave 收到这些命令,依次在自己的内存中执行一遍。

    • 完美闭环!至此,Slave 的数据终于和 Master 达到了百分之百的严丝合缝。

三、 秋招面试实战:高频拷问

🗣️ 面试官: “为什么 Master 同步给 Slave 时,要先耗费 CPU 和磁盘资源去生成 RDB,而不是直接把现有的数据转化为操作命令(AOF 格式)一条条发过去?”

💡 你的破局解析:

“这主要是出于网络带宽和恢复效率的极致考量。

如果直接发送命令流,对于一个存满了几 GB 数据的 Redis,其包含的命令数量是数以千万计的。不仅网络传输极其漫长,Slave 收到后单线程重放这千万条命令的速度也极其缓慢。

而 RDB 是经过极致压缩的二进制文件,体积非常小,网络传输极快。并且 Slave 加载 RDB 是直接按字节映射到内存的,恢复速度远超命令重放。全量同步的核心诉求就是‘快’,所以选择 RDB 作为全量同步的基石是最优解。”


学习总结

全量同步的过程是一场精密的分布式协同战役。它巧妙地结合了 RDB 快照(搞定历史存量数据)repl_baklog 积压缓冲区(搞定同步期间的增量数据) ,保证了数据在两端的一致性。


⚠️ 但是,请思考一个极其常见的生产事故:

如果小弟 7002 只是因为网络机房抖动,掉线了仅仅 3 秒钟。3 秒后它又连上了大哥。

难道大哥又要傻乎乎地重新执行 bgsave,把好几 GB 的 RDB 快照重新发一遍吗?这绝对会导致系统性能灾难!

为了应对这种“短暂掉线重连”,Redis 设计了极其轻量级的增量同步机制