面试官:Redis主从复制时网络开小差了怎么整?

上周因为实在太忙就认认真真写了一篇水文 , 吹了一下自己过去的经历 , 反响竟然超出了我的预期 , 并且后台还有读者留言表示想看续集的 。 哈哈 , 果然大家还是对水文更有热情 。
这期我们继续回到之前的 Redis 话题 。 今天主要讲的是主从复制数据一致性相关以及面对网络中断如何进行数据同步的问题 。
不 BB 了 , 直接上钟吧!
面试官:Redis主从复制时网络开小差了怎么整?文章插图
图注:思维导图
主从模式配置对于 Redis 主从大家可能并不陌生 , 但是配置的话日常工作中并不会经常操作 。 在这里简单介绍下主从的相关配置 。
1、主从模式
面试官:Redis主从复制时网络开小差了怎么整?文章插图
【面试官:Redis主从复制时网络开小差了怎么整?】Redis 中设置主从的方式很简单 , 通常有两种:

  • 通过在配置文件 redis.conf 中设置 slaveof 方式(永久);
  • 直接在客户端执行 slaveof ip port 的方式(临时);
2、主-从-从模式
面试官:Redis主从复制时网络开小差了怎么整?文章插图
对于主-从-从的模式来说 , 配置也与上边的操作类似 , 在这里就不多赘述了 。
主从一致性原理了解了主从配置后 , 下面就要进入正题了 。
在主从中 , 通常的操作是主库用来写入数据 , 从库用来读取数据 。 这样的好处是避免了所有的请求压力都打在了主库上 , 同时系统的伸缩性也得到了很大的提升 。
但是问题就来了 , 读从库时的数据要与主库保持一致 , 那就需要主库的数据在写入后同步到从库中 。 如何保持主库与从库的数据一致性 , 当有多个从库时 , 又如何做到呢?
1、全量复制这是第一次同步时所发生的传递关系 。 看名字就知道 , 主库第一次就毫无保留的把所有数据都传递给了从库 。
我们先来看下它们是如何发生第一次关系的(就知道你会想歪) 。
面试官:Redis主从复制时网络开小差了怎么整?文章插图
图中的同步流程已经很清晰了 , 总共分为三部分:
(1)主从节点建立联系当从节点与主节点第一次建立联系时 , 从节点会向主节点发送 psync 命令 , 表示要进行数据同步 。
正如你看到的 psync 命令后会带有两个参数:一个是 runID , 一个是偏移量 offset 。
  • runID:每个Redis实例生成的随机且唯一的ID , 在这里表示的是主节点的ID 。
  • offset:复制偏移量 。
在图中第一次复制时因为不知道主库ID和偏移量 , 因此用“?”和“-1”分别来表示runID 和 offset 。
当主节点接收到 psync 命令后 , 会使用 FULLSYNC命令向从节点发送 runID 及offset 两个参数 。 从节点将其信息保存下来 。
到这里关系算是建立了下来 。
(2)主节点同步RDB文件RDB文件 , 这是一个老面孔了 , 持久化时会用到的二进制文件 。 在这里起着主从数据同步的作用 , 也就是说主从同步是依赖 RDB 文件来实现的 。
从节点接收到 RDB 文件后 , 在本地完成数据加载 , 算是完成了主从同步 。
到这里你有没有发现什么问题?
我们回想下 RDB 文件是如何生成的 。 在持久化那篇文章里 , 我们介绍过 , 父进程 fork 了一个子进程来进行生成 RDB 文件 。 父进程并不阻塞接收处理客户端的命令 。
面试官:Redis主从复制时网络开小差了怎么整?文章插图
那么问题就产生了 , 当主节点把 RDB 文件发送给从节点时 , 主节点同时接收的命令又该如何来处理?
(3)主节点同步缓冲区命令这一步就是来解决 RDB 文件生成后 , 父进程又接收到写命令同步的问题的 。
为了保证主从节点数据的一致性 , 主节点中会使用缓冲区来记录 RDB 文件生成后接收到的写操作命令 。 在 RDB 文件发送完成后会把缓冲区的命令发送给从节点来执行 。
到这里 , 主从节点的数据同步算是完成了 。
2、级联操作我们再来回顾下整个同步流程 , 从建立关系 , 生成 RDB 文件 , 传输给从节点到最后缓冲区命令发送给从节点 。 这是一个从节点与主节点同步的完整流程 。
那么我们再来思考:当有多个从节点 , 也就是一主多从时 , 第一次连接时都要进行全量复制 。 但是在生成 RDB 文件时 , 父进程 fork 子进程时可能会出现阻塞 , 同时在传输 RDB 文件时也会占用带宽 , 浪费资源 。
这种情况我们该如何来解决呢?
不知道你对文章开头的 主-从-从模式是否还有印象 。 通过对从节点再建立从节点 。 同步数据时从级联的从节点上进行同步 , 从而就减轻了主节点的压力 。