Skip to content

第十章 主从复制与高可用

前几章我们主要在单机 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(具体接入方式属各语言客户端细节,本章只记原理)。

故障转移流程(概念步骤)

  1. 主观下线:某个哨兵探测主超时,认为主可能挂了(主观)。
  2. 客观下线:足够多哨兵同意,确认主真的不可用(客观)。
  3. 选举领头哨兵:由哨兵之间协商选出一个来执行切换。
  4. 选新主:从现有从节点里按规则(偏移量、优先级等)挑一个提升为主。
  5. 改复制关系:其余从节点改为复制新主;旧主恢复后通常也会被降级为从,避免脑裂期间双写(细节由实现与配置保证,入门只需理解“只有一个对外写入主”这一目标)。
  故障前:  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”。

坚持是一种品格