主从复制原理和优化
性质
- 一个主节点可以有多个从节点,一个从节点只能有一个主节点
- 从节点本身也是一个主节点,可以有自己的从节点
- 数据流是单向的,只能从主节点到从节点
作用
- 从节点通过备份复制同步主节点上的数据,形成数据副本,是高可用可分布式的基础
- 当主节点宕机时,从节点升级为主节点顶替主节点的工作,达到高可用的效果
- 从节点是只读的,主节点是可读写的,从节点可以承担读操作,主节点承担写操作,达到读写分离效果,从而减轻主节点的负担
实现方式
info replication
命令可以查看该节点的从属关系
命令方式
slaveof
:希望当前Redis服务成为某个IP和端口下的Redis服务的从属- 该命令是异步的
- 该命令会清除当前数据库的所有数据然后去同步主节点数据
slaveof no one
:不希望成为任何人的从属- 并不会将之前同步的数据清除,仅仅是断掉连接
配置文件方式
配置项 | 描述 | 默认值 |
---|---|---|
slaveof |
设置当前节点作为其他节点的从节点,指定IP和端口 | |
masterauth |
主节点的密码 | |
slave-read-only |
设置当前为从节点时是只读的,不会执行写操作 | yes |
原理
run_id
是Redis服务器的随机标识符,服务重启后就会改变,当从节点复制时发现主节点的run_id
和之前的不同时,就认为主节点发生了重大变化,会进行全量复制,使用info server
命令可查看到run_id
项
参与主从复制的节点都会维护自身的偏移量,在处理完更新命令后,将更新数据量累加到偏移量(单位字节),从节点每秒上报自身偏移量给主节点,主节点会记录从节点的偏移量,主从节点通过该偏移量可判断主从节点数据是否一致,使用info replication
命令查看
- 对于主节点
master_repl_offset
项为主节点偏移量,slave
(该项后还会有从节点编号)项为该节点从节点信息 - 对于从节点
slave_repl_offset
项为从节点偏移量
全量复制
流程
- 从节点向主节点发送同步命令
psync ? -1
:问号代表不知道主节点runid,-1
为从节点的偏移量,即第一次复制 - 主节点收到同步消息后,通知从节点要进行全量复制(发送
+FULLRESYNC
信号),并将自身的runid和偏移量发送给从节点- 之后通过
bgsave
命令进行RDB文件生成,生成完成后会向从节点发送RDB文件 - 若在
bgsave
过程中有新的更新命令,会将这些命令放入复制缓冲区,生成完成后也会发送复制缓冲区中的内容
- 之后通过
- 从节点收到进行全量复制的命令后,保存主节点相关信息(runid和偏移量)
- 从节点收到RDB文件后,会先清空当前数据库的所有数据
- 根据接收RDB文件开始进行恢复,若还收到复制缓冲区内容也会同时加载进来
开销
- 对于主节点来说:bgsave的开销、RDB文件网络传输开销
- 对于从节点来说:清空数据开销、加载RDB开销、若还开启了AOF重写,需要重写AOF,以保证AOF最新
所以要尽量的避免全量复制,但是对于第一次的全量复制是无法避免的
部分复制
在Redis4.0中,优化了psync,简称psync2,实现了即使redis实例重启的情况下也能实现部分同步
- 节点和从节点之间发生了网络抖动,导致这期间数据是无法同步
- 主节点将这期间的更新命令放入复制缓冲区,缓冲区默认大小为1MB,使用
info replication
命令repl_backlog_size
项可以查看
- 主节点将这期间的更新命令放入复制缓冲区,缓冲区默认大小为1MB,使用
- 重新建立连接后,从节点会发送消息告知主节点自身偏移量和runid
- 主节点校验从节点的偏移量
- 偏移量在复制缓冲区保存范围内,则通知从节点进行部分复制(发送
CONTINUE
信号),将未同步的数据进行同步 - 偏移量不再范围内,则通知从节点进行全量复制
- 偏移量在复制缓冲区保存范围内,则通知从节点进行部分复制(发送
优化
- 复制数据延迟:当更新操作从主节点同步到从节点时会有短暂的延迟,当网络原因或从节点阻塞时,这个延迟会比较长,导致主从不一致
- 解决:对偏移量进行监控,当有问题时,将请求转移到其他节点上
- 主从节点内存不一致:若主节点内存大于从节点内存,可能会导致从节点丢失数据
- 解决:使用标准工具进行安装,并且对其监控
- 读到过期数据:在之前版本中,对于过期数据的检验是懒惰式和定时检测策略,但是在3.2版本中已经得到解决
- 懒惰式:在操作该数据时才会判断该数据是否过期,过期后会删除并返回空,从节点是不能执行更新操作的,所以会读到脏数据
- 定时检测策略:定期检测数据是否过期,若过期就将其删除,若在空挡期间读取数据就会读到脏数据
- 复制风暴:主节点重启后,runid发生变化,导致所有从节点进行全量复制操作
- 解决1:采用故障转移方式(从节点升级为主节点)来避免全量复制
- 解决2:增大复制缓冲区
rel_backlog_size
的容量 - 解决3:使用一主一从、一从多从的链式结构,将复制风暴转移到从节点上,减轻主节点的压力
Comments NOTHING