敞开生长之旅!这是我参与「日新方案 12 月更文挑战」的第十六天,点击检查活动详情

大家好,我是Zhan,一名个人练习时长一年半的大二后台练习生

这篇文章是复习 Redis 主从仿制同步数据原理 的学习笔记

假如有不对的当地,欢迎各位纠正

与君同舟渡,达岸各自归


导言

Redis的特性便是必须支撑读高并发的,单节点Redis并发才能虽然不错,可是在高并发场景下也顶不住,且单节点假如宕机了,就会导致服务不可用。因而就有了主从这样的架构形式,给master数据同步给它的小弟slave读写分离),这样恳求就能够分发在多个Redis结点上了,一起也方便了水平扩容

Redis 攻略面经(四)-- 详解主从复制中的同步数据

一切的数据修正只发生在主服务器上,然后将最新的数据同步给从服务器上,以确保主从服务器的数据是共同,当然这仅仅咱们从整体上来看,详细是怎么做到主从数据共同性的咱们下面来看看:


全量同步

当咱们进行第一次同步,例如:服务器A和服务器B两个服务器,在服务器B履行:

replicaof <服务器 A 的 IP 地址> <服务器 A 的 Redis 端口号>

那么此刻服务器B便是服务器A从结点了,那么服务器A就需要把数据同步给服务器B,因为是第一次同步,因而是全量同步,也便是把一切的数据都传给服务器B

那么服务器A怎么判别是第一次同步呢?

在履行replicaof指令后,从服务器B就会给主服务器A发送psync指令,标明要进行数据同步,而psync指令有两个参数:

  • Replication Id:数据集的标记,主从结点的数据集共同,也便是说replication id持平
  • offset偏移量,表明仿制的进度,假如从节点的offset落后于主节点的,就代表从节点的数据落后于主节点,需要数据更新,经过主从结点的偏移量的差值也能知道需要更新哪一段数据

关于第一次同步的服务器B来说,并没有主服务器的replication id,且没有进行过仿制,因而发送的指令为:psync ? -1

主服务器会依据从服务器发送的指令来判别下一步的操作,针关于psync ? -1,主服务器会回来FULLRESYNC {replication id} {offset}

  • FULLRESYNC:标明此次同步为全量同步
  • Replication Id:主结点的数据集,这样主节点和从节点的数据集Id就共同了
  • offset:标明此次从节点仿制的数据的偏移量

上述的操作能够用下图来表明:

Redis 攻略面经(四)-- 详解主从复制中的同步数据


在树立完衔接并洽谈好要传输的数据之后,就要开始正式传输数据了:

主服务器会履行bgsave在后台生成RDB快照,然后传输给从节点,从节点拿到数据后,清空当前结点的一切数据,然后导入RDB文件:

Redis 攻略面经(四)-- 详解主从复制中的同步数据


在服务器B导入 RDB 快照期间,客户端对服务器A的写操作,这部分数据服务器B并没有,那么Redis怎么处理这儿的主从不共同呢?

主服务器会把:主服务器生成RDB文件期间主服务器发送RDB文件期间从服务器加载RDB文件期间,三个时刻段的数据更改写入replication buffer缓冲区中

然后在从服务器RDB文件加载完毕后,会发送一个确认的音讯给主服务器,主服务器就会把缓冲区里面一切记载的写操作发送给从服务器,从服务器履行缓冲区中的操作,便主从数据共同了。

Redis 攻略面经(四)-- 详解主从复制中的同步数据


至此,第一次全量同步完毕,完成第一次同步之后,主从结点之间就会树立一个TCP衔接,后续的写操作的指令传达就靠这个长衔接的TCP衔接

Redis 攻略面经(四)-- 详解主从复制中的同步数据


增量同步

在第一次同步之后,主从结点经过TCP衔接来进行通讯写指令,可是因为网络动摇,TCP衔接断开了,重连后,中心的那部分数据会不会丢掉呢?

假如说重连之后,要进行一次全量仿制重新树立TCP衔接,那么这个开销太大了,这就要提到增量同步。咱们在讲psync指令的时分提到了两个个变量offset,在重连的时分,psync指令中的replication id是已知的,因而完好的指令便是:

fsync <replication id> <offset>

然后主服务器发现replication id相同,offset大于从服务器,因而发送给从服务器CONTINUE,标明接下来运用增量同步

offset 和 数据的关系记载在哪呢?

主服务器进行指令传达的时分,不仅会把写指令发送给从服务器,还会把指令写到缓冲区repl_backlog_buffer中,因而这个缓冲区中会保存最近传达的写指令。

很明显,咱们不或许缓冲一切的写指令,毕竟空间有限,也便是说只会缓存一定量的写指令,这是经过环形缓冲区来完成的:

Redis 攻略面经(四)-- 详解主从复制中的同步数据

也便是说,当缓冲区写满后,最旧的数据会被最新的数据所掩盖,那么就存在这个危险:网络康复的时分,从服务器想读的数据现已被掩盖了,此刻主服务器就会不得已选用全量同步,因而咱们最好把缓冲区的大小设置的大一些

综上,全量同步的大概流程便是:

  1. 从服务器发送replication idoffset
  2. 主服务器依据这两个判别是否进行增量同步:
    1. replication id:首先判别是否是同一个数据集
    2. offset
      1. 假如说从服务器想读的数据现已被掩盖了,那就进行全量同步
      2. 假如数据还在,就把offset差值的数据传给从服务器,在此期间replication buffer缓冲区也会记载在此期间主服务器进行的写操作指令,在增量同步完毕之前把replication buffer中的指令发送给从服务器

主-从-从链式结构

在前面的剖析中咱们能够发现,主节点在主从同步的时分所做的比较耗时的两个操作便是:生成RDB快照、传输RDB快照:

  • 生成RDB快照:虽然咱们运用的是bgsave后台生成RDB快照,可是假如数据量比较大,那么虽然是后台履行,也有或许影响到主线程的功率乃至堵塞,导致主线程挂掉
  • 传输RDB快照:传输RDB文件会占用主服务器的网络带宽,会影响主服务器呼应指令恳求

因而咱们能够约束一个master上的slave结点个数,假如实在太多slave,则能够选用主-从-从链式结构,削减master压力:

Redis 攻略面经(四)-- 详解主从复制中的同步数据

也便是说数据同步不一定需要主节点“亲力亲为”,能够选个“副总”帮助去做数据同步


主从数据不共同

主从结点之间的写指令发送是异步的,也便是说:

  • 客户端发送写指令
  • 主服务器履行写指令,并异步把写指令发送给从服务器
  • 主服务器履行完写指令就会把成果回来给客户端
  • 并不会等待从服务器履行完指令再回来成果给客户端
  • 在从服务器还没有履行主服务器发送过来的指令时,去读取就会有主从结点的数据不共同。 也便是说无法完成主从数据时刻保持共同,也便是强共同性,除非进行同步,可是同步会很影响功率。

那咱们怎么去处理这种主从数据不共同的状况呢?

  1. 硬件的角度:确保主从结点间通讯状况,确保网络衔接状况良好
  2. 软件的角度:咱们能够自己弄一个检测程序,来检测主从结点的数据差
    1. 经过Redis的INFO replication拿到主从结点的offset,得到他们的差值
    2. 关于差值大于咱们指定的差值的时分,就让客户端不与这个结点通讯

主从切换的数据丢掉

异步仿制同步丢掉

在前文中咱们提到,Redis主从结点之间的数据仿制,是异步仿制的,也便是说或许存在:

  • 主服务器存在很多写指令没有传给从服务器,数据同步需要比较久的时刻
  • 然后客户端发送写指令
  • 主服务器履行完写指令
  • 回来成果给客户端
  • 可是主服务器回来给客户端成果后和同步数据前,发生了Redis宕机,那么数据就会丢掉

那咱们怎么尽或许的去削减数据丢掉呢?

Redis配置中有个参数min-slaves-max-lag,Redis会依据当前数据同步的速度,判别出同步完成需要的时刻,假如时刻超过了min-slaves-max-lag,便不再承受客户端的恳求,这样即便丢数据,也只会丢这10s内的数据

那么总不能为了宕机这种特殊状况,一直不处理恳求,此刻咱们能够把数据线丢进本地缓存或许磁盘或许音讯队列,这样等待Redis康复正常,再去读取这些音讯即可。


集群脑裂

假如主节点的网络失联,与一切的从节点都失联了,可是客户端并不知情,数据仍是在往这个结点传,这些数据都写在了主节点的缓冲区中,此刻,岗兵发现了主节点失联了,于是选出了另外一个主节点,此刻就出现了所谓的:集群脑裂——此刻集群有两个主节点

然后原主节点的网络好了,可是因为岗兵机制,现在原主节点降级为从节点,会与现主节点做一次全量同步,这样在主节点网络失联期间的数据就丢掉了

那咱们怎么去削减集群脑裂丢掉的数据呢?

在Redis的配置文件中有两个参数帮助咱们处理问题:

  • min-slaves-to-write:主节点至少有x个从节点,不然主结点制止写数据
  • min-slaves-max-lag:主从仿制的延迟不能超过x秒,不然主节点制止写数据

主节点衔接的从节点中至少有 x 个从节点,并且主节点进行数据仿制时的 ACK 音讯延迟不能超过 x 秒,原主节点就会被约束接收客户端写恳求,客户端也就不能在原主节点中写入新数据了


总结

本文讲了Redis主从仿制进行数据同步的原理、数据不共同或许丢掉的状况以及处理办法

  • 关于主从仿制的同步数据,咱们别离介绍了:
    • 第一次同步时进行的全量仿制
    • 第一次同步完毕后指令传达的方式
    • 增量仿制的运用状况以及运用流程
  • 关于数据的丢掉和不共同,咱们别离介绍了:
    • 主从数据因为异步仿制导致无法确保强共同性
    • 怎么削减主从数据不共同带来的影响
    • 异步仿制同步丢掉集群脑裂 带来的数据丢掉问题 信任读完今日的文章,大家能对Redis集群的底层原理有了更深一步的了解~

友链

  • Redis 攻略面经(一)– 常见数据类型
  • Redis 攻略面经(二)– 关于持久化,你了解多少?
  • Redis 攻略面经(三)– 详解内存回收的两种策略

✒写在最后

都看到这儿啦~,给个点赞再走呗~,也欢迎各位大佬纠正以及补充,在评论区一起沟通,共同进步!也欢迎加微信一起沟通:Goldfish7710。咱们明天见~

Redis 攻略面经(四)-- 详解主从复制中的同步数据