📚 高级篇 08. 分布式缓存 - Redis 主从全量同步原理
一、 核心概念:大哥如何认出小弟?
在讲解同步流程前,必须先掌握两个极其关键的底层身份证号。如果没有它们,主从节点之间根本无法交流。
-
Replication Id (简称
replid): 数据集的唯一标识。- 每个 Redis 启动时都会生成一个属于自己的唯一的
replid。 - 当小弟(Slave)认大哥(Master)成功后,小弟会把自己的
replid修改为和大哥一模一样。 - 作用: Master 通过对比
replid,就能瞬间判断出“这个小弟是不是之前就跟着我混的”。如果不一样,说明是新来的,必须进行全量同步。
- 每个 Redis 启动时都会生成一个属于自己的唯一的
-
Offset (偏移量): 数据同步的进度条。
- 随着 Master 不断接收新的写命令,它的
offset会不断累加递增。 - Slave 在拉取数据时,自己的
offset也会跟着递增。 - 作用: 如果 Master 的
offset是 1000,Slave 的offset是 900,说明 Slave 落后了 100 个进度,需要补齐。
- 随着 Master 不断接收新的写命令,它的
二、 全量同步的核心流程 (分为三个阶段)
触发时机: 通常发生在 Slave 第一次连接 Master,或者 Slave 宕机太久导致数据脱节极其严重时。
🚩 第一阶段:建立连接与协商同步
这是双方互换底牌的阶段,决定了接下来是大动干戈还是小修小补。
-
小弟请求同步: Slave 向 Master 发送
psync ? -1命令。?表示:我是新来的,我还不知道大哥你的replid是多少。-1表示:我是一张白纸,我的offset进度是未知的。
-
大哥判断身份: Master 收到命令,一看
replid是?,立刻断定这是个纯萌新。 -
大哥下达指令: Master 回复
+FULLRESYNC <大哥的replid> <大哥目前的offset>。- 意思就是:“确认执行全量同步!记住,从现在起,你的归属 ID 是这个,你要追赶的进度目标是这个。”
-
小弟领命: Slave 收到回复,立刻把大哥的
replid和offset保存到自己的内存中。
🚩 第二阶段:RDB 核心数据传输
这是全量同步中最耗时、最核心的阶段。
-
大哥生成快照: Master 立刻在后台执行
bgsave命令,利用fork子进程生成当前完整内存数据的 RDB 快照文件。(此时 Master 的主进程依然在飞速处理客户端的新写请求)。 -
发送快照: Master 将生成的 RDB 文件通过网络发送给 Slave。
-
小弟清空重载: Slave 收到 RDB 文件后,先清空自己本地的所有旧数据,然后把 RDB 文件加载到内存中。
- 至此,小弟的数据状态恢复到了大哥执行
bgsave那个精确的历史瞬间。
- 至此,小弟的数据状态恢复到了大哥执行
🚩 第三阶段:增量命令补偿 (极其精妙的防漏设计)
💥 致命漏洞填补:
在大哥执行 bgsave 生成 RDB、并把 RDB 传给小弟的这几秒甚至几十秒的时间差里,大哥又接收了无数个新的写命令。这些新命令根本不在 RDB 文件里!如果不管它们,小弟的数据就永远比大哥少一块。
-
大哥的记事本 (
repl_baklog): 在第二阶段bgsave开始的那一刻起,Master 会把期间接收到的所有新写命令,全部悄悄记录到一个叫repl_baklog(复制积压缓冲区) 的内存队列中。 -
发送补偿日志: 当小弟加载完 RDB 醒来后,Master 会把
repl_baklog里的这些新命令打包发送给 Slave。 -
小弟执行追赶: 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 设计了极其轻量级的增量同步机制。