在真实的业务系统中,Redis 往往并不是"锦上添花"的组件,而是直接承载着高并发读写、请求削峰以及核心业务状态的关键基础设施。一旦 Redis 出现不可用,轻则接口响应变慢,重则引发数据库雪崩,造成连锁故障。因此,如何通过主从复制与高可用架构保证 Redis 的稳定性,是每一个后端工程师都绕不开的问题。
本文将从设计初衷出发,系统性地讲解 Redis 主从复制的工作原理、关键机制、性能优化策略以及生产环境中的实践经验,并在最后对哨兵与集群方案进行整体对比,帮助你在不同业务阶段做出合理的架构选择。
一、分布式场景下 Redis 主从架构的设计初衷
在最初的单机 Redis 架构中,所有请求都集中在一个节点上,这种部署方式在业务早期足够简单高效,但随着访问量增长,会逐渐暴露出两个致命问题。
1. 单点问题
如果某个服务器程序,只有一个节点(只搞一个物理服务器,来部署:这个服务器程序)
-
可用性问题,如果这个机器挂了,意味着服务就中断了
-
性能/支持的并发量也是比较有限的
引入分布式系统,主要也就是为了解决上述的单点问题
在分布式系统中,往往希望有多个服务器来部署redis服务,从而构成一个redis集群,此时就可以让这个集群给整个分布式系统中其他的服务,提供更稳定/更高效的数据存储功能
2. 可用性风险
单机 Redis 是一个典型的单点故障:
-
一旦 Redis 进程崩溃或机器宕机,缓存层会瞬间不可用;
-
大量请求直接穿透到数据库,极易引发缓存雪崩;
-
对于依赖 Redis 做限流、分布式锁、会话存储的系统,甚至可能导致业务逻辑完全失效。
3. 性能瓶颈
Redis 虽然单线程模型极其高效,但单节点的 CPU、内存和网络资源终究有限:
-
写请求集中在一个节点上;
-
大量读请求无法并行扩展;
-
在高并发场景下,延迟会明显上升。
为了解决这两个问题,Redis 引入了主从复制(Replication)机制,通过"一个主节点 + 多个从节点"的架构,实现:
-
读写分离:主节点负责写操作,从节点分担读请求;
-
数据冗余:数据在多个节点上保存,提升容灾能力;
-
高可用基础:为后续的自动故障转移(Sentinel / Cluster)奠定基础。
4. 分布式系统的几种Redis部署方式
1. 主从模式
在若干个redis节点中,有的是"主"节点,有的是"从"节点.
假设有三个物理服务器(称为是三个节点)分别部署了一个redis-server进程
此时就可以把其中的一个节点,作为"主节点"另外两个节点作为"从节点"
从节点,得听主节点的~~
(从节点上的数据要跟随主节点变化;从节点的数据要和主节点保持一致)
本来,在主节点上保存一堆数据.引入从节点之后,就是要把主节点上面的数据,复制出来,放到从节点中.
后续,主节点这边对于数据有任何修改,都会把这样的修改给同步到从节点上. (从节点,就是主节点的副本)
如果我改了从节点的数据,是否是把从节点的数据往主节点上同步呢??
Redis主从模式中,从节点上的数据,不允许修改!!!只能读取数据!!
更准确的说,主从模式,主要是针对"读操作"进行并发量&可用性的提高~~
而写操作的话,无论是可用性还是并发,都是非常依赖主节点.主节点又不能搞多个实际业务场景中,读操作往往就是比写操作更频繁

之前只是单个redis服务器节点,此时这个机器挂了整个redis就挂了
上述这个主从结构,这些redis的机器不太可能"同时挂了"
但是整个机房是否可能被一锅端了??(也是可能会存在的....)这个时候如果考虑到更高的可用性,就可以把这些机器放到多个不同的机房中.(异地多活)
由于从节点的数据都是时刻和主节点保持一致的因此其他的客户端从从节点这里读取数据,和从主节点这里读取数据,没有区别的!!
后续如果有客户端来读取数据了,就可以从上述节点中,随机挑一个节点,给这个客户端提供读取数据的服务
引入了更多的计算资源,自然能够支撑的并发量也就大幅提高了
2. 主从+哨兵模式
3. 集群模式
二、Redis 主从复制的核心原理
Redis 的主从复制并不是简单的数据拷贝,而是一套围绕 RDB 快照、命令流同步、偏移量对齐 构建的完整机制。
1. 主从节点的角色与职责划分
主节点(Master)
-
接收并处理所有写命令;
-
将写命令追加到复制缓冲区;
-
在需要时生成 RDB 快照并发送给从节点;
-
通过 TCP 连接将增量命令实时推送给所有从节点。
从节点(Slave)
-
默认只处理读请求,不接受写操作;
-
启动或重连时向主节点请求数据同步;
-
加载主节点发送的 RDB 文件;
-
持续接收并执行主节点推送的增量命令;
-
维护自己的复制偏移量,用于同步状态校验。
这种设计使得主节点承担写压力,从节点横向扩展读能力,整体架构既简单又高效。

三、主从复制的完整流程解析
Redis 的复制过程可以拆分为三个阶段:连接建立、全量同步、增量同步。

1. 建立连接与复制握手
当从节点执行 slaveof <master-ip> <master-port> 后,会发生以下过程:

-
建立 TCP 连接;
-
从节点发送
PING检测主节点状态; -
如配置了密码,则通过
AUTH完成认证; -
双方协商复制能力,准备进入同步阶段。
2. 全量同步:构建初始一致性
全量同步通常发生在以下场景:
-
从节点首次接入主节点;
-
主节点重启,runid 发生变化;
-
从节点断连时间过长,复制缓冲区数据已被覆盖。
全量同步的核心步骤包括:
-
主节点执行
bgsave生成 RDB 快照; -
生成快照期间,新写入的命令被暂存到复制缓冲区;
-
主节点将 RDB 文件发送给从节点;
-
从节点清空旧数据并加载 RDB;
-
主节点发送缓冲区中的增量命令;
-
主从数据达到完全一致。
需要注意的是,全量同步对主节点 CPU、内存和网络的消耗都较大,应尽量减少触发频率。
3. 增量同步:维持实时一致性
在正常运行阶段,主从复制主要依赖增量同步:
-
主节点每执行一条写命令,就会将其写入复制缓冲区;
-
同时通过 TCP 将命令推送给从节点;
-
从节点执行命令并更新自己的复制偏移量;
-
主从通过偏移量对齐,保证数据持续一致。


四、复制机制中的关键概念
1. 复制偏移量(offset)
偏移量本质上是一个"进度指针",用于表示已同步的数据量。主从双方通过比较 offset,可以快速判断是否存在数据缺失。
2. 复制缓冲区(repl backlog)
复制缓冲区是主节点维护的一个环形缓冲区,用于保存最近的写命令:
-
从节点短暂断连后,可以基于 offset 从缓冲区中补齐缺失数据;
-
缓冲区过小会导致数据被覆盖,从而触发全量同步。

就是一个内存中的简单的队列
会记录最近一段时间修改的数据
总量有限,随着时间的推移,就会把之前的旧的数据逐渐删掉

-
当主从节点之间出现网络中断时,如果超过repl-timeout 时间,主节点会认为从节点故障并终端复制连接。
-
主从连接中断期间主节点依然响应命令,但这些复制命令都因网络中断无法及时发送给从节点,所以暂时将这些命令滞留在复制积压缓冲区中。
-
当主从节点网络恢复后,从节点再次连上主节点。
-
从节点将之前保存的replicationId和复制偏移量作为psync 的参数发送给主节点,请求进行部分复制。
replicationld其实就是在描述"数据的来源",offset描述"数据的复制的进度"
-
主节点接到 psync请求后,进行必要的验证。随后根据offset 去复制积压缓冲区查找合适的数据,并响应+CONTINUE给从节点。
-
主节点将需要从节点同步的数据发送给从节点,最终完成一致性。
3. 运行 ID(runid)
一个redis 服务器上,replicationid和 runid是都存在的!!!两个不同的id,看起来非常像
每个 Redis 实例启动时都会生成唯一的 runid:
-
从节点通过 runid 判断主节点是否发生过重启;
-
runid 变化意味着历史数据不可追溯,只能全量同步。


4. PSYNC 协议
Redis 2.8 引入 PSYNC 协议,用于区分全量与增量同步,是现代 Redis 主从复制的核心基础。
psync这里可以从主节点获取全量数据,也可以获取一部分数据.
主要就是看offset这里的进度
ofset写作-1,就是获取全量数据.
ofset写具体的正整数,则是从当前偏移量位置来进行获取
获取所有数据,是最稳妥的,但是会比较低效.如果从节点之前已经从主节点这里复制过一部分数据了,就只需要把新的之前没复制过的数据搞过来即可
不是从节点索要那部分,主节点就一定给哪部分,主节点会自行判定,看当前是否方便给部分数据~~不方便就只能给全量了

五、性能优化与常见问题排查
1. 减少全量同步的触发
-
合理增大
repl-backlog-size; -
避免频繁重启主节点;
-
提高网络稳定性,减少断连。
2. 从节点延迟问题
-
排查网络带宽与延迟;
-
检查主节点写压力;
-
确保从节点 CPU 和内存资源充足。
3. 无盘复制与高性能场景
开启 repl-diskless-sync yes 可避免磁盘 IO,但会增加内存和网络压力,适用于内存充足、追求极致性能的场景。
4. 啥时候进行全量复制:
-
首次和主节点进行数据同步
-
主节点不方便进行部分复制的时候
5. 啥时候进行部分复制:
从节点之前已经从主节点上复制过数据了.因为网络抖动或者从节点重启了,从节点需要重新从主节点这边同步数据,此时看看能不能只同步一小部分(大部分数据都是一致的)

-
从节点发送psync命令给主节点进行数据同步,由于是第一次进行复制,从节点没有主节点的运行ID和复制偏移量,所以发送psync?-1。
-
主节点根据命令,解析出要进行全量复制,回复+FULLRESYNC响应。
-
从节点接收主节点的运行信息进行保存。
-
主节点执行bgsave进行 RDB文件的持久化。
-
主节点发送RDB文件给从节点,从节点保存RDB数据到本地硬盘
-
主节点将从生成RDB到接收完成期间执行的写命令写入缓冲区中,等从节点保存完RDB文件后,主节点再将缓冲区内的数据补发给从节点,补发的数据仍然按照rdb的二进制格式追加写入到收到的rdb文件中.保持主从一致性。
-
从节点清空自身原有旧数据。
-
从节点加载RDB文件得到与主节点一致的数据。
-
如果从节点加载RDB完成之后,并且开启了AOF持久化功能,它会进行bgrewrite操作,得到最近的AOF文件。
6. 全量复制
主节点,进行全量复制的时候,也支持"无硬盘模式"(diskless)
主节点,生成的rdb 的二进制数据,不是直接保存到文件中了,而是直接进行网络传输了(省下了一系列读硬盘和写硬盘的操作)从节点,之前,也是先把收到的rdb数据,写入到硬盘中,然后再加载现在也可以省略这个过程,直接把收到的数据进行加载了。
即使引入了无硬盘模式,仍然整个操作是比较重量,比较耗时的. 大规模数据(全量复制)网络传输,是没法省的。相比于网络传输来说,读写硬盘是小头
从节点要从主节点这里进行全量复制.全量复制,开销是很大的.有些时候,从节点本身已经持有了主节点的绝大部分数据,这个时候,就不太需要进行全量复制了,
比如,出现网络抖动,主节点这边最近修改的数据可能就无法及时同步过来了。更严重的,从节点已经感知不到主节点了(进一步的从节点可能会升级成主节点)
网络抖动,一般都是"暂时的",过一会就恢复了此时就可以让从节点和主节点重新建立联系
当从节点和主节点重新建立连接之后,就需要进行数据的同步。
psync带有具体的replid和offset值主节点就要根据psync的参数进行判定。当前这次是按照全量复制合适还是部分复制合适
7. 实时复制
从节点,已经和主节点,同步好了数据了(从节点这一时刻已经和主节点数据一致了)但是之后,主节点这边会源源不断的收到新的修改数据的请求.主节点上的数据就会随之改变.
也需要能够同步给从节点。
从节点和主节点之间会建立TCP的长连接
然后主节点把自己收到的修改数据的请求,通过上述连接,发给从节点从节点再根据这些修改请求,修改内存中的数据。
发送给从节点这个过程也是需要时间的
正常来说,这个延时是比较短的.但是如果是多级从节点的树形结构~~如果这里从节点的级别很多~~(有很多层),延时也就会上升
在进行实时复制的时候,需要保证连接处于可用状态
心跳包机制
默认是60s
-
主节点:默认,每隔10s给从节点发送一个ping命令.从节点收到就返回pong
-
从节点:默认,每隔1s就给主节点发起一个特定的请求,就会上报当前从节点复制数据的进度(ofset)
六、生产实践:部署、监控与演练
在生产环境中,主从复制并不是"配置完成就万事大吉",还必须配合规范化部署和持续监控。
主从节点必须分布在不同机器;
配置统一管理,避免配置漂移;
通过
INFO replication持续监控复制状态;定期进行主节点宕机演练,验证切换能力。
++主从复制,最大的问题还是在主节点上.++
主节点挂了,从节点就迷茫了。虽然能够提供读操作,但是从节点不能自动的升级成主节点。不能替换原有主节点对应的角色。此时,就需要程序猿/运维手工的恢复主节点(非常繁琐的)
Redis哨兵自动的对挂了的主节点进行替换
从节点和主节点之间断开连接,有两种情况:
- 从节点主动和主节点断开连接.
slaveof no one
这个时候,从节点,就能够晋升成主节点
意味着我们程序猿要主动修改redis的组成结构
- 主节点挂了
这个时候,从节点,不会晋升成主节点的
必须通过人工干预的方式,恢复主节点
这个是脱离咱们掌控的高可用下的一个典型问题
七、从主从复制到高可用架构的演进
-
主从复制:解决数据冗余与读写分离;
-
哨兵模式:解决主节点自动故障转移;
-
集群模式:解决数据分片与容量扩展问题。
不同阶段选择不同方案,才能在复杂度和收益之间取得平衡。
八、总结
Redis 主从复制是所有高可用 Redis 架构的基石。只有真正理解其底层原理、同步机制和性能边界,才能在生产环境中合理配置、稳定运行,并在故障发生时快速定位问题。主从只是开始,哨兵与集群才是规模化系统的必经之路,而扎实的复制原理理解,是走向更复杂架构的前提。