写点什么

你知道 Redis 是如何保持数据一致性吗

  • 2022-10-17
    广东
  • 本文字数:1332 字

    阅读完需:约 1 分钟

前言

说到 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 尽可能的减少中断的时间。

发布于: 刚刚阅读数: 4
用户头像

还未添加个人签名 2020-06-16 加入

还未添加个人简介

评论

发布
暂无评论
你知道Redis是如何保持数据一致性吗_后端_芥末拌个饭吧_InfoQ写作社区