主从复制的概念
Redis主从复制是将一台Redis服务器的数据复制到另一台Redis服务器,发送数据的是主节点,接收收据的是从节点,数据只能从主节点发送到从节点。
其中涉及到了两个角色,主节点和从节点,默认情况下Redis的节点都是主节点。且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。
主从复制的作用
数据冗余: 主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
故障恢复: 当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复,但实际上是一种服务的冗余。
负载均衡: 在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
高可用基石: 除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。
建立复制
- Redis的解压后的文件夹,复制一份,命名如下:
- 修改Redis-x64-3.2.100-6380的redis.windows.conf,将端口号port修改为6380,如图:
- 打开6379的服务器端。
- 打开6380的服务器端。
- 打开6379的客户端。
- 打开6380的客户端。
- 在客户端查看服务器信息,二者结果如下:
- 将6380的服务器设置为从节点。
创建成功。
在一台电脑上建立主从复制时遇到的坑和自己的解决方法:
(1)修改端口号后运行服务器时的命令要加配置文件名,命令为:redis-server.exe redis.windows.conf,不然打开后服务器端的端口号还是6379,读不到配置文件的6380。
(2)运行客户端时,命令要加端口号:redis-cli.exe -p 6380,不然默认还是6379。
拓扑
一主一从。最简单的拓扑结构,主节点宕机时,从节点提供故障转移支持,可以只在从节点开启AOF,既保证数据安全性也避免了持久化对主节点的性能干扰。但是如果主节点关闭持久化功能,当主节点重启后因为上次未持久化,数据集为空,这时从节点要继续复制主节点会导致从节点数据也被清空。可以通过先断开与主节点的关系,再重启主节点来避免。
一主多从。可以利用多个多个从节点实现读写分离,在主节点上进行写操作,写并发量高的情况下主节点压力较大;在从节点上进行读操作,分担主节点的读压力;
树状。引入中间层,可以从主节点读复制数据,也可以将数据往子节点进行复制。降低主节点的主节点的负载和需要传送给从节点的数量。
复制原理
复制过程
从节点执行salveof命令后,复制开始运作,流程如下:
(1)从节点保存主节点信息
信息包括IP,port,连接状态等。
(2)从节点和主节点建立socket连接
从节点内部通过内部运行的定时任务维护复制相关逻辑,当定时任务发现存在新的主节点后
, 尝试与该节点建立网络连接。
从节点会创建一个socket套接字,专门与主节点连接。
(3)发送ping命令
连接成功后从节点发送ping命令请求首次通信。ping命令的主要目的是:
1. 检测主从之间的网络套接字是否可用;
2. 检测主节点当前是否可接受处理命令。
(4)权限验证
如果主节点设置了requirepass参数,则需要密码验证,从节点必须配置与主节点相同的
密码才能通过验证,验证失败,复制终止,从节点重新发起复制流程。
(5)同步数据集
主从复制连接正常通信后,对于首次建立复制的场景,主节点把持有的数据全部发送给从
节点。
(6)命令持续复制
主节点把当前数据同步给从节点后,便完成了复制建立过程,接下来主节点会持续将写命令
发送给从节点,保证数据一致性。
数据同步
同步过程分为全量复制和部分复制。
全量复制:将主节点的所有数据复制给从节点。数据量较大时对主从节点开销较大,一般用于初次复制场景。
部分复制:用于处理主从复制中因为网络闪断等原因造成的数据丢失场景,当从节点再次连接上主节点后,如果条件允许,主节点会补发数据给从节点,补发数据远远小于全量的数据,可以有效避免全量复制的过高开销。
相关复制命令:2.8之前—>sync 2.8之后------> psync
psync需要主从节点各自复制偏移量,主节点复制积压缓冲区,主节点运行ID的支持。
复制偏移量:参与复制的主从节点都会维护自身的复制偏移量,主节点处理完命令后,将自己的复制偏移量更新(命令的字节长度做累加记录)。从节点每秒钟上报自己的复制偏移量给从节点。通过主从节点的复制偏移量来判断主从节点数据是否一致。
复制积压缓冲区:复制积压缓冲区是保存在主节点的固定长度的队列,默认大小为1MB,当主节点有连接从节点时被建立,主节点响应谢命令时,不但把命令发送给从节点,还会复制给积压缓冲区。
它能实现最近已复制数据的功能,用于部分复制和复制命令丢失的补救。
主节点运行ID:每个Redis节点启动后都会动态分配一个40位的十六进制字符串作为运行ID,用来作为Redis的唯一标识。
psync命令:从节点使用psync命令实现部分复制和全量复制,命令为:psync {runid} {offset},runid为主节点的运行id,offset为当前从节点已复制的数据偏移量。
psync运行过程:
+FULLRESYNC{runid}{offset}表示全量复制,+COUNTINUE表示部分复制,+ERR表示主节点版本低于2.8,无法识别psync命令,从节点将发送旧版的sync命令触发全量复制过程。
全量复制过程
1)发送psync命令进行数据同步,由于是第一次进行复制,从节点没有主节点的运行ID和复制偏移量,所以发送psync -1。
2)主节点根据psync -1 解析出当前为全量复制,回复+FULLRESYNC响应。
3)从节点接受主节点的响应数据,保存运行ID和偏移量offset。
4)主节点执行bgsave保存RDB文件到本地。
5)主节点发送RDB文件给从节点,从节点把接收到的RDB文件保存在本地并直接作为从节点的数据文件,打印相关日志。
6)主节点发送RDB快照给从节点直至发送完成期间,主节点依然响应读写命令,在主节点会把这期间的读写命令数据保存在复制客户端缓冲区内,当从节点加载完RDB文件后,主节点再把缓冲区的数据发给从节点,保证主从数据的一致性。
(7)从节点接受完主节点传送来的全部数据后会自动清空自身旧的数据。
(8)从节点清空数据后开始加载RDB文件,对于较大的RDB文件,这一步比较耗时。
从节点成功加载RDB文件后,如果当前节点开开启了AOF持久化功能,他会立刻做bgrewriteaof操作,为了保证全量复制后AOF持久化文件立刻可用。
部分复制:
1)当主从节点之间网络出现中断时,如果超过repl-timeout时间,主节点会认为从节点故障并中断复制链接。
2)主从链接中断时主节点依然响应命令,但是复制链接中断命令无法发送给从节点,可以将最近一段时间内的写命令数据存在复制积压缓冲区。
3)主从节点网络恢复后,从节点再次连接上主节点。
4)主从节点恢复后,由于从节点之前保存了自身已经复制的偏移量和主节点的运行id。因此会把他们当做psync参数发送给主节点,要求进行部分复制操作。
5)主节点收到psync命令后首先核对参数runid是否与自身一致,如果一致,说明之前复制的是当前主节点,之后根据参数offset在自身复制积压缓冲区查找,如果偏移量之后的数据存在缓冲区中,则对从节点发送+CONTINUE响应,表示可以进行部分复制。
6)主节点根据偏移量把复制积压缓冲区里的数据发送给从节点,保证主从复制进入正常状态。
心跳
主从节点在建立复制后,他们之间维护者长连接并彼此发送心跳命令。
主从节彼此都有心跳检测机制,各自模拟成对方的客户端进行通信,通过client list命令查看复制相关客户端的信息,主节点的连接状态为flags=M,从节点的连接状态为flags=S。
主节点默认每隔10秒对从节点发送ping命令,判断从节点的存货性和连接状态。
从节点在主线程中每隔1秒发送replconf ack {offset}命令,给主节点上上报自身当前的复制偏移量。