在 Redis 主从复制的面试中,replication buffer 和 repl backlog 是一对极易混淆的概念。很多候选人能说出“一个用于全量同步,一个用于增量同步”,但再往下追问“它们分别分配在哪个节点上”“什么时候创建、什么时候释放”“为什么有了 replication buffer 还需要 repl backlog”,就开始含糊其辞了。
这篇文章会从主从复制的整体流程切入,把这两个缓冲区的定位、生命周期、内存行为以及常见面试追问一次性讲清楚。
先看主从复制的整体流程
Redis 主从复制分为两个阶段:
- 全量同步(Full Resynchronization):从节点第一次连接主节点,或者断线太久无法增量同步时,主节点会 fork 出子进程生成 RDB 文件发送给从节点。
- 增量同步(Partial Resynchronization):从节点短暂断线后重连,如果条件满足,主节点只发送断线期间缺失的写命令,而不需要重新传 RDB。
这两个阶段分别对应了今天要讲的两个缓冲区:
- replication buffer:全量同步期间,主节点用来缓存“RDB 生成之后、从节点加载 RDB 完成之前”这段时间内产生的新写命令。
- repl backlog:主节点上维护的一个固定大小的环形缓冲区,用于支持增量同步,保存最近一段时间的写命令。
replication buffer 是什么
定位与创建时机
replication buffer 是主节点为每一个从节点单独维护的一个缓冲区。当主节点执行 BGSAVE 生成 RDB 时,从节点还没有收到并加载完 RDB,但主节点不可能停止处理写请求。这段时间内所有新的写命令,都会被写入对应从节点的 replication buffer 中。
等从节点加载完 RDB 后,主节点再把 replication buffer 中积累的命令发送过去,从而保证主从数据一致。
关键特征
- 每个从节点一份:主节点有 N 个从节点,就有 N 个 replication buffer(严格说是每个从节点的输出缓冲区 client output buffer 的一部分)。
- 动态增长:大小不固定,取决于全量同步耗时和写入量。同步期间写入越频繁、RDB 越大传输越慢,这个缓冲区就越大。
- 可配置上限:通过
client-output-buffer-limit replica参数限制。如果超过硬限制,主节点会强制断开该从节点连接,避免主节点内存被撑爆。 - 生命周期短:全量同步完成后,缓冲区中积累的数据发送完毕,这部分内存就会被释放(或回收到正常复制流中)。
一个容易忽略的点
replication buffer 并不只存在于全量同步阶段。在正常复制流中,主节点向从节点发送命令时,如果从节点处理慢,命令也会堆积在输出缓冲区里。所以更准确的说法是:全量同步阶段它会显著增长,是内存风险的高发期,而日常复制中它一直存在但通常很小。
repl backlog 是什么
定位与创建时机
repl backlog 是主节点上全局唯一的一个环形缓冲区(circular buffer),在第一个从节点连接时创建,之后一直存在(只要还有一个从节点)。
它保存的是主节点最近产生的一批写命令。每个命令还会附带一个 master_repl_offset(复制偏移量)。从节点断线重连时,会带上自己已经处理的偏移量,主节点检查这个偏移量是否还在 backlog 范围内:
- 如果在,说明断线期间的命令都还在 backlog 里,可以执行增量同步,只补发缺失部分。
- 如果不在(被环形缓冲区覆盖了),只能退化为全量同步。
关键特征
- 全局唯一:不管有多少个从节点,主节点只有一个 repl backlog。
- 固定大小:由
repl-backlog-size配置,默认 1MB。它是环形结构,写满后新数据覆盖旧数据。 - 长期存在:只要主节点还有从节点,backlog 就一直保留。所有从节点都断开后,经过
repl-backlog-ttl(默认 3600 秒)才会被释放。 - 目的明确:专门为增量同步(PSYNC)服务,是“断线重连能否快速恢复”的关键。
核心区别对比
| 维度 | replication buffer | repl backlog |
|---|---|---|
| 数量 | 每个从节点一个 | 全局唯一 |
| 分配位置 | 主节点 | 主节点 |
| 主要用途 | 全量同步期间缓存新写命令 | 支持增量同步(断线重连) |
| 大小 | 动态增长,可配上限 | 固定大小(环形) |
| 生命周期 | 随从节点连接创建/释放 | 第一个从节点连接时创建,长期存在 |
| 溢出后果 | 主节点断开该从节点 | 从节点无法增量同步,退化为全量同步 |
| 相关配置 | client-output-buffer-limit replica |
repl-backlog-size、repl-backlog-ttl |
为什么有了 replication buffer 还需要 repl backlog
这是面试中最常被追问的问题,也是理解两者关系的关键。
replication buffer 解决的是一次全量同步过程中的数据一致性问题,它的生命周期和某一次同步绑定。一旦从节点断开,这个 buffer 就没了。
而 repl backlog 解决的是从节点断线重连后能否快速恢复的问题。如果只有 replication buffer,从节点每次断线都必须重新全量同步,代价极高(fork、生成 RDB、传输、加载)。有了 backlog,短时间断线可以走增量同步,大幅降低开销。
换句话说:
- replication buffer 面向“同步过程”,保证全量同步不丢数据。
- repl backlog 面向“断线恢复”,保证增量同步可行。
两者服务的目标不同,缺一不可。
常见面试追问
追问一:主节点内存暴涨通常和哪个有关?
多数情况是 replication buffer。全量同步期间写入量大、从节点加载慢,缓冲区持续膨胀,可能触发 client-output-buffer-limit 导致从节点被断开,甚至拖垮主节点。调大 backlog 一般不会导致内存暴涨,因为它是固定大小的。
追问二:repl backlog 设置多大合适?
经验公式:repl-backlog-size = 平均写入速率 × 预计最长断线时间。比如平均每秒写入 1MB,预计从节点最长断线 60 秒,那 backlog 至少设为 60MB。设太小会导致频繁全量同步。
追问三:从节点也会有 backlog 吗?
repl backlog 只在主节点上维护。从节点本身不创建 backlog,但它有自己的复制偏移量,用于重连时向主节点请求增量同步。
追问四:全量同步时,命令是先写 replication buffer 还是先写 backlog?
两者都会写。主节点在处理写命令时,会同时把命令传播给所有从节点的输出缓冲区(含 replication buffer),并追加到 repl backlog。它们是并行写入的,不是二选一。
总结
一句话概括:replication buffer 是主节点为每个从节点在全量同步期间准备的“临时蓄水池”,repl backlog 是主节点为所有从节点共享的、用于断线重连增量同步的“固定环形日志”。
理解这两个概念,不仅要记住定义,更要抓住三个关键:分配粒度(每从节点 vs 全局)、大小策略(动态 vs 固定)、服务目标(全量同步 vs 增量同步)。面试时能把这三点讲清楚,基本就能拿下这道题。
未经允许不得转载:任鹏个人博客 » Redis 主从复制中 replication buffer 和 repl backlog 的区别

