【面试突击】Redis 主从复制核心面试知识点

Redis 主从复制核心面试知识点

🎯 一、什么是主从复制?(开场必答)

核心定义

Redis 主从复制是将一个 Redis 服务器(Master)的数据自动复制到其他 Redis 服务器(Slave)的机制。

复制代码
架构图:
          ┌──────────┐
          │  Master  │ ← 写操作
          └────┬─────┘
               │
      ┌────────┼────────┐
      ↓        ↓        ↓
   Slave1   Slave2   Slave3  ← 读操作

核心特点(必背)

复制代码
1. 一主多从
   - 一个 Master 可以有多个 Slave
   - 一个 Slave 只能有一个 Master

2. 主写从读
   - Master:可读可写
   - Slave:只读(默认配置)

3. 数据自动同步
   - Master 写入数据后自动同步到 Slave
   - 异步复制:Master 不等 Slave 确认

4. 非阻塞复制
   - 同步过程中 Master 仍可处理请求

🎯 二、主从复制的作用(高频考点)

四大核心作用

复制代码
1. 数据冗余(备份)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• Master 数据自动备份到 Slave
• Master 故障时,Slave 可升级
• 防止数据丢失

2. 读写分离(性能提升)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• 写操作 → Master
• 读操作 → Slave(负载均衡)
• 性能提升:单机 10 万 QPS → 1 主 3 从 40 万 QPS

3. 高可用基础
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• 配合 Sentinel 实现自动故障转移
• 配合 Cluster 实现分布式架构
• 保证服务持续可用

4. 负载均衡
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• 多个 Slave 分担读压力
• 提升系统并发能力

典型应用场景

复制代码
电商系统示例:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
场景:商品详情页

• 商品更新(少量)→ Master 写入
• 商品查询(海量)→ Slave 读取

假设:
- 每秒 1000 次商品查询(读)
- 每秒 10 次商品更新(写)
- 读写比 100:1

架构:1 Master + 3 Slave
- Master 处理 10 次写 + 部分读
- Slave1、Slave2、Slave3 各分担 333 次读
- 系统总吞吐量提升 4 倍

🎯 三、复制原理(核心必背)

3.1 三种复制方式

1️⃣ 全量复制
复制代码
定义:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
完整复制 Master 的所有数据到 Slave

触发条件:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Slave 第一次连接 Master
✅ Master 重启(运行 ID 变化)
✅ 复制偏移量不在复制积压缓冲区

流程(8 步):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. Slave 发送 PSYNC 命令
   PSYNC ?  -1(?  表示首次,-1 表示无偏移量)

2. Master 返回 +FULLRESYNC <运行ID> <偏移量>

3. Master 执行 BGSAVE 生成 RDB 快照
   fork 子进程,不阻塞主进程

4. Master 将 BGSAVE 期间的写命令存入复制缓冲区

5. Master 发送 RDB 文件给 Slave

6. Slave 清空旧数据,加载 RDB 文件

7. Master 发送复制缓冲区的增量命令

8. Slave 执行增量命令,进入命令传播阶段

特点:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• 耗时长(数据量大时可能几分钟)
• 开销大(fork、磁盘 IO、网络传输)
• 可能阻塞(fork 时短暂阻塞)
2️⃣ 部分复制(增量复制)
复制代码
定义:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
只复制 Slave 断线期间缺失的数据

触发条件:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✅ Slave 短暂断线重连
✅ Master 运行 ID 未变化
✅ 复制偏移量在复制积压缓冲区内

核心机制:复制积压缓冲区
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• Master 维护的固定大小 FIFO 队列(默认 1MB)
• 保存最近的写命令
• 用于部分复制

流程:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. Slave 断线,最后偏移量 10000
2. Master 继续写入,当前偏移量 10500
3. Slave 重连,发送 PSYNC <运行ID> 10000
4. Master 检查:
   ✅ 运行 ID 匹配
   ✅ 10000 在积压缓冲区内
   → 返回 +CONTINUE
5. Master 发送 10000-10500 的增量命令
6. Slave 执行命令,同步完成

优势:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• 只传输增量数据(可能几 KB)
• 耗时短(秒级)
• 无需生成 RDB
• 网络开销小
3️⃣ 命令传播
复制代码
定义:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
全量/部分复制完成后,Master 持续将写命令发送给 Slave

流程:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
客户端 → Master:  SET key "value"
         ↓
Master 执行命令,修改数据
         ↓
Master 发送命令给所有 Slave
         ↓
Slave 执行命令,保持一致

特点:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• 实时同步
• 异步传播(不阻塞 Master)
• 保证最终一致性

3.2 关键概念(必背)

运行 ID (runid)
复制代码
• 每个 Redis 实例的唯一标识
• 40 位随机十六进制字符串
• 实例重启后 runid 会变化
• 用于判断 Master 是否重启过

作用:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Slave 重连时对比 runid:
✅ 匹配 → 尝试部分复制
❌ 不匹配 → 全量复制
复制偏移量 (offset)
复制代码
• 记录复制进度的字节偏移量
• Master 和 Slave 各自维护

Master offset:  已发送的字节数
Slave offset:   已接收的字节数

判断同步状态:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Master offset = Slave offset → 已同步 ✅
Master offset > Slave offset → 有延迟 ⚠️

示例:
Master offset:  100000
Slave offset:   100000
→ 完全同步

Master offset: 100500
Slave offset:  100000
→ 延迟 500 字节
复制积压缓冲区 (replication backlog)
复制代码
定义:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Master 维护的固定大小 FIFO 队列

作用:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
保存最近的写命令,用于部分复制

默认大小:1MB

大小计算公式:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
缓冲区大小 = 平均写入速度 × 预期断线时间 × 2

示例:
• 写入速度:1MB/s
• 预期断线:60 秒
• 缓冲区 = 1MB/s × 60s × 2 = 120MB

配置建议:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
写入量大 → 增大缓冲区(如 100MB)
写入量小 → 使用默认值即可

3.3 复制流程总结(背诵版)

复制代码
完整复制流程:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

阶段 1:建立连接
  Slave 连接 Master → 发送 PING → 身份验证

阶段 2:数据同步
  全量复制:BGSAVE → 发送 RDB → 加载 RDB → 发送缓冲命令
  部分复制:发送增量命令

阶段 3:命令传播
  Master 持续发送写命令 → Slave 执行

阶段 4:心跳检测
  Slave 每秒发送心跳 → Master 检测延迟

🎯 四、面试常见问题(必背)

Q1: Redis 主从复制的原理是什么?

复制代码
答:Redis 主从复制分为三个阶段:

1. 建立连接阶段
   Slave 连接 Master,发送 PSYNC 命令

2. 数据同步阶段
   • 全量复制:Master 执行 BGSAVE 生成 RDB,
     发送给 Slave,Slave 加载 RDB
   • 部分复制:Master 从复制积压缓冲区发送
     增量命令给 Slave

3. 命令传播阶段
   Master 持续将写命令发送给 Slave,保持同步

关键概念:
• 运行 ID:判断 Master 是否重启
• 复制偏移量:记录复制进度
• 复制积压缓冲区:保存最近命令,用于部分复制

Q2: 全量复制和部分复制的区别?

复制代码
答:
全量复制:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
触发:Slave 首次连接或 Master 重启
流程:BGSAVE → 发送 RDB → 加载 RDB
特点:耗时长、开销大、可能阻塞

部分复制:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
触发:Slave 短暂断线重连
流程:从复制积压缓冲区发送增量命令
特点:耗时短、开销小、无阻塞

对比:
• 全量复制传输整个数据集(可能几 GB)
• 部分复制只传输增量数据(可能几 KB)
• 部分复制性能远高于全量复制

Q3: 主从复制如何保证高可用?

复制代码
答:主从复制是高可用的基础,配合以下机制:

1. 数据冗余
   • 数据自动备份到 Slave
   • Master 故障时可从 Slave 恢复

2. 读写分离
   • Master 故障时,Slave 仍可提供读服务
   • 保证部分业务可用

3. 故障转移(配合 Sentinel)
   • Sentinel 监控 Master
   • Master 故障时自动选举 Slave 升级
   • 自动切换,无需人工干预

4. 负载均衡
   • 多个 Slave 分担读压力
   • 单节点故障不影响整体服务

Q4: 如何解决主从延迟问题?

复制代码
答:
原因分析:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. 网络延迟
2. Slave 负载高
3. Master 写入量大
4. 大 key 操作

解决方案:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
1. 网络优化
   • 主从部署在同一机房
   • 使用高速网络

2. Slave 优化
   • 增加 Slave 数量分散压力
   • 避免慢查询

3. Master 优化
   • 避免大 key 操作
   • 控制写入速率

4. 应用层容忍
   • 强一致性场景读 Master
   • 最终一致性场景读 Slave

5. 监控告警
   • 监控主从延迟(lag)
   • 延迟过大降级读 Master

Q5: 主从复制与哨兵、集群的关系?

复制代码
答:
主从复制:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• 基础架构
• 手动故障转移
• 单点写入

Redis Sentinel(哨兵):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• 基于主从复制
• 自动监控、自动故障转移
• 高可用方案
• 仍是单点写入

Redis Cluster(集群):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• 内置主从复制
• 数据分片(16384 个槽)
• 分布式架构
• 多点写入

关系:
主从复制 → Sentinel → Cluster
(基础)  (高可用) (分布式)

面试话术模板

复制代码
面试官:讲讲 Redis 主从复制?

你:Redis 主从复制是将 Master 的数据自动复制到 Slave 的机制。

主要作用有四点:
1. 数据备份,防止数据丢失
2. 读写分离,提升性能(1 主 3 从可提升 4 倍吞吐量)
3. 高可用基础,配合 Sentinel 实现故障转移
4. 负载均衡,多个 Slave 分担读压力

复制原理分三个阶段:
1. 建立连接:Slave 连接 Master
2. 数据同步:全量复制或部分复制
3. 命令传播:持续同步写命令

全量复制用于首次连接,Master 生成 RDB 发送给 Slave;
部分复制用于断线重连,只发送增量命令,性能更好。

关键机制是复制积压缓冲区,保存最近的写命令,
用于部分复制,默认 1MB,可根据写入量调整。

在 Java 中实现读写分离,通常维护两个连接池,
写操作用 Master 连接池,读操作用 Slave 连接池,
Slave 可以做轮询负载均衡。

常见问题是主从延迟,可以通过网络优化、增加 Slave、
业务容忍延迟等方式解决。
相关推荐
Lee川15 小时前
优雅进化的JavaScript:从ES6+新特性看现代前端开发范式
javascript·面试
Lee川18 小时前
从异步迷雾到优雅流程:JavaScript异步编程与内存管理的现代化之旅
javascript·面试
晴殇i20 小时前
揭秘JavaScript中那些“不冒泡”的DOM事件
前端·javascript·面试
绝无仅有21 小时前
Redis过期删除与内存淘汰策略详解
后端·面试·架构
绝无仅有21 小时前
Redis大Key问题排查与解决方案全解析
后端·面试·架构
AAA梅狸猫1 天前
Looper.loop() 循环机制
面试
AAA梅狸猫1 天前
Handler基本概念
面试
Wect1 天前
浏览器缓存机制
前端·面试·浏览器
掘金安东尼1 天前
Fun with TypeScript Generics:玩转 TS 泛型
前端·javascript·面试
掘金安东尼1 天前
Next.js 企业级落地
前端·javascript·面试