适用版本:Redis 7.2.x
Redis 的高可用体系里,主从复制几乎是最基础的一环。很多同学第一次接触 Redis 架构时,会先看到这样的部署方式:一台主库负责写,一台或多台从库负责同步数据、分担读流量、参与故障切换。
看起来很简单,但如果继续往下问,就会出现很多关键问题:
- 从库是怎么拿到主库数据的?
- 主库数据量很大时,同步是不是会很重?
- 网络闪断后,为什么有时只补一小段数据,有时却要全量重传?
- 主从复制为什么能支撑 Sentinel 和 Cluster 的故障切换?
这篇文章就围绕这些问题,系统梳理 Redis 主从复制的工作原理、关键配置、常见命令和排查思路。读完之后,你应该能把“主从复制”从会用,提升到真正理解它的运行机制。
一、为什么 Redis 需要主从复制
单机 Redis 虽然简单,但一旦主机故障,服务就会直接中断。另外,随着业务读请求增加,只靠一个实例也很容易成为瓶颈。
所以主从复制主要解决三类问题:
1. 数据冗余
主库上的数据会同步到从库,相当于保留了多份副本。即使主库故障,也还有其他节点持有数据。
2. 读写分离
很多业务会把写请求打到主库,把部分读请求打到从库,从而减轻主库压力。
3. 高可用基础能力
无论是 Sentinel 还是 Redis Cluster 的副本切换,本质上都依赖主从复制。没有副本,就谈不上故障切换。
可以先记住一句话:
主从复制不是完整高可用方案,但它是 Redis 高可用的底座。
二、主从复制的基本架构图景
一个最常见的 Redis 主从拓扑如下:
+----------------+
| Client 写入 |
+--------+-------+
|
v
+---------------+
| Master 主库 |
| 负责处理写请求 |
+---+--------+---+
| |
复制流 | | 复制流
v v
+----------+ +----------+
| Replica1 | | Replica2 |
| 从库 | | 从库 |
+----------+ +----------+
在这个模型里:
- 主库(master) 负责处理写请求;
- 从库(replica) 默认从主库异步复制数据;
- 从库也可以继续挂下级副本,但生产里更常见的是星型结构;
- Redis 7.2.x 文档与配置中更常见的术语是 replica,但很多历史资料仍习惯写 slave。
需要特别注意:
Redis 复制默认是异步复制。
这意味着主库返回客户端写成功时,数据不一定已经同步到所有从库。所以主从复制增强了可用性,但并不等于强一致。
三、从库如何建立复制关系
1. 配置方式
最常见的方式是在从库配置文件中指定主库地址:
replicaof 192.168.10.10 6379
masterauth your_master_password
masteruser default
如果主库开启了 ACL 或密码认证,通常要同时配置认证信息。
2. 运行时动态指定
也可以在从库上动态执行:
127.0.0.1:6380> REPLICAOF 192.168.10.10 6379
OK
取消复制关系则可以执行:
127.0.0.1:6380> REPLICAOF NO ONE
OK
这个命令的含义是:当前实例不再作为别人的副本,而是提升为独立主库。
3. 建链后的第一步:握手
从库连接主库后,并不是立刻开始传输数据,而是会先完成一轮握手,包括:
- 建立 TCP 连接;
- 如果开启认证,执行认证;
- 发送
PING检查连通性; - 通过
PSYNC申请同步; - 主库根据条件决定执行全量同步还是部分重同步。
所以主从复制的关键,并不只是“从库连上主库”,而是主从双方如何决定同步方式。
四、全量同步:第一次复制时发生了什么
第一次建立复制关系时,通常会执行全量同步。
1. 全量同步的触发场景
以下情况常常会触发全量同步:
- 新从库第一次接入主库;
- 从库断线太久,主库 backlog 已经覆盖不到它缺失的数据;
- 主库发生重启或复制历史切换,旧的复制 ID 无法继续匹配;
- 手工重建复制关系。
2. 全量同步流程
完整流程可以概括为:
从库发起 PSYNC
|
v
主库判断:无法部分同步
|
v
主库执行 BGSAVE 生成 RDB 快照
|
v
把 RDB 文件发给从库
|
v
从库清空旧数据并加载 RDB
|
v
主库把快照期间积压的写命令继续发给从库
|
v
主从进入稳定增量复制状态
3. 为什么全量同步成本高
全量同步的压力通常体现在三个方面:
- 主库压力:需要
fork子进程生成 RDB; - 网络压力:需要传输整份快照;
- 从库压力:要加载快照并重建数据集。
如果主库数据量很大,或者短时间内多个从库一起重连,就可能带来明显抖动。
4. 一个很实用的理解角度
全量同步本质上是:
先把主库当前的“全量状态”给从库,再把这段时间新增的写操作补上。
这样从库最终就能追平到主库最新状态。
五、部分重同步:为什么网络闪断后不一定全量复制
如果每次网络抖动都重传整份数据,Redis 主从复制会非常脆弱。为了解决这个问题,Redis 提供了部分重同步机制。
1. 核心概念:Replication ID 与 Offset
理解部分重同步,重点抓住两个概念:
(1)Replication ID
主库会维护复制历史标识,可以理解为“这一段复制历史是谁生成的”。
(2)Offset
主库复制流中的每个字节都有偏移量,从库会记录自己已经处理到哪里。
所以从库断线重连时,会告诉主库:
- 我之前跟的是哪个复制历史;
- 我已经同步到哪个 offset。
如果主库判断这段历史还有效,而且缺失的数据还在 backlog 中,就可以直接把缺失部分补给从库,而不必全量重传。
2. 什么是 backlog
repl-backlog-size 配置的是主库用于复制的积压缓冲区,本质上是一个环形缓冲区。
repl-backlog-size 256mb
它保存的是最近一段时间的写命令流。
这块缓冲区很关键,因为部分重同步能不能成功,很大程度取决于:
- 从库断开了多久;
- 主库写入速度有多快;
- backlog 是否足够大。
3. 一个直观例子
假设:
- 主库当前复制 offset 为
1000000; - 从库断线前同步到了
998000; - backlog 中还保留着
998001 ~ 1000000这段数据。
那么从库重连时,主库就只需要补发这 2000 字节之后的差量数据,而不是整库重传。
这就是部分重同步的价值:
把“全量复制”尽量变成“断点续传”。
六、复制稳定运行时,数据是怎么持续同步的
当主从进入稳定状态后,主库会把写命令异步发送给从库。
1. 主库处理写请求
客户端写入主库,例如:
SET order:1001 paid
INCR page:view:home
HSET user:1 name Alice age 20
2. 主库传播复制流
这些写操作会被编码成 Redis 协议流,持续发送给从库。
3. 从库按顺序回放
从库接收到这些命令后,按顺序应用到自己的数据集。
所以从库本质上并不是“定时拉快照”,而是:
- 初始阶段拿一份全量快照;
- 稳定阶段持续接收增量命令流。
4. 为什么复制延迟会出现
由于复制是异步的,所以从库可能会短暂落后于主库,常见原因包括:
- 主库写入量突然增大;
- 网络带宽不足或网络抖动;
- 从库本身 CPU、磁盘、内存压力过大;
- 大 key、大批量写入导致复制流处理变慢。
这也是为什么很多关键一致性场景不能简单依赖“写主读从立刻可见”。
七、主从复制与持久化之间的关系
主从复制和持久化经常一起出现,但它们解决的问题不一样:
- 主从复制:解决副本分发与高可用基础能力;
- RDB / AOF 持久化:解决实例重启后的数据恢复。
不过在全量同步时,它们又会发生关联。
1. 全量同步通常依赖 RDB 快照
主库在给从库做全量同步时,通常会生成 RDB 快照并发送出去。
2. 持久化配置会影响复制成本
如果主库本身已经存在较高的持久化压力,再叠加全量复制,就更容易出现:
fork阻塞放大;- Copy-On-Write 内存压力上升;
- 磁盘和网络占用变高。
3. 复制不是备份
这一点非常重要。
如果主库误删数据、执行错误命令、业务写入脏数据,这些变化也会同步到从库。因此:
主从复制提高的是可用性,不是“历史可回滚能力”。
真正的备份仍然要依赖快照备份、AOF、异地备份等方案。
八、常用配置项与示例
下面给出一组比较常见的主从复制配置示例:
# 从库配置主库地址
replicaof 192.168.10.10 6379
# 主库认证信息
masteruser default
masterauth your_master_password
# 复制积压缓冲区
repl-backlog-size 256mb
# 从库只读
replica-read-only yes
# 与主库的心跳检测周期
repl-ping-replica-period 10
# 复制超时时间
repl-timeout 60
# 无盘复制,可按场景评估开启
repl-diskless-sync yes
repl-diskless-sync-delay 5
1. replica-read-only
从库默认只读,这样可以避免业务误写从库造成混乱。
2. repl-backlog-size
这个值太小,网络稍一抖动就可能触发全量同步;太大则会占用额外内存。要结合:
- 主库写入速率;
- 可接受断链时长;
- 实例内存规模。
3. repl-diskless-sync
这是无盘复制能力。开启后,主库可以在某些场景下直接通过 socket 把 RDB 流发送给从库,减少磁盘中转。
是否开启要看环境特点:
- 如果磁盘 IO 紧张,可能更有价值;
- 如果网络稳定性一般,也要评估传输风险与运维习惯。
九、日常观察主从状态的常用命令
1. INFO replication
这是排查复制问题最常用的命令:
127.0.0.1:6379> INFO replication
在主库上,你通常能看到:
- 当前角色是
master; - 已连接从库数量;
- 每个从库的 offset、lag;
- backlog 状态。
在从库上,你通常能看到:
- 当前角色是
slave/replica; - 主库地址;
- 主从连接状态;
- 当前复制 offset;
- 是否正在同步。
2. ROLE
127.0.0.1:6379> ROLE
这个命令可以快速看实例当前是主库、从库还是哨兵模式下的其他角色信息。
3. REPLICAOF
REPLICAOF 192.168.10.10 6379
REPLICAOF NO ONE
用于动态建立或解除主从关系。
4. WAIT
127.0.0.1:6379> SET payment:100 ok
OK
127.0.0.1:6379> WAIT 1 100
(integer) 1
WAIT 可以让客户端在写入后等待指定数量副本确认,用来在一定程度上增强写后复制可见性。但要注意:
- 它不是强一致事务;
- 只是让客户端在返回前等待更多复制确认;
- 仍然要结合业务容忍度使用。
十、一个典型主从复制实验流程
如果你想自己验证,可以按下面思路搭一个最小实验。
1. 启动主库与从库
- 主库:
6379 - 从库:
6380
从库配置:
port 6380
replicaof 127.0.0.1 6379
2. 在主库写入数据
127.0.0.1:6379> SET site:name redis-demo
OK
127.0.0.1:6379> LPUSH jobs task1 task2
(integer) 2
3. 在从库读取验证
127.0.0.1:6380> GET site:name
"redis-demo"
127.0.0.1:6380> LRANGE jobs 0 -1
1) "task2"
2) "task1"
4. 查看复制状态
127.0.0.1:6380> INFO replication
重点关注:
master_link_status是否为up;master_sync_in_progress是否为0;slave_repl_offset是否持续推进。
十一、生产中常见问题
1. 为什么主从复制不是强一致?
因为 Redis 复制默认是异步的。主库先处理写请求并返回客户端,然后再异步把命令传播到从库。
所以会出现:
- 主库已写成功;
- 从库短时间还没同步到;
- 如果此时主库故障,可能发生最近一小段写入丢失。
2. 为什么从库重连后有时增量同步,有时全量同步?
关键看两点:
- 主库 backlog 中是否还保留它缺失的那段数据;
- 复制 ID 是否还能对得上这段历史。
对得上就部分重同步;对不上就全量同步。
3. 主从复制延迟大,先看什么?
建议先看:
INFO replication中的 offset 差距;- 主库写入量是否突然升高;
- 网络带宽与延迟;
- 是否存在大 key、大批量写、Lua 脚本;
- 从库自身 CPU、内存、磁盘压力。
4. 为什么多个从库同时重连会拖垮主库?
因为可能触发多副本全量同步,带来:
fork压力;- RDB 生成压力;
- 大量网络传输;
- 主库内存额外消耗。
所以生产里常常需要控制副本重建节奏,而不是同时批量拉起。
5. 从库能不能写?
默认不建议。虽然某些场景可以调整只读策略,但会引入数据一致性混乱,通常不作为常规用法。
6. 主库误删数据后,从库能不能救回来?
通常不能直接依赖从库,因为删除命令也会同步过去。要恢复历史状态,还是要看是否有 RDB、AOF 或其他备份。
十二、实践建议
1. 不要把从库当成“绝对实时”的读库
如果业务对刚写入的数据立刻可见非常敏感,就要谨慎使用读写分离。否则很容易踩到复制延迟问题。
2. 根据写入速率合理设置 backlog
写入越快,越需要更大的 repl-backlog-size,否则网络稍有闪断就容易退化成全量同步。
3. 大实例特别关注全量同步成本
实例越大,fork、RDB、网络传输的代价越高。大实例应尽量减少频繁全量复制。
4. 主从复制配合监控一起看
至少建议长期关注:
- 主从 offset 差值;
- 主从连接状态;
- 全量同步次数;
- backlog 命中率;
- 复制延迟;
- 网络吞吐与磁盘压力。
5. 认清复制的边界
主从复制提升的是可用性和扩展性,但不是强一致、不是版本回滚、也不是完整备份方案。
十三、小结
理解 Redis 主从复制,最重要的是抓住下面几件事:
- 首次复制通常是全量同步:主库生成 RDB,从库加载快照,再补增量命令。
- 网络闪断后优先尝试部分重同步,依赖 replication ID、offset 和 backlog。
- 稳定运行时,主库通过异步复制流持续把写命令传播给从库。
- 主从复制是高可用基础,但不是强一致,也不是备份。
- Sentinel 和 Cluster 的故障切换,本质上都建立在副本复制之上。
如果你后续继续学习 Redis 的 Sentinel 和 Cluster,会发现很多故障切换、延迟、一致性边界问题,归根到底都和这里讲的复制机制密切相关。
📝 版权声明:本文为原创技术博客,转载请注明出处。
如文章中存在错误或不准确之处,欢迎在评论区指正,感谢您的阅读与支持!