主从复制
0. 引言
主从复制(Replication)是 Redis 高可用的地基:数据从 master 同步到 replica,实现读写分离(读扩展)与故障转移(Sentinel/Cluster 的依赖)。本章解析复制协议(PSYNC/PSYNC2)、同步机制与 7.x 下的实践要点。
1. 基本架构
图表渲染中…
- replica 默认只读(
replica-read-only yes),通过REPLICAOF host port指定主节点; - 复制是异步的:master 执行写命令后立即返回,复制在后台进行——主从存在延迟是常态;
- 拓扑:一主多从、级联复制(replica 也可作为更下游的 master)。
2. 同步协议演进:SYNC → PSYNC → PSYNC2
2.1 PSYNC(Redis 2.8+)
replica 通过 PSYNC <replid> <offset> 向 master 请求同步:
- 全量同步(full resync):master 生成 RDB 快照发给 replica,之后把快照期间的写命令发给 replica 重放;
- 部分同步(partial resync):replica 断线重连后,若断线期间的命令还在 master 的**复制积压缓冲区(repl_backlog)**内,只需补发增量——避免全量重传。
图表渲染中…
2.2 PSYNC2(Redis 4.0+)
PSYNC2 解决"主从切换后全量同步风暴":
- replication ID 与 offset:
replid(当前数据集血缘)+replid2(上一个 replid,即故障前 master 的 ID)+offset唯一定位数据集版本; - 主从切换后,新 master 继承旧 master 的
replid2,其余 replica 只需部分同步(基于旧 replid 的 offset 增量),而不是全量重传; - 这极大降低了故障转移场景下的带宽与延迟冲击。
2.3 复制缓冲与配置
text
# redis.conf
repl-backlog-size 1mb # 复制积压缓冲区:越大,部分同步命中率越高
repl-backlog-ttl 3600 # 无 replica 时 backlog 保留时间
repl-diskless-sync yes # 无盘同步:RDB 直接通过 socket 传输(7.x 默认 yes)
repl-diskless-sync-delay 5 # 等待多个 replica 同时同步的窗口
min-replicas-to-write 1 # 至少 N 个 replica 在线才接受写(防脑裂丢数据)
min-replicas-max-lag 10建议:repl-backlog-size 按"峰值写速率 × 容忍断线时间"估算(如 10MB/s × 60s = 600MB),部分同步命中率直接影响故障恢复体验。
3. 全量同步的细节
图表渲染中…
- 无盘复制(diskless):7.x 默认开启,RDB 不落盘直接走网络,避免磁盘 IO 与双倍磁盘占用;
- 全量同步期间 master 仍可服务,但大实例 fork 有短暂阻塞(同 RDB 章节的 COW 分析);
- 大 key 过多会明显拖慢全量同步,从库提升前建议先
BGSAVE预热。
4. 延迟与一致性
4.1 复制延迟来源
| 来源 | 说明 | 对策 |
|---|---|---|
| 网络 RTT | 跨机房明显 | 同机房部署 |
| master 写量大 | 命令流积压 | 分片、降低写放大 |
| replica 慢 | 单线程处理不过来 | 提高实例规格 |
| 大 value | 序列化/传输/重放耗时 | 拆分大 key |
4.2 一致性权衡
- 异步复制:master 返回成功 ≠ replica 已收到,
min-replicas-to-write可强制"至少 N 个副本在线才写",用可用性换一致性; - WAIT 命令(Redis 3.0+):
WAIT numreplicas timeout阻塞等待指定数量 replica 确认,实现同步复制的近似(仅保障"已传播",非分布式事务); - 脑裂:master 与多数派失联但仍接受写 → 切换后数据丢失。配合
min-replicas-to-write+ Sentinel 的quorum降低概率。
4.3 过期键的复制语义
- 过期删除由 master 决定,master 删除后向 replica 传播
DEL; - replica 自身不主动删除过期键(除非读请求触发惰性检查),保证主从一致;
- 读从库可能读到"已过期但未删"的 key——可接受(短暂),或启用
replica-serve-stale-data no直接拒绝读。
5. 复制与持久化的关系
- replica 默认不持久化也能工作(数据全量来自 master),但重启后需重新全量同步;
- 建议:replica 开启 AOF,作为 master 持久化失败的兜底;
- 备份时从 replica 上
BGSAVE(redis-cli --rdb或BGSAVE),避免影响 master 性能。
6. 常见坑清单
- repl-backlog-size 太小:频繁断线触发全量同步风暴;
- 忽略 master 与 replica 版本差异:replica 版本不能高于 master(7.x 内部校验);
- 读写分离读旧数据:复制延迟导致读到旧值,业务需容忍或路由敏感读走 master;
- 主从切换后未处理
replid变化:客户端主从切换感知(Sentinel/Cluster 已封装); - 大实例首次全量:预留带宽与磁盘,建议错峰。
7. 小结
- 复制 = 命令流 + 部分同步(PSYNC2 的 replid/offset 机制)+ 全量兜底;
- 异步复制是性能与一致性的默认平衡点,关键场景用
WAIT/min-replicas收紧; - 主从复制解决读扩展与数据冗余,但不解决自动故障转移——那是 Sentinel 的职责(下一章)。
下一章讲解 Sentinel:Redis 高可用的自动故障转移机制。