Redis是如何保证数据一致性的

举报
芥末拌个饭吧 发表于 2022/11/11 17:28:50 2022/11/11
【摘要】 说到Redis的高可靠性,我们很容易想到AOF或者RDB快照,它们通过日志文件的方式恢复数据。但是宕机期间,我们的服务就会受到影响。 巴菲特曾说过:不要把鸡蛋都放在一个篮子里。这句话的含义就是要将风险分散开来,在Redis的高可靠性保证来说也是一样。我们不能只把数据都放在一台服务器上,需要将数据复制在多台实例上,这样就能在一台服务器故障时,依然有其他的服务器工作。

前言

说到Redis的高可靠性,我们很容易想到AOF或者RDB快照,它们通过日志文件的方式恢复数据。但是宕机期间,我们的服务就会受到影响。

巴菲特曾说过:不要把鸡蛋都放在一个篮子里。这句话的含义就是要将风险分散开来,在Redis的高可靠性保证来说也是一样。我们不能只把数据都放在一台服务器上,需要将数据复制在多台实例上,这样就能在一台服务器故障时,依然有其他的服务器工作,这就是今天要将的Redis主从同步。

主从库模式的工作方式

主从库之间是采用读写分离的方式:

  • 读操作:主从库都可以接收;
  • 写操作:只有主库能执行,主库写完后再同步给从库。

为何写操作只能在主库执行呢?这是因为如果写操作可以在任一库中执行,同一份数据多次更新后就会产生数据不一致的问题了。接下来说说主从同步的模式。

主从同步有3种工作模式,分别是:

  • 全量复制:第一次同步时执行
  • 基于长连接的命令传播:主从库正常运行的时候执行
  • 增量复制:遇到网络故障时执行。

主从第一次同步

这个过程主要有2部分数据要同步,分别是:

  • 当前时刻所有的日志数据;
  • 同步阶段新产生的数据。

对于这2部分数据,Redis是用下面3个阶段去完成数据同步的:

  1. 第一阶段:主从库之间建立连接,从库向主从发出pysync命令,命令包含了主库的运行ID(runID)和复制进度偏移量(offset)参数。
  2. 第二阶段:主库将此时的所有数据同步到从库,从库收到后,在实例上将数据复制加载。在这个过程中,主库不会被阻塞。同时,这个过程中如果有新的数据产生,主库会在内存用一个叫做replication buffer的结构记录RDB文件生成后收到的写操作。
  3. 第三阶段:此阶段就是将主库replication buffer新收到的写命令发给从库,从库再去同步这些数据。

对于这个同步过程,主库有2个很耗时的动作:生成RDB文件、传输RDB文件。如果从库很多,全部由主库将全量数据同步到从库,就会导致主库一直在fork子进程的动作中,而fork动作会阻塞主线程处理正常的请求。

此时我们可以采用”主-从-从“的同步模式,就是选择一个从库作为联接主库和其他从库的对象,避免主库忙于处理fork子进程。选择从库的命令就是:

replicaof 从库IP 端口

这个"主-从-从"模式的示意图如下:

当主从库完成了全量复制时,这个主从集群就会有一个长连接去做同步数据的工作,这样可以避免频繁地建立连接产生开销。

增量复制的过程

当网络故障后,主从库就会采用增量复制的方式继续同步数据。

主要过程就是当主从库断开连接后,主库会将这个断连过程中的写操作命令,都写入到一个环形扇区replication buffer,同时也会将命令写到repl_backlog_buffer缓冲区。repl_backlog_buffer这个缓冲区就记录着主库写到的位置,而从库会记录自己读到的位置。

正常情况下,从库在缓冲区的读位置和主库的写位置的偏移量基本相等。主从库连接恢复后, 主库只用把 master_repl_offset 和 slave_repl_offset 之间的命令操作同步给从库就行。

在网络断开期间,若主库的 repl_backlog_size环形缓冲区写满之后,会覆盖数据。连接恢复后,从库通过psync命令将自己记录的slave_repl_offset发给主库。若主库查询不到就进行全量复制,查得到就增量复制。

小结

主从同步过程,主要是增量复制这块较难理解,大家可以参考官方文档多了解一下具体实现。总的来说,主从同步保证了我们实例故障时,Redis尽可能的减少中断的时间。


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。