Redis主从数据同步原理及优化

Redis作为我们常用的缓存,虽然Redis的速度很快,但是单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离。如下:

从上图我们可以看到,主节点(master)主要负责写操作的请求,从节点(slave/replica)主要负责读操作的请求。但是,既然没往从节点写数据,主从节点之间的数据又是如何同步的呢?

主从结点数据同步主要分为两种:①全量同步 ②增量同步。

在了解什么是全量同步和增量同步前,我们需要来看一下主从数据同步时的流程:

(主从数据同步的过程依赖RDB完成,因此如果对这个知识点不了解的朋友可以去看看我主页关于Redis持久化的文章:点我传送!!!

第一阶段

① 二者建立连接准备传输数据;

②slave节点请求数据同步;

③master判断slave节点是否与自己是第一次建立连接(通过对比slave节点存储的replid是否与自己一致来判断是否第一次建立连接,如果一致则不是第一次,不一致则是第一次)。如果是第一次则将自己的数据版本信息(replid)发给slave节点,然后进入第二阶段。不是第一次则进入第三阶段。

第二阶段:(全量同步

①执行bgsave,生成RDB文件。

②发送RDB文件给从节点,从节点通过读取RDB文件得到所有数据(由于这个过程比较耗时,所以如果此时还有写操作不断更改主节点数据的时候,会导致数据不一致。因此如果还有写操作不断请求,就将这些写操作记录在repl_baklog日志中,并在第三阶段将这个日志记录的发给slave节点,保证主从节点数据的一致性)。

第三阶段:(增量同步

①发送repl_baklog日志中记录的命令,然后slave节点执行这些命令,实现数据同步。

  1. 全量同步

什么是全量同步,就是主节点将全部数据都同步给从节点。

如上文我们所说:主从第一次建立连接时,会执行全量同步,将master节点的所有数据都拷贝给slave节点。

那么,master如何得知salve是第一次来连接呢?

我们需要先来了解两个东西:

  • Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid

  • offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。(这个我们后文会有介绍)

上文我们可以看到,在第一阶段slave节点会向master节点发送数据同步请求,这个时候slave节点会将自己的唯一Replid(数据版本信息)和offset(偏移量)发送给master节点,因此master节点只需要对比自己的Replid是否与slave发送过来的Replid一致就知道是否是第一次连接了,不是则执行全量同步。

因此全量同步的流程图可以变为下图:

  1. 增量同步

什么是增量同步?就是只更新slave与master存在差异的部分数据。

全量同步需要先做RDB,然后将RDB文件通过网络传输个slave,成本太高了。因此除了第一次做全量同步,其它大多数时候slave与master都是做增量同步

那么master怎么知道slave与自己的数据差异在哪里呢?这里就需要说下我们流程图中提到的repl_baklog日志了。

首先我们先来介绍一下repl_baklog日志的原理:

repl_baklog日志文件是一个固定大小的环形数组,也就是说角标到达数组末尾后,会再次从0开始读写,这样数组头部的数据就会被覆盖。repl_baklog的数据结构图如下:

大家看到这个slave和master肯定又很疑惑了,这里代表什么意思呢?这里就又要提到我们刚刚说的offset(偏移量了)。这里的slave和master是指slave节点和master节点的offset所处位置。大家可以将offset理解成指向repl_baklog数组的指针,比如上文slave节点的offset和master节点的offset差距为红色部分,意思是二者之间数据还差这么多,因此要不断将二者之间的repl_baklog记录的的命令发给slave节点,来完成数据同步。

简而言之,slave与master的offset之间的差异,就是salve需要增量拷贝的数据了。

增量同步的流程图如下:

这里会出现一种极端情况:当slave节点宕机的时候,slave的offset还在原地,但是master的offset不断前移:

二者之间的差距越来越大:

直到master的offset超过slave节点的offset(可以理解成已经套圈了):

由于上述我们提到repl_baklog日志文件是一个固定大小的环形数组,也就是说角标到达数组末尾后,会再次从0开始读写,这样数组头部的数据就会被覆盖。由于数据被覆盖,但是由于被覆盖的这部分数据还没被同步,因此会导致这一部分的数据丢失。

上述情况已经无法通过增量同步来完成主从节点之间的数据同步了,因此只能进行全量同步来进行数据同步了。但是由于全量同步的效率实在低,因此我们就需要对这种情况进行优化。

  1. 主从节点数据同步优化

主从同步可以保证主从数据的一致性,非常重要。因此我们要知道如何对这一过程进行有效的优化。

可以从以下几个方面来优化Redis主从就集群:

  • 在master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO。(全量同步慢很大原因就是因为过程中大部分主要是通过RDB完成的,而RDB要操作磁盘,因此效率较低,所以无磁盘复制,通过网络来传输数据的效率会高很多,但是对网络要求高,如果断网之类的则会失效)。

  • Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO(内存越多,说明需要同步的数据就越多,因此RDB的过程越慢)。

  • 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步。(这里解决我们上述说的那个情况,减少了全量同步的可能性,提高了效率)

上述①、②两点都是针对全量同步的优化,③是针对解决我们上文提到的一种情况,导致增量同步无法完成数据同步而执行效率较低的全量同步。

  1. Redis数据同步常见面试题

简述全量同步和增量同步区别?

  • 全量同步:master将完整内存数据生成RDB,发送RDB到slave。后续命令则记录在repl_baklog,逐个发送给slave。

  • 增量同步:slave提交自己的offset到master,master获取repl_baklog中从offset之后的命令给slave。

什么时候执行全量同步?

  • slave节点第一次连接master节点时。

  • slave节点断开时间太久,repl_baklog中的offset已经被覆盖时。

什么时候执行增量同步?

  • slave节点断开又恢复,并且在repl_baklog中能找到offset时

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值