目录
主从模式
主从复制作用
建立主从复制
主节点信息
从节点信息
断开主从复制关系
主从拓扑结构
主从复制原理
1. 复制过程
2. 数据同步(PSYNC)
3. 三种复制方式
一、全量复制
二、部分复制
三、实时复制
四、主从复制模式存在的问题
在非分布式系统中,即仅有一个主机提供服务时,如果该主机发生故障,整个服务将会崩溃。这种情况被称为单点问题,它不仅影响了系统的可用性,还限制了系统的并发处理能力。
为了解决单点问题并提高服务的并发处理能力,可以引入分布式系统。通过多个主机共同完成一个服务:
- 提升并发能力:多台服务器分担负载,支持更大数量的客户端请求。
- 避免单点故障:即使一台服务器出现故障,其他服务器仍能继续提供服务,确保业务连续性。
主从模式
在分布式系统中,Redis通常采用以下三种部署模式之一:
- 主从模式
-
- 定义:包含一个主服务器(Master)和多个从服务器(Slave)。所有写操作都在主服务器上执行,而读操作可以在从服务器上分散进行。
- 数据一致性:从服务器的数据是从主服务器复制而来,且不允许直接修改,以保证数据的一致性和完整性。
- 工作原理:写入操作集中在主节点,查询操作则被分配到从节点,确保主节点的数据是最新的,同时减轻其负载。
- 主从 + 哨兵模式
-
- 概述:在主从模式基础上加入了哨兵(Sentinel)组件,用于监控集群健康状况,并在主节点故障时自动选择一个新的主节点。
- 功能:提供了自动化的故障检测与恢复机制,减少了人工干预的需求。
- 集群模式
-
- 特点:允许多个Redis实例协同工作,形成一个逻辑上的大型数据库,支持水平扩展。
- 适用场景:适合需要 更大存储容量或更高性能的应用环境。
本博客将 重点讲解 Redis的主从模式,包括其工作原理、优势以及如何帮助解决单点问题,从而提高了服务的可靠性和性能。
- 本章节相关操作不需要记忆,后续如果用到了能查到即可。
- 重点是理解主从复制的流程和原理。
主从复制作用
- 解决单点问题,通过数据复制多个副本部署到其他服务器,满足 故障恢复和负载均衡 等需求。
- 复制功能 是高可用Redis的基础,哨兵和集群 都是在复制的基础上构建的。
- 从节点上的数据要跟随主节点变化,从节点的数据要和主节点保持一致
-
- 主从模式,从 要是针对"读操作",进行并发量和可用性的提高
- 写操作,无论是可用性还是并发量,都非常依赖主节点,主节点不能搞多个
建立主从复制
- 参与复制的Redis实例划分为主节点(master)和从节点(slave)
-
- 每个从结点只能有⼀个主节点,⽽⼀个主节点可以同时具有多个从结点
- 复制的数据流是单向的,只能由主节点到从节点。
配置:
大部分人手上都只有一台主机或者云服务器,此时想要打造一个分布式系统就需要用一些其他技巧,而不是真的在多个主机上部署分布式。
- 其实在一台主机上,是可以允许多个
redis-server
进程的,只要保证 每个进程的端口号不同,那么就可以有多个redis-server
存在。 - 创建从节点的配置文件:
- 找到
port
选项:默认的端口号是6379
,此端口号修改为其它端口,不要与主节点冲突。 - 找到
daemon
选项,保证该选项是yes
,这样Redis
才能在后台运行。
修改这两个配置文件后启动
启动后通过ps
查看,可以看到同时有三个Redis
在运行:
绑定的三个端口分别是:6379
、6380
、6381
。
启动不同的客户端
此时三个节点是单独的三个服务,还没有构成主从结构。
配置主从需要通过slaveof
,有以下三种方式:
- 配置文件中加入
slaveof {masterHost} {masterPort}
随Redis启动生效。 - 在
redis-server
启动命令时加入--slaveof {masterHost} {masterPort}
生效。 - 直接使用
redis
命令:slaveof {masterHost} {masterPort}
生效。
此处通过修改配置文件完成主从配置,因为其是持久的,后两种方式在每车次启动时都要输入额外的命令。
在两个slave.conf
shift+g 到最末尾加上以下内容
kill -9 后,重启服务器,查看网络情况
可以发现,除了三个redis-server
,还有很多其它的redis
网络连接,这是因为主从之间,要进行数据传输,所以要创建额外的网络连接。
测试一下:
左侧端口为6379
主节点,右侧为6380
从节点,主节点设置key1 123
,从节点可以get
得到,但是当从节点试图写入数据,发生报错,表示不允许修改数据。
- 只读模式:默认情况下,从节点配置为只读模式(
slave-read-only=yes
),以防止数据不一致。
在主节点和从节点之间的TCP网络连接中,默认启用了Nagle算法:旨在通过合并较小的TCP数据包来减少传输的数据包数量,从而节省带宽。然而,这可能会增加TCP的传输延迟。反之,关闭Nagle算法可以减少传输延迟但会增加网络带宽的使用。
- 默认状态:Nagle算法默认是开启的(
repl-disable-tcp-nodelay
设置为no
)。 - 关闭Nagle算法:可以通过设置
repl-disable-tcp-nodelay yes
来关闭Nagle算法,以减少传输延迟。这种调整适用于主从节点间网络环境良好、低延迟的情况,例如同机房部署;而在跨机房等复杂网络环境中,则可能需要保持Nagle算法开启以优化带宽使用。
info replication
,可以查看主从相关的信息。
主节点信息
role
:表示当前节点为主节点connected_slaves
:当前有两个从节点slave0
:第一个从节点的相关信息,
-
ip
:地址port
:端口state
:状态
master_replid
:标识主节点的身份ID。master_replid2
:用于在 网络抖动情况下 启用,记录 旧主节点的复制ID,以便后续重新连接。offset=475
:表示当前从节点复制到的位置,即 偏移量。- 以
repl_backlog
开头的字段:描述了 积压缓冲区 的状态,支持部分同步机制。
从节点信息
master_xxx
:主节点的一些信息slave_priority
:一个优先级,如果主节点崩溃了,会从新选主节点,与该优先级有关master_replid
:主节点的idconnected_slaves
:表明当前节点下连接的从节点数量,若无则显示0。
这些内容也不需要记忆,可以去官网查询,官方文档有很详细的解释。
redis_info commands
断开主从复制关系
- 指令:可以在从节点中输入
SLAVEOF NO ONE
指令用来断开现有的所有主从复制关系。 - 效果:从节点断开主从关系后,不再隶属于其他节点,但内部已有的数据不会被抛弃。当前断开的从节点 会晋升为主节点。
我们可以尝试来实现一下 这个“认贼作父”的过程
实现:
此处通过slaveof
重新将6380
设置为了6381
的主节点。
不论是salveof
,还是slaveof no one
,都是临时修改主从关系,一旦服务重启,仍然依照配置文件设置主从关系。
主从拓扑结构
拓扑结构:若干个节点之间,按照什么样的方式来进行组织连接
Redis 的复制拓扑结构支持单层或多层的复制关系,根据复杂性可以分为以下三种:
1. 一主一从拓扑
- 特点:最简单的拓扑结构。
- 优化:可以通过 关闭主节点的AOF,只在从节点上开启AOF来减少主节点的压力。
- 缺陷及改进:一旦主节点宕机,需要让主节点从从节点获取AOF文件再重启,以防止数据丢失和同步问题。
注意:这种方式要 关闭主节点的自动重启功能,因为主节点使用RDB
持久化,此时数据往往不是最新的。一旦主节点重启,那么就会通过RDB
恢复数据,导致主节点得到旧数据。而这个旧数据又会同步给从节点,此时从节点的AOF
新数据就被旧数据覆盖了
2. 一主多从拓扑
- 适用场景:适用于读数据比重较大的场景,可以将 读命令负载均衡 到不同的从节点上来分担压力。
- 缺点:不适用于写数据比重较大的场景,因为随着从节点个数增加,主节点的网络传输压力也会增大。
3. 树形拓扑
- 特点:从节点不仅可以复制主节点数据,还可以作为其他从节点的主节点继续向下层复制。
- 优势:相比一主多从结构,可以减少主节点网络传输压力,不需要那么高的网卡带宽。
- 缺点:数据修改后的 同步延时更长。
主从复制原理
1. 复制过程
- 保存信息:首先保存主节点的信息,包括IP和端口。
- 建立连接:之后 建立主从节点之间的TCP连接(经历三次握手)。
- 验证连接:给主节点发送PING命令,验证其是否正常工作。
- 数据同步:包括全量同步(首次连接时同步所有数据)和命令持续复制(增量同步,后续每一步操作都进行同步)。
在整个主从同步的过程中,最后两步分别是
同步数据集
和持续复制命令,是复制数据的关键步骤
和后面讲的 三种同步机制之间:
同步数据集:
- 如果是第一次同步,触发
全量同步
- 如果是断线重连,触发
部分同步
持续复制命令:
- 进行
实时同步
2. 数据同步(PSYNC
)
Redis 提供了 PSYNC
命令来完成数据同步的过程。PSYNC
指令一般不需要我们手动执行,Redis 服务器会在建立好主从同步关系之后自动执行 PSYNC
。
其语法格式为 PSYNC replicationid offset
replicationid
:
-
- 表示的是主节点的复制ID。这个ID是主节点启动时生成的,每次主节点重启后生成的
replicationid
都是不一样的。或者是在从节点和主节点断开之后,从节点晋升为主节点时也会生成新的replicationid
。 - 这个参数实际上就是我们之前通过
info replication
查询出来的master_replid
。一旦从节点与主节点建立了复制关系,它就会从主节点这边获取到replicationid
。
- 表示的是主节点的复制ID。这个ID是主节点启动时生成的,每次主节点重启后生成的
offset
:
-
- 这个参数是主节点和从节点上都会维护的数据偏移量,它是一个整数。
- 主节点上会收到很多修改操作的命令,每个命令都要占据一定的字节数。主节点会把这些修改命令中的数据的字节数进行累加,得到主节点的
offset
。 - 从节点的偏移量描述的是当前从节点在从主节点同步数据时同步到了哪里。从节点每秒钟都会上报自身的复制偏移量给主节点。
replid
和 offset
共同确定一个唯一的数据集
关于 PSYNC
的工作方式:
PSYNC
可以从主节点中获取全量数据,也可以获取一部分数据,这主要取决于offset
的进度。如果offset
设置为-1
,则表示获取全量数据;如果offset
设置为具体的整数值,则表示从当前的偏移量开始进行获取。
当输入psync
后,可能得到以下三种结果:
+FULLRSYNC replid offset
:进行全量复制+CONTINUE
:进行部分复制-ERR
:说明主节点不支持psync
,此时可以使用sync
此处sync
是在前台运行的命令,一旦执行sync
,主节点的所有命令都会被阻塞。
注意:
在获取数据时,并不是从节点请求哪部分数据,主节点就提供哪部分数据。
- 主节点会自行判定当前是否方便提供部分数据,若不方便,则只能提供全量数据。
- 从节点申请进行全量复制,此时主节点无法承受这么多网络压力,那么可能就会变成部分复制。
3. 三种复制方式
一、全量复制
触发条件:首次与主节点进行数据同步时,或在主节点不方便进行部分复制的情况下,从节点会进行全量复制。此时的 replicationid
和 offset
分别是未知和 -1
。
流程:
- 发起同步:从节点发送
PSYNC
命令给主节点进行数据同步,由于初次复制,从节点没有主节点的运行ID和offset,因此默认执行全量复制。 - 响应确认:主节点根据命令解析出要进行全量复制,并回复
+FULLRESYNC
响应。 - 保存信息:从节点接收并 保存主节点的运行信息(eg. id...)
- 持久化快照:主节点执行
BGSAVE
进行 RDB 文件的持久化。 - 传输快照:主节点将生成的 RDB 文件发送给从节点,从节点保存该文件到本地磁盘。
- 补发增量:主节点将从生成 RDB 文件到接收完成期间执行的写命令的数据写入缓冲区,等从节点保存完 RDB 文件之后,再将缓冲区内的数据补发。
- 清理旧数据:从节点清空自身原有的旧数据。
- 加载新数据:从节点 加载 RDB 文件以获得与主节点一致的数据。(5+6)
- 持久化操作:如果从节点开启了 AOF 持久化,则会进行重写操作;如果没有开启,则全量化复制完成。
无硬盘模式支持:
- 主节点在进行全量复制时也支持“无硬盘模式”,即主节点生成的 RDB 二进制数据直接通过网络传输给从节点,无需先保存到文件中。
- 从节点也可以省略把收到的数据写入硬盘的过程,直接加载。这虽然节省了读写硬盘的操作,但网络传输消耗不可避免。
二、部分复制
适用场景:当从节点已经持有主节点绝大部分的数据时,为了减少开销,可以进行部分复制。例如在网络抖动后重新建立连接时,只需同步中断期间的数据变化即可。
流程:
- 超时判定:当主节点和从节点出现网络中断超过
repl-timeout
时间,主节点会认为从节点故障。 - 命令滞留:中断期间,主节点继续响应命令,但由于网络问题无法及时发送给从节点,这些命令被暂时滞留在 积压缓冲区。
- 主节点与从结点网络恢复.
- 从节点将之前保存的
replicationid
和复制偏移量作为PSYNC
参数发送给主节点,请求部分复制。 - 验证与查找:主节点接收到
PSYNC
请求后,进行必要的验证,随后根据offset区复制积压缓冲区查找合适的数据,并响应+CONTINUE给从节点. - 数据同步:主节点将所需同步的数据发送给从节点,最终完成一致性。
在第5步的时候,验证的步骤具体是什么呢?
- 首先验证
replicationid
是否一致。如果不一致,则进行全量复制; - 如果一致,则进一步判断
offset
是否存在于积压缓冲区中。若存在,则可以进行部分复制;否则需要全量复制。 - [ 这里是一个非常经典的验证思想 ]
三、实时复制
- 描述:主从节点在建立复制连接后,主节点会把自己收到的修改操作,通过 TCP 长连接的方式,源源不断的传输给从节点,从节点就会根据这些请求来同时修改自身的数据,保持从节点和主节点数据的一致性。
- 机制:从节点和主节点之间维持一个TCP长连接,主节点通过此连接将收到的修改数据请求发送给从节点。为确保网络连接可用,引入了 心跳包机制——主节点 每隔10秒 给从节点发送一个
PING
命令,从节点接收到后返回PONG
;同时,从节点每秒向主节点上报当前复制进度(offset
)。
如果主节点发现从节点通信延迟超过repl-timeout
配置的值(默认60秒),则判定从节点下线,断开复制客户端连接。从节点恢复连接后,心跳机制继续进行。
四、主从复制模式存在的问题
- 核心挑战:最大的问题在于主节点上。如果主节点意外宕机,从节点虽能继续提供读操作,但不会自动升级为主节点(除非通过
SLAVEOF NO ONE
断开)。这时就需要程序员手动恢复主节点,或者引入哨兵模式来实现自动故障转移。