Redis-主从复制-psync运行流程

发布于:2025-07-08 ⋅ 阅读:(25) ⋅ 点赞:(0)

目录

1.psync 数据同步

replication 复制:

offset偏移量:

2.psync运行流程:

运行流程:

3.全量复制

流程如下:

无磁盘复制 diskless:

4.部分复制:

进行行全量复制的情况:

进行部分复制的情况:

5.replicationId和runid的区别:

总结:


1.psync 数据同步

通过psync命令来实现主从同步数据,是从节点给主节点发的命令,这个命令不需要手动执行,当建立好主从连接关系后,redis会自动执行这个命令.

psync语法格式: psync replication offset

replication 复制:

缩写:replid :是主节点的id.

从节点的master-replid 记录是从哪个主节点同步的.即主节点的id.

可以看到,这里有两个replid,第二个是全为0,当主节点和从节点的数据传输过程中出现网络抖动,或主节点挂了,与从节点连接的主节点目前不存在,当从节点就晋升为新的主节点时,会生成新的id,保存在replid中;这时replid2就会保存原来的主节点的id,之后当主节点又恢复了,可以再通过replid2再与主节点连接起来.

offset偏移量:

主节点和从节点都会维护一个偏移量,用来记录当前从节点同步主节点数据的进度.

主节点上每收到一个操作数据的命令(读数据除外),每个命令都会占据几个字节的空间,主节点会把这些命令的字节数累加(一个整型数字);当从节点同步时,也会记录类加偏移量.

当从节点的偏移量和主节点相同时,就表示这个从节点中的数据和主节点的数据完全一致了.

当两个从节点的replication和offset完全一致是,说明这两个从节点中的内容是完全相同的.(从同一个主节点复制,同步进度相同).

2.psync运行流程:

psync命令是从节点向主节点发送的命令,用来让主节点同步数据到从节点。

同步数据的方式有全量复制,部分复制和实时复制;主节点要根据psync命令的参数判断是哪种复制。

psync语法格式: psync replication offse

当replication为? ,且 offset = -1时,则尝试进行全量复制;

offset为一个确定的正整数时,是从指定的偏移量进行复制,即部分复制.但实际是哪种复制,还要看主节点是否方便部分复制,若无法部分复制,即使offset指定了具体的值,还是会进行全量复制.

运行流程:

1>.从节点给主节点发送psync命令,

2>.主节点根据psync参数和自身数据情况决定响应结果,主节点返回的命令有一下几种:

-FULLRESYNC:从节点进行全量复制流程

-CONTINUE:从节点进行部分复制流程

-ERR:说明redis版本过低,不支持psync命令。可以使用sync命令进行全量复制。(sync命令会阻塞redis server处理其他请求,psync不会 )

3.全量复制

全量复制在redis主从节点第一次进行数据同步的时候进行,即从节点刚和主节点建立连接的时候。

流程如下:

1.从 主动发送psync命令给 主 进行数据同步,由于是第一次复制,从 没有 主 的replid和复制偏移量,所以发送psync ? -1.

2.主根据命令,解析出要进行全量复制,回复 -FULLRESYNC响应

3.从 收到主 的运行id等信息,并进行保存·。

4.主 开始执行bgsave,进行RDB文件的持久化。

5.主 发送RDB文件给 从,从 先保存RDB文件到本地硬盘中。

6.主节点在生成rdb文件和将rdb文件传输给从节点的过程中,可能又会有对数据的操作命令:

于是: 主 将 从开始执行bgsave命令到发送给从节点之间又产生的 写命令,写入一个缓冲区中,等 从保存完rdb文件,主 再将缓冲区中的数据补发给 从节点,补发的数据仍以rdb的二进制格式追加到写入的rdb文件中,补发是为了保持 主从一致性。

7.从节点清空自身原有的旧数据,

8.从节点加载rdb文件和主节点保持数据一致。

9.若从节点开启了aof持久化功能,在加载完rdb文件后会执行bgrewrite操作(由于目前得到的是所有的数据,数据存在一定的冗余,此操作会进行数据的整理,瘦身),得到最新的aof文件。

在第四部,主节点生成rdb文件,有两个可讨论的小问题:

1>.为啥用rdb文件存储,而不是aof文件?

使用rbd文件,而不是aof文件,是因为rdb文件是以二进制的形式存储的,aof是以文本格式存储的,主节点通过网络传输向从节点传输大量数据时,rdb文件节省空间.

2>.若主节点的持久化方式就是以rdb文件形式存储,能否将已有的rdb文件直接传输给从节点,不再重新进行rdb文件持久化?

不能, 因为主从同步,要求的不是尽量保持一致,而是要求100%的一致,此时可能主节点已经有新的数据操作,但还未被rdb持久化,若直接将已有的rdb文件传输过去,更不能保证主从节点数据的一致性了,因此主节点必须要重新生成rdb文件.

全量复制是一件成本较高的操作,应尽可能避免对大量数据集的redis执行全量复制。

无磁盘复制 diskless

但在一些情况下,不得不执行全量复制,可以通过采用“无磁盘复制”的方法来降低开销:

默认情况下,进行全量复制主节点要将生成的rdb文件存储到磁盘上,然后再将磁盘上的rdb文件发送给从节点。

redis的2.8.18版本支持无磁盘复制,即主节点在执行bgsave命令,生成rdb文件后,不会将生成的rdb文件存储到磁盘,而是直接通过网络传输将rdb文件发送给从节点从节点接收到的rdb也可以不写入磁盘,直接加载.也会节省文件存储到磁盘带来的开销. 这样就节省了一系列的写硬盘和都硬盘的操作开销。

注意: 尽管引入了“无盘复制”,但全量复制的成本还是很高了,仅是得到了较小的优化,对网络传输等操作是无法缓解的,还是要尽量避免全量复制。

4.部分复制:

部分复制也是在主从节点建立连接后,进行第一次复制的操作。

部分复制是全量复制的一种优化机制,复制流程和全量复制流程一样,只是发生部分复制和全量复制的情况不同。

进行行全量复制的情况:

1.主从节点第一次建立连接,第一次同步数据。

2.主节点不方便进行部分复制。

进行部分复制的情况:

1.从节点已经复制过主节点的数据,因为网络抖动,或从节点重启了;

2.当主从节点因为一些情况断开来连接,后又连接上,从节点只需要同步部分主节点的数据(主从节点的大部分数据已经是一致的)。

部分复制过程:

1>.当主从节点出现网络问题中断时,如果超过 repl-timeout 时间,主节点会认为 从节点故障并 中断 复制连接。

2>.主从节点断开连接后,主节点还会接收响应命令. 由于主从节点断开了,从节点无法再同步主节点的数据了;  主节点在和从节点断开后,将收到的响应暂时 存放在一个积压缓冲区中.

3>.当主节点网络恢复后,从节点会再次连接上主节点.

4>.从节点将之前保存的replicationId和offset信息,通过发送psync命令给主节点,进行部分数据同步.

5>.主节点收到psync命令后,通过验证后,根据offset去复制积压缓冲区中的合适数据,并响应-CONTINUE给从节点

6>.主节点将从节点需要的数据同步给从节点,完成主从一致性.

细节:

1. 积压缓冲区:

就是一个内存中一个简单的队列,会记录最近一段时间数据的修改,但由于空间有限,随着时间的推移,会把之前旧的数据删除.

2.当主节点网咯恢复后,收到从节点的psync命令后,要进行验证,验证的内容:

1>.判断从节点传过来的replicationId是否是自己的.若不是自己的Id,说明该从节点未和主节点有过连接,需要进行全量复制. 若是,说明是网络中断之前连接过的从节点;

2.确认是之前断开的从节点后,再判断offset,看数据复制的进度是否在积压缓冲区的范围内,若太多数据需要同步,已经超出积压缓冲区的范围,就需要进行全量复制;  若在积压缓冲区的范围内,就再积压缓冲区中找到确定的位置,进行部分复制即可.

5.实时复制

在主节点和从节点已经建立连接并同步过全量数据后,主节点就会把后续的数据的修改,通过tcp长连接,实时复制给从节点,从而保证主从节点的一致性.

这里的长连接需要通过"心跳包"来进行维护:

1>.主从节点都有心跳检测,各⾃模拟成对⽅的客⼾端进⾏通信,

2>.主节点默认每隔 10 秒对从节点发送 ping 命令,判断从节点的存活性和连接状态。

3>.从节点默认每隔 1 秒向主节点发送 replconf ack {offset} 命令,给主节点上报⾃⾝当前的复制偏移量.

如果主节点发现从节点通信延迟超过 repl-timeout 配置的值(默认 60 秒),则判定从节点下线,断开复制客⼾端连接。从节点恢复连接后,⼼跳机制继续进⾏

注意: 这里的时间都是可以进行自己设定的.(无需记忆)

6.replicationId和runid的区别:

replicationId和runId在一个redis服务器上都存在,来观察一下这两个的区别:

主节点的replicationId:

主节点的runId:通过info server命令获取:

查看从节点6380的replicationId:

6380的runId:

6381的replicationId:

6381的runId:

可以看到三个节点的replicationId都是相同的,而runId都是不同的.

总结:

replicationId是用来确认连接的主节点的标识符.在主从复制中起作用;

runId是标识一次redis的运行,redis每重启一次,都会生成一个新的runId.是用来实现redis哨兵功能的.runId和主从复制没有关系.

这两个符号的长度相同,格式相似,但他俩没啥关系.

7.主从复制的缺陷:

1.若主从节点采用的树形结构,数据同步会存在延迟性,

2.一旦主节点挂了.从节点就不知道要怎么办了,这时就需要通过人工干预的方式恢复.但人工处理往往是具有非常的大的延迟性和存在出错的可能,即需要再采取措施来处理这样的问题,就是通过哨兵机制来解决.

 下一篇文章讲的就是redis的哨兵机制.