目录
- 1.复制
- 1.全量复制
- 2.1部分复制
- 2.2复制积压缓冲区
- 3.实时复制
- 2.总结
1.复制
1.全量复制
-
什么时候进行全量复制?
- 首次和主节点进行数据同步
- 主节点不方便进行部分复制的时候
-
全量复制流程:
- 从节点发送
psync
命令给主节点进⾏数据同步,由于是第⼀次进⾏复制,从节点没有主节点的运⾏ID和复制偏移量,所以发送psync ? -1
- 主节点根据命令,解析出要进⾏全量复制,回复
+FULLRESYNC
响应 - 从节点接收主节点的运⾏信息进⾏保存
- 主节点执⾏
bgsave
进⾏RDB⽂件的持久化 - 主节点发送RDB⽂件给从节点,从节点保存RDB数据到本地硬盘
- 主节点将从⽣成RDB到接收完成期间执⾏的写命令,写⼊缓冲区中,等从节点保存完RDB⽂件后,主节点再将缓冲区内的数据补发给从节点,补发的数据仍然按照RDB的⼆进制格式追加写⼊到收到的rdb⽂件中,保持主从⼀致性
- 从节点清空⾃⾝原有旧数据
- 从节点加载RDB⽂件得到与主节点⼀致的数据
- 如果从节点加载RDB完成之后,并且开启了AOF持久化功能,它会进⾏
bgrewrite
操作,得到最近的AOF⽂件
- 从节点发送
-
注意:全量复制是⼀件⾼成本的操作
- 主节点
bgsave
的时间, RDB在⽹络传输的时间,从节点清空旧数据的时间,从节点加载RDB的时间等 - 所以⼀般应该尽可能避免对已经有⼤量数据集的Redis进⾏全量复制
- 主节点
-
有磁盘复制 VS 无磁盘复制
- 默认情况下,进⾏全量复制需要主节点⽣成RDB⽂件到主节点的磁盘中,再把磁盘上的RDB ⽂件通过发送给从节点
- Redi 从2.8.18版本开始⽀持⽆磁盘复制,主节点在执⾏RDB⽣成流程时,不会⽣成RDB⽂件到磁盘中了,⽽是直接把⽣成的RDB数据通过⽹络发送给从节点,这样就节省了⼀系列的写硬盘和读硬盘的操作开销
2.1部分复制
- 部分复制主要是Redis针对全量复制的过⾼开销做出的⼀种优化措施
- 使⽤
psync replicationId offset
命令实现
- 使⽤
- 什么时候进行部分复制?
- 当从节点正在复制主节点时,如果出现⽹络闪断或者命令丢失等异常情况时,从节点会向主节点要求补发丢失的命令数据,如果主节点的复制积压缓冲区存在数据则直接发送给从节点, 这样就可以保持主从节点复制的⼀致性
- 补发的这部分数据⼀般远远⼩于全量数据,所以开销很⼩
- 部分复制流程:
- 当主从节点之间出现⽹络中断时,如果超过
repl-timeout
时间,主节点会认为从节点故障并中断复制连接 - 主从连接中断期间主节点依然响应命令,但这些复制命令都因⽹络中断⽆法及时发送给从节点,所以暂时将这些命令滞留在复制积压缓冲区中
- 当主从节点⽹络恢复后,从节点再次连上主节点
- 从节点将之前保存的
replicationId
和复制偏移量作为psync
的参数发送给主节点,请求进⾏部分复制 - 主节点接到
psync
请求后,进⾏必要的验证,随后根据offset
去复制积压缓冲区查找合适的数据, 并响应+CONTINUE
给从节点 - 主节点将需要从节点同步的数据发送给从节点,最终完成⼀致性
- 当主从节点之间出现⽹络中断时,如果超过
2.2复制积压缓冲区
-
复制积压缓冲区是保存在主节点上的⼀个固定⻓度的队列,默认⼤⼩为1MB
- 会记录最近一段时间修改的数据
- 总量有限,随着时间的推移,就会把之前的旧的数据逐渐删掉
-
当主节点有连接的从节点(
slave
)时被创建,这时主节点(master
)响应写命令时,不但会把命令发送给从节点,还会写⼊复制积压缓冲区
-
由于缓冲区本质上是先进先出的定⻓队列,所以能实现保存最近已复制数据的功能,⽤于部分复制和复制命令丢失的数据补救
-
复制缓冲区相关统计信息可以通过主节点的
info replication
中127.0.0.1:6379> info replication # Replication role:master ... repl_backlog_active:1 // 开启复制缓冲区 repl_backlog_size:1048576 // 缓冲区最⼤⻓度 repl_backlog_first_byte_offset:7479 // 起始偏移量,计算当前缓冲区可⽤范围 repl_backlog_histlen:1048576 // 已保存数据的有效⻓度
-
根据统计指标,可算出复制积压缓冲区内的可⽤偏移量范围:
[repl_backlog_first_byte_offset, repl_backlog_first_byte_offset + repl_backlog_histlen]
-
如果当前从节点需要的数据,已经超出了主节点的积压缓冲区的范围,则⽆法进⾏部分复制,只能全量复制了
3.实时复制
- 主从节点在建⽴复制连接后,主节点会把⾃⼰收到的修改操作,通过TCP⻓连接的⽅式,源源不断的传输给从节点,从节点就会根据这些请求来同时修改⾃⾝的数据,从⽽保持和主节点数据的⼀致性
- 这样的⻓连接,需要通过⼼跳包的⽅式来维护连接状态(这⾥的⼼跳是指应⽤层⾃⼰实现的⼼跳,⽽不是TCP⾃带的⼼跳)
- 主从节点彼此都有⼼跳检测机制,各⾃模拟成对⽅的客⼾端进⾏通信
- 主节点默认每隔10秒对从节点发送
ping
命令,判断从节点的存活性和连接状态 - 从节点默认每隔1秒向主节点发送
replconf ack {offset}
命令,给主节点上报⾃⾝当前的复制偏移量
- 如果主节点发现从节点通信延迟超过
repl-timeout
配置的值(默认60秒),则判定从节点下线,断开复制客⼾端连接- 从节点恢复连接后,⼼跳机制继续进⾏
2.总结
- 单点问题:
- 单个Redis节点,可用性不高
- 单个Redis节点,性能有限
- 主从复制的特点:
- Redis通过复制功能实现主节点的多个副本
- 主节点⽤来写,从节点⽤来读,这样做可以降低主节点的访问压⼒
- 复制⽀持多种拓扑结构,可以在适当的场景选择合适的拓扑结构
- 复制分为全量复制,部分复制和实时复制
- 主从节点之间通过⼼跳机制保证主从节点通信正常和数据⼀致性
- 主从复制配置的过程:
- 主节点配置不需要改动
- 从节点在配置⽂件中加⼊
slaveof 主节点ip 主节点端口
的形式即可
- 主从复制的缺点:
- 从机多了,复制数据的延时⾮常明显
- 主机挂了,从机不会升级成主机,只能通过⼈⼯⼲预的⽅式恢复