面试知识库
进阶

Redis主从复制#

一句话答案#

全量复制(RDB 快照)+ 增量复制(repl_backlog 缓冲区),默认异步复制——主从切换时可能丢失未同步的数据。

核心要点

复制流程#

从库发送 PSYNC runId offset
  ├── 首次连接(runId=?,offset=-1)→ 全量复制
  └── 重连 → 判断 offset 是否在 repl_backlog 中
        ├── 在 → 增量复制
        └── 不在 → 全量复制
plaintext

全量复制#

1. 从库发送 PSYNC ? -1
2. 主库执行 BGSAVE 生成 RDB 快照(fork 子进程)
3. 主库发送 RDB 文件给从库
4. 期间主库的写命令暂存到 repl_backlog
5. 从库加载 RDB
6. 主库发送缓冲区中的增量命令
7. 从库执行增量命令,同步完成
plaintext

开销: fork 主进程(内存翻倍风险)+ 网络传输 RDB + 从库加载 RDB 期间阻塞

增量复制#

  • 主库维护一个环形缓冲区 repl_backlog(默认 1MB)
  • 从库断连重连后,发送自己的 offset
  • 主库从 repl_backlog 中找到 offset 之后的命令增量发送
  • repl_backlog 太小 → offset 被覆盖 → 退化为全量复制

生产建议: repl-backlog-size 设为 写入 QPS × 平均命令大小 × 可容忍断连秒数 × 2

异步复制与数据丢失#

默认行为: 主库写入后立即返回客户端,不等待从库确认

数据丢失场景:

时刻 T1: 客户端写入主库 SET key=100,主库返回 OK
时刻 T2: 主库宕机(key=100 尚未同步到从库)
时刻 T3: 哨兵提升从库为新主库
结果: key=100 丢失
plaintext

丢失量估算:

  • 主从延迟通常 < 1 秒
  • 最多丢失 最近 1 秒内的写入命令
  • 高写入场景(如 1 万 QPS)→ 最多丢 1 万条

减少数据丢失的配置#

# 至少 N 个从库确认写入,否则主库拒绝写入
min-replicas-to-write 1

# 从库复制延迟超过 M 秒,视为不可用
min-replicas-max-lag 10
plaintext

效果: 如果没有任何从库在 10 秒内确认同步,主库停止接受写入 → 牺牲可用性换数据安全。

注意: 这不是同步复制,只是”确保至少有一个从库在跟上”。写入仍然是先返回客户端的。

主从延迟的排查#

# 在从库上执行
INFO replication

# 关注:
master_link_status: up          # 连接状态
master_last_io_seconds_ago: 0   # 上次 IO 距今秒数
slave_repl_offset: 1234567      # 从库 offset
master_repl_offset: 1234580     # 主库 offset(差值 = 延迟量)
bash

延迟大的常见原因:

  • 从库负载高(被大量读请求打满)
  • 网络带宽不足
  • 从库执行慢命令(如 KEYS *)
  • 主库大 Key 写入(从库重放慢)
面试回答(2分钟版)

Redis 主从复制分为全量同步和增量同步。从库首次连接或 repl_backlog 中找不到断点 offset 时触发全量同步:主库 fork 子进程生成 RDB 快照发给从库,期间写命令暂存到缓冲区,从库加载完 RDB 再接收增量命令。断线重连时如果 offset 还在 repl_backlog 环形缓冲区内就做增量同步,只发送断点之后的命令,非常轻量。正常运行阶段是命令传播,主库每条写命令异步发给所有从库。关键点是默认异步复制,主库写入成功即返回客户端不等从库确认,所以主从切换时最多丢失最近约一秒的写入。要降低丢失风险可以配置 min-replicas-to-write 和 min-replicas-max-lag,确保至少有一个从库在跟上,否则主库拒绝写入。repl_backlog 大小建议按”写入 QPS 乘以命令大小乘以可容忍断连秒数”来设置,太小会频繁触发全量同步。

追问与易错

追问方向:

  • “全量复制什么时候触发?”→ 首次连接 / repl_backlog offset 不在 / runId 不匹配
  • “repl_backlog 太小会怎样?”→ 频繁触发全量复制,主库 fork + 传输 RDB 开销大
  • “主从切换丢数据怎么办?”→ min-replicas-to-write 降低丢失量 + 业务层做对账补偿
  • “主从复制和 Cluster 的数据同步一样吗?”→ 一样,Cluster 的每个分片内部也是主从复制

易错点:

  • ❌ “主从复制是同步的”——默认异步,主库不等从库确认
  • ❌ “从库宕机不影响主库”——如果配了 min-replicas-to-write,从库全挂会导致主库拒绝写入
  • ❌ “Redis 不会丢数据”——异步复制 + 主从切换,最多丢最近 1 秒的写入
  • ❌ 混淆 repl_backlog 和 client output buffer——前者是全局复制缓冲,后者是每个从库的发送缓冲