一、主从复制总结
主从复制解决的问题就是单点问题:
1、单个 redis 节点,可用性不高。
2、单个 redis 节点,性能有限。
主从复制的特点:
- Redis 通过复制功能实现主节点的多个副本。 主节点用来写,从节点用来读。这样做可以降低主节点的访问压力。
- 复制支持多种拓扑结构,可以在适当的场景选择合适的拓扑结构。 复制分为全量复制,部分复制和实时复制。
- 主从节点之间通过心跳机制保证主从节点通信正常和数据⼀致性。
主从复制配置的过程:
主节点配置不需要改动。从节点在配置文件中加入 slaveof 主节点ip 主节点端口的形式即可。
主从复制的缺点:
1、从机多了,复制数据的延时非常明显。
2、主机挂了,从机不会升级成主机。只能通过人工干预的方式恢复。
复制积压缓冲区
“复制积压缓冲区”:用于主从复制中的部分重同步,是一个循环缓冲区,存储最近的写命令。
持久化机制
“持久化机制”:如RDB和AOF,用于在节点重启后恢复数据。主节点数据的恢复不依赖于复制积压缓冲区,而是依赖于持久化机制(RDB快照和AOF日志)。
因此,即使复制积压缓冲区满了,移除了旧命令,只要主节点配置了持久化,就可以通过加载RDB文件或重放AOF日志来恢复数据。
主节点数据恢复流程:
1、“持久化配置”:
“RDB”:定期生成数据快照 或者 “AOF”:记录每个写命令。
2、“主节点重启后”:
如果配置了AOF,优先使用AOF恢复(因为AOF更完整)。如果没有AOF,但配置了RDB,则使用RDB恢复。
“恢复数据”
主节点从磁盘加载RDB或AOF文件,将数据恢复到内存中。
“复制积压缓冲区”:主节点重启后,复制积压缓冲区是空的,因为它是内存中的结构,且没有持久化。所以,主节点重启后,从节点需要全量同步,因为部分同步所需的缓冲区数据已经不存在了。
全量复制
1、主服务器执行 BGSAVE,在后台生成 RDB 快照文件
2、同时主节点使用复制缓冲区记录生成 RDB 期间的所有写命令
3、从服务器清空自己的数据,然后加载 RDB 文件
4、主服务器将RDB生成期间缓冲的写命令,发送给从服务器。
部分复制
偏移量比对
1、从服务器发送自己的复制偏移量给主服务器
2、主服务器检查偏移量是否在复制积压缓冲区中
发送缺失的命令
1、如果偏移量在缓冲区内,主服务器发送缺失的命令给从服务器
2、从服务器执行这些命令,快速追上主服务器
3、如果从服务器的复制偏移量不在主服务器的复制积压缓冲区中,就会触发全量同步。
二、建立主从复制
操作命令,在节点的配置文件
1、在配置文件中加入slaveof {masterHost} {masterPort}随Redis启动生效。
2、接下来,我们将redis.conf配置文件复制一份redis-slave.conf,并且修改其daemonize为yes。这样主从就配置好了。
复制偏移量
主节点保存了
"自己的master_repl_offset" - 主节点全局复制偏移量
"每个从节点的slave_repl_offset" - 记录每个从节点的同步进度
从节点保存了:
"自己的 slave_repl_offset" - 从节点已处理的偏移量
"主节点的 master_repl_offset" - 从节点所知的主节点最新偏移量
那么主和从的2个偏移量是在什么时候增加的?

备注:主节点往从节点异步发送命名时,会把主节点最新的master_repl_offset发送过去。
2、从节点定期(默认每秒10次)向主节点发送REPLCONF ACK <slave_repl_offset>,主节点据此更新该从节点的偏移量记录。
三、断开主从复制
断开与主节点复制关系,从节点晋升为主节点。
从节点断开复制后并不会抛弃原有数据,只是无法再获取主节点上的数据变化
将当前从节点的数据源切换到另一个主节点
- 断开与旧主节点复制关系。
- 与新主节点建立复制关系。
- 删除从节点当前所有数据。
- 从新主节点进行复制操作。
四、主从复制的拓扑结构
根据拓扑复杂性可以分为以下三种:一主一从、一主多从、树状主从结构。
一主一从结构
一主一从结构是最简单的复制拓扑结构,用于主节点出现宕机时从节点提供故障转移支持

一主多从结构
一主多从结构(星形结构)使得应用端可以利用多个从节点实现读写分离,如图所示。对于读比重较大的场景,可以把读命令负载均衡到不同的从节点上来分担压力。同时一些耗时的读命令可以指定一台专门的从节点执行,避免破坏整体的稳定性。

树形主从结构
树形主从结构(分层结构)使得从节点不但可以复制主节点数据,同时可以作为其他从节点的主节点继续向下层复制。

五、主从复制实现原理
主从复制过程
1、在从节点的配置文件上,保存主节点(master) 的信息。开始配置主从同步关系之后,从节点只保存主节点的地址信息(主节点的ip和port),此时建立复制流程还没有开始
2、从节点(slave) 内部通过每秒运行的定时任务维护复制相关逻辑,当定时任务发现存在新的主节点后,会尝试与主节点建立基于TCP的网络连接。如果从节点无法建立连接,定时任务会无限重试直到连接成功或者用户停止主从复制。
3、发送ping命令。连接建立成功之后,从节点通过ping命令确认主节点在应用层上是工作良好的。如果ping命令的结果pong回复超时,从节点会断开TCP连接,等待定时任务下次重新建立连接。
4、权限验证。如果主节点设置了requirepass参数,则需要密码验证,从节点通过配置masterauth参数来设置密码。如果验证失败,则从节点的复制将会停止。
5、同步数据集。对于首次建立复制的场景,,主节点会把当前持有的所有数据全部发送给从节点,这步操作基本是耗时最长的,所以又划分称两种情况:全量同步和部分同步。
6、命令持续复制。当从节点复制了主节点的所有数据之后,针对之后的修改命令,主节点会持续的把命令发送给从节点,从节点执行修改命令,保证主从数据的一致性。
数据同步psync命令
Redis使用psync命令完成主从数据同步,同步过程分为:全量复制和部分复制。
全量复制:一般用于初次复制场景,它会把主节点全部数据一次性发送给从节点,当数据量较大时,会对主从节点和网络造成很大的开销。
部分复制:用于处理在主从复制中因网络闪断等原因造成的数据丢失场景,当从节点再次连上主节点后,如果条件允许,主节点会补发数据给从节点。因为补发的数据远小于全量数据,可以有效避免全量复制的过高开销。
PSYNC命令的语法格式:
PSYNC replicationid offset
//如果replicationid offset 设为-1此时就是在尝试进行全量复制.
//如果replicationid offset 设为了具体的数值,则是尝试进行部分复制.
replicationid是什么?
1、replicationid是主节点的复制id。主节点重新启动,或者从节点晋级成主节点,
都会生成一个replicationid. (同一个节点,每次重启,生成的replicationid也会变化)。
2、从节点在和主节点建立连接之后,就会获取到主节点的replicationid。
offset 是什么?
1、参与复制的主从节点都会维护自身复制偏移量。主节点(master) 在处理完写入命令后,
会把命令的字节长度做累加记录,
2、从节点(slave) 每秒钟上报自身的复制偏移量给主节点,因此主节点也会保存从节点的复
制偏移量,主节点根据从节点的偏移量计算需要复制的内容。
3、从节点在接受到主节点发送的命令后,也会累加记录自身的偏移量。
4、通过对比主从节点的复制偏移量,可以判断主从节点数据是否一致。
5、replid + offset共同标识了一个"数据集"。如果两个节点,他们的replid和offset
都相同,则这两个节点上持有的数据,就一定相同
psync的运行流程
1、从节点发送psync命令给主节点,replid和offset的默认值分别是"主节点ID"和 -1。
2、主节点根据psync参数和自身数据情况决定响应结果:
如果回复+FULLRESYNC replid offset, 则从节点需要进行全量复制流程。
如果回复+CONTINEU,从节点进行部分复制流程。
如果回复-ERR,说明Redis主节点版本过低,不支持psync命令。从节点可以使用sync命令进行
全量复制
psync一般不需要手动执行。Redis会在主从复制模式下自动调用执行
sync会阻塞redis server处理其他请求。psync则不会
全量复制
全量复制是Redis最早支持的复制方式,也是主从第-次建立复制时必须经历的阶段。全量复制的运行流程如图所示。

- 从节点发送psync命令给主节点进行数据同步,由于是第一-次进行复制, 从节点没有主节点的运行ID和复制偏移量,所以发送psync?-1。
- 主节点根据命令,解析出要进行全量复制,回复+FULLRESYNC响应。 从节点接收主节点的运行信息进行保存。 主节点执行bgsave进行RDB文件的持久化。 主节点发送RDB文件给从节点,从节点保存RDB数据到本地硬盘。
- 主节点将从生成RDB到接收完成期间执行的写命令,写入缓冲区中,等从节点保存完RDB文件后,主节点再将缓冲区内的数据补发给从节点,补发的数据仍然按照rdb的二进制格式追加写入到收到的rdb文件中保持主从一致性。
- 从节点清空自身原有旧数据。 从节点加载RDB文件得到与主节点一致的数据。
- 如果从节点加载RDB完成之后,并且开启了AOF持久化功能,它会进行bgrewrite操作,得到最近的AOF文件。
- 通过分析全量复制的所有流程,我们会发现全量复制是一件高成本的操作。主节点bgsave的时间,RDB在网络传输的时间,从节点清空旧数据的时间,从节点加载RDB的时间等。所以一般应该尽可能避免对已经有大量数据集的Redis进行全量复制。
总结下来重点就是:
1、主服务器执行 BGSAVE,在后台生成 RDB 快照文件
2、同时主节点使用复制缓冲区记录生成 RDB 期间的所有写命令
3、从服务器清空自己的数据,然后加载 RDB 文件
4、主服务器将RDB生成期间缓冲的写命令,发送给从服务器。
部分复制
部分复制主要是Redis针对全量复制的过高开销做出的一种优化措施,使用psync replicationld offset命令实现。当从节点正在复制主节点时,如果出现网络闪断或者命令丢失等异常情况时,从节点会向主节点要求补发丢失的命令数据,如果主节点的复制积压缓冲区存在数据则直接发送给从节点,这样就可以保持主从节点复制的一致性。补发的这部分数据一般远远小于全量数据 ,所以开销很小。整体流程如图所示。
- 当主从节点之间出现网络中断时,如果超过repl-timeout 时间,主节点会认为从节点故障并中断复制连接。
- 主从连接中断期间主节点依然响应命令,但这些复制命令都因网络中断无法及时发送给从节点,所以暂时将这些命令滞留在复制积压缓冲区中。
- 当主从节点网络恢复后,从节点再次连上主节点。
- 从节点将之前保存的replicationld和复制偏移量作为psync的参数发送给主节点,请求进行部分复制。
- 主节点接到psync请求后,进行必要的验证。随后根据offset去复制积压缓冲区查找合适的数据,并响应+CONTINUE给从节点。
- 主节点将需要从节点同步的数据发送给从节点,最终完成一致性。

总结:
偏移量比对
1、从服务器发送自己的复制偏移量给主服务器
2、主服务器检查偏移量是否在复制积压缓冲区中
发送缺失的命令
1、如果偏移量在缓冲区内,主服务器发送缺失的命令给从服务器
2、从服务器执行这些命令,快速追上主服务器
3、如果从服务器的复制偏移量不在主服务器的复制积压缓冲区中,就会触发全量同步。
3123

被折叠的 条评论
为什么被折叠?



