第十章 主从复制与高可用
前几章我们主要在单机 Redis 上练习命令与数据结构。在生产环境里,数据往往要扛住更大流量、更高可用性,这时就会用到多节点部署。本章用概念和原理帮你建立整体图景:主从复制、哨兵、集群分别解决什么问题,以及它们如何组合成常见的生产架构。
10.1 为什么需要多节点
单机 Redis 简单好懂,但放到真实业务里会遇到三类典型问题。
单点故障(Single Point of Failure)
只有一台机器时,进程崩溃、机器宕机、机房网络抖动,都会导致整库不可用。业务若强依赖缓存或会话,影响面会很大。
客户端
|
v
+-------------+
| 单机 Redis | <-- 挂了 = 全挂
+-------------+容量瓶颈
内存有上限。数据量或热点集合变大后,一台机器的内存可能装不下,或单机 CPU/网络成为瓶颈。
读压力
很多场景是写少读多。若所有读写都压在一台主库上,读请求很容易把单机打满;而数据本身可以多份只读副本分担读流量。
小结:多节点的核心动机可以记成三句话——抗故障、扩容量、分担读(具体用哪种架构,见 10.5 节对比)。
10.2 主从复制
主从复制(Replication) 的含义是:一台 主节点(Master) 负责接收写操作;一台或多台 从节点(Replica / Slave) 复制主节点的数据,一般用于读扩展和备份。从节点默认是只读的(可配置,但生产上常见做法是读主写从或读写分离时读从)。
原理概览:全量同步 + 增量同步
初次建立复制关系时,通常先做一次全量同步(把主上的数据快照传给从),之后主上每条会改变数据的命令再增量传给从,从本地重放这些命令,数据就与主保持一致(在复制正常的前提下)。
建立复制 / 断线重连后需要补数据时
=====================================
Master Replica
| |
|---- RDB 或类似全量数据 ------->| 全量:先对齐“底稿”
| |
|---- 写命令流(增量) --------->| 增量:持续追平
| |
v v
接受写 重放命令,只读对外初学者只需记住:
| 阶段 | 作用 |
|---|---|
| 全量同步 | 让从节点快速拥有一份与主接近一致的数据基线 |
| 增量同步 | 主上新增的写以命令形式持续同步到从 |
若网络长时间中断,可能再次触发全量或大规模补数据,这是复制机制的自然结果;本章不展开参数与调优。
REPLICAOF / SLAVEOF 命令
从节点要“跟随”哪个主,需要显式配置或命令指定:
REPLICAOF <host> <port>:让当前实例成为指定地址实例的从节点(Redis 5 起推荐用语)。SLAVEOF <host> <port>:老命令,语义与REPLICAOF相同,仍兼容。REPLICAOF NO ONE:取消复制,把自己变回独立的主(在手动切换等场景会见到概念)。
配置通常在配置文件里写 replicaof host port,或在运行时发送上述命令。原理上就是:从向主注册,主把数据与命令流推(或配合拉取机制)给从。
读写分离的基本思路
写请求
|
v
+-------------+
| Master |
+-------------+
/ | \
读请求 读请求 读请求
| | |
v v v
+--------+ +--------+ +--------+
|Replica1| |Replica2| |Replica3|
+--------+ +--------+ +--------+- 写:只打主(保证一份写入源,避免冲突)。
- 读:可以打到从,分散读压力。
注意(概念层):主从复制是异步的,读从可能读到略微过期的数据;对一致性要求极高的读,仍可能要读主或配合业务策略。这是使用读写分离时脑子里要有的一根弦。
主从模式的局限:主节点故障时,不会自动把某个从提升为新主并让全局改连——这需要 哨兵 或人工介入。
10.3 哨兵模式(Sentinel)
要解决什么问题?
纯主从架构下,主挂了之后:谁来宣布“新主是谁”?应用配置的连接地址怎么变?哨兵(Sentinel) 用来在主从结构之上做监控与自动故障转移,让系统在不人工改配置的情况下尽量自动恢复。
哨兵的三大功能
| 功能 | 含义(入门理解) |
|---|---|
| 监控 | 周期性检查主、从、其它哨兵是否按预期工作 |
| 通知 | 某实例异常时,可通过订阅等机制通知管理员或其它系统 |
| 自动故障转移 | 主不可用时,选举一个从为新主,并令其它从改跟新主;同时告诉客户端应连哪台主 |
架构示意(哨兵集群 + 一主多从)
应用 / 客户端
|
+------------+------------+
| 先问 Sentinel 要“当前主”地址 |
+------------+------------+
|
+-------------------+-------------------+
| | |
v v v
+----------+ +----------+ +----------+
|Sentinel 1| |Sentinel 2| |Sentinel 3|
+----------+ +----------+ +----------+
| | |
+-------------------+-------------------+
| 监控 & 投票
v
+-------------+
| Master |
+-------------+
/ | \
v v v
Replica Replica Replica通常部署多个哨兵(奇数个便于投票),避免单个哨兵自己误判。客户端实际连接 Redis 数据节点时,常见做法是通过哨兵发现当前主地址,而不是写死一个 IP(具体接入方式属各语言客户端细节,本章只记原理)。
故障转移流程(概念步骤)
- 主观下线:某个哨兵探测主超时,认为主可能挂了(主观)。
- 客观下线:足够多哨兵同意,确认主真的不可用(客观)。
- 选举领头哨兵:由哨兵之间协商选出一个来执行切换。
- 选新主:从现有从节点里按规则(偏移量、优先级等)挑一个提升为主。
- 改复制关系:其余从节点改为复制新主;旧主恢复后通常也会被降级为从,避免脑裂期间双写(细节由实现与配置保证,入门只需理解“只有一个对外写入主”这一目标)。
故障前: Client --> Master <-- Replicas
故障后: 某 Replica 提升为 New Master,其它 Replica 跟新主,Client 通过 Sentinel 得知新主地址10.4 集群模式(Cluster)
要解决什么问题?
主从 + 哨兵主要解决 高可用 和 读扩展,但整份数据仍在一份逻辑数据集里(主持有全量)。当单主内存放不下全量数据时,需要把数据拆到多台机器上,这就是 Redis Cluster(集群) 要解决的:水平分片、分散容量与写压力。
数据分片:16384 个哈希槽
Cluster 将键空间逻辑上切成 16384 个槽(slot)。每个键通过 CRC16(key) mod 16384 算出一个槽号(简化理解即可),每个主节点负责其中一部分槽;数据按槽分布在不同节点上。
槽 0 - 5460 槽 5461 - 10922 槽 10923 - 16383
+----------------+----------------+----------------+
| Master A | Master B | Master C |
| (主 + 可选从) | (主 + 可选从) | (主 + 可选从) |
+----------------+----------------+----------------+
\ | /
\ | /
v v v
整体对外是一个 Cluster,客户端根据 key 算槽并路由到对应节点每个主可以带从节点做高可用;主挂了时,集群会尝试由对应从接管槽(故障转移思想与哨兵类似,但是在 Cluster 协议内完成)。
架构 ASCII 图(三主三从示意)
Client
|
+-------------+-------------+
| Cluster-aware 客户端 |
| 或 代理层(视架构而定) |
+-------------+-------------+
/ | \
v v v
+---------+ +---------+ +---------+
| M1 + R1 | | M2 + R2 | | M3 + R3 |
+---------+ +---------+ +---------+
槽区间1 槽区间2 槽区间3
M = Master R = Replica(从)节点之间通过 Gossip 等机制交换状态,维护集群拓扑;初学者知道“去中心化、多主分片”即可。
集群模式下的常见限制(概念)
因为键落在不同节点上,部分操作会受限(与单机或单主多从不同):
| 现象 | 原因(入门说法) |
|---|---|
| 多键操作可能报错或需同槽 | 例如部分命令要求多个 key 在同一槽;可用 hash tag {...} 让相关 key 落同槽(属于使用技巧,本章只点名) |
| 事务、Lua 若跨槽 | 同样受槽分布约束 |
| 复杂度与客户端 | 客户端要能处理 MOVED / ASK 重定向(或配合代理),才能找对节点 |
记住一句话:Cluster 用分片换来容量与吞吐,跨槽多键原子操作不如单机自由。
10.5 三种部署模式的选择建议
下面从入门选型角度做对比,便于和面试官或同事沟通“我们为什么用这种架构”。
| 对比项 | 主从复制 | 主从 + 哨兵 | Redis Cluster |
|---|---|---|---|
| 核心目的 | 备份、读写分离、分担读 | 在主从基础上 自动故障转移 | 分片,突破单机内存,分散写与容量 |
| 数据副本 | 一主多从 | 同左 | 每片有自己的主从 |
| 主故障 | 需人工切换(纯主从) | 哨兵自动选主、改拓扑 | 集群内对槽做主从切换 |
| 客户端复杂度 | 相对简单(可自己拆读写) | 需配合 Sentinel 发现主 | 需 Cluster 客户端或代理 |
| 典型场景 | 读多写少、可接受短时人工介入 | 生产常见:要高可用又未分片 | 数据量大、单机装不下或单主写瓶颈 |
简要建议:
- 数据能装进一台主的内存、主要怕主挂:主从 + 哨兵 是最常被提到的组合。
- 数据量或写压力需要多台机器分担全量数据集:考虑 Cluster。
- 仅学习与测试:单机 足够;理解本章有助于你阅读公司架构图。
本章小结
| 小节 | 关键 takeaway |
|---|---|
| 10.1 多节点 | 单机有 单点故障、容量、读压力 三类动机 |
| 10.2 主从 | 全量 + 增量 复制;REPLICAOF/SLAVEOF;读写分离与复制延迟意识 |
| 10.3 哨兵 | 监控、通知、自动故障转移;多哨兵投票;客户端通过哨兵感知当前主 |
| 10.4 集群 | 16384 槽 分片;扩容与容量;跨槽 对多键/事务/Lua 的限制 |
| 10.5 选型 | 高可用未分片偏 哨兵 + 主从;大数据集偏 Cluster |
下一章预告
第十一章:在项目中使用 Redis 将把前面学过的数据类型、过期、持久化以及本章的多节点概念,收束到真实项目里:如何选型键设计、如何避免常见坑、如何与应用程序配合(连接、序列化、缓存与数据库一致性等入门话题)。你将从“会用命令”过渡到“能在工程里负责任地使用 Redis”。