Redis主从一致性(2.8版本前后的差别)

背景

在Redis中,用户可以执行slaveof指令,或者修改SLAVEOF设置,使得一个服务器B成为另一个服务器A的slave。那么服务器A叫做主服务器,服务器B叫做从服务器。在实际的工程中,主服务器一般只接受客户端的写请求,而从服务器接受客户端的读请求,另外一般持久化也是由其中一个从服务器来执行的,这样可以实现高可用。

但主从关系也产生了一个问题,如何保证主从一致性?也就是如何确保主从的数据是相同的?

这在Redis2.8之前和之后有着不一样的实现,主要体现在sync和psync

Redis2.8之前

在这段时间里,Redis的同步功能分为全量同步和增量同步

全量同步

全量同步发生在初次同步断线重连同步这两个阶段

初次同步

当从服务器第一次连上主服务器,此时要进行一次初步的同步操作,具体流程如下:

  • 1.从服务器向主服务器发送sync指令
  • 2.主服务器收到指令,执行BGSAVE指令,也就是RDB,在后台生成一个rdb文件,并适用一个缓冲区开始记录写命令
  • 3.主服务器生成rdb文件后,将该文件发给从服务器,从服务器将这个二进制文件加载到内存中
  • 4.主服务器将缓冲区中的写操作发送给从服务器,从服务器逐个执行,此时就完成了一次全量同步

断线重连同步

当从服务器挂掉了,重新连接上来的时候,主从之间数据已经不一致了,那么此时还要进行一次同步。在Redis2.8之前,会采用一次全量同步。而在Redis2.8之后,就会灵活选择策略,这个在后面说

增量同步

在执行完初次同步之后,就完事了吗?当然不是,主服务器是不断处理写请求的,数据不断更新,此时也需要有实时同步策略才能保证主从一致

增量同步其实很简单,主服务器将每一条写命令都发送给从服务器去执行,就能保证动态保证主从一致了

Redis2.8之前同步策略的缺点

这个缺点主要是表现在断线重连之后,直接进行全量同步的这个策略。

考虑这样一个场景,从数据库虽然挂掉了,但是很快就重连上来了,此时它丢失的写操作只有很少,比如说只有几条,那这时直接进行一次全量同步sync很明显是不划算的操作

并且sync是一个重量级操作:

  • 生成rdb文件需要进行磁盘IO,如果数据量很大的话速度很慢
  • 由父进程fork出一个子进程进行的,消耗CPU资源
  • 生成rdb文件实际上是Copy-On-Write方法进行的,内存会暴涨原来的两倍

所以Redis2.8之后主要就是针对该点进行了优化,用psync替代了sync

Redis2.8之后

Redis2.8之后,主要是对断线重连之后的同步策略进行了优化。在断线重连之后,可以自动按照实际情况选择是进行全量同步还是增量同步的价值更高

这个策略的实现由三个部分组成

  • 复制偏移量
  • 复制积压缓存区
  • 运行ID

复制偏移量

主从服务器都会各自维护一个复制偏移量,当主服务器向从服务器传播N个字节时,自己的复制偏移量加上N;从服务器接受到主服务器传来的N个字节时,自己的复制偏移量也会加上N。所以如果主从的复制偏移量相同,则说明主从一致。

那么根据复制偏移量的差异就可以得知主从服务器之间从哪到哪的数据是没有同步的,根据这个数量可以选择具体要实现哪个策略来进行重同步。要作出选择,还需要基于另一个东西,也就是复制积压缓存区

复制积压缓存区

复制积压缓存区其实是一个先进先出(FIFO)队列,但是和传统的先进先出队列不一样,里面的元素不能被主动取出,只有当队列已满,并且再添加新元素时,队列头的元素才会被挤出来。所以该队列的长度是固定的。

当主服务器执行写命令时,它不仅会传播给从服务器,还会将该命令+复制偏移量加入队列中,如图:

img

而当从服务器断线重连后,如果它的复制偏移量对应的操作还存在于主服务器的队列中,说明断线没多久,此时进行增量同步操作

如果复制偏移量的值已经不在队列中了,说明已经被挤出去了,此时进行全量同步

那设置复制积压偏移量这个队列的大小就很关键了,它能间接决定断线重连后同步的效率。这个队列的最小值一般可以设定为 second*write_size_per_second second为从服务器的平均断线时间,write_size_per_second为主服务器平均每秒执行的写操作数量

服务器运行ID

除了复制偏移量和复制积压缓存区之外,实现部分重同步还需要一个运行ID

主从服务器都有一个自己的运行ID,由40个随机的十六进制字符组成。

当从服务器第一次连接上主服务器时,主服务器会将自己的运行ID发给从服务器,从服务器会保存这个运行ID

当从服务器断线重连后,首先会向主服务器发送自己记录的主服务器运行ID

  • 若发送的运行ID与主服务器的运行ID相同,说明从服务器之前连的就是该主服务器,此时可以根据策略选择进行全量同步还是增量同步
  • 若不同,说明从服务器连接上了新的主人,此时直接进行全量同步

参考:

https://www.cnblogs.com/lukexwang/p/4711977.html

发布了60 篇原创文章 · 获赞 7 · 访问量 3877

猜你喜欢

转载自blog.csdn.net/SCUTJAY/article/details/104481580