上周因为实在太忙就认认真真写了一篇水文,吹了一下自己过去的经历,反响竟然超出了我的预期,并且后台还有读者留言表示想看续集的。哈哈,果然大家还是对水文更有热情。

这期我们继续回到之前的 Redis 话题。今天主要讲的是主从复制数据一致性相关以及面对网络中断如何进行数据同步的问题。
不 BB 了,直接上钟吧!

图注:思维导图

主从模式配置

对于 Redis 主从大家可能并不陌生,但是配置的话日常工作中并不会经常操作。在这里简单介绍下主从的相关配置。

1、主从模式

Redis 中设置主从的方式很简单,通常有两种:

  • 通过在配置文件 redis.conf 中设置 slaveof 方式(永久);

  • 直接在客户端执行 slaveof ip port 的方式(临时);

2、主-从-从模式

对于主-从-从的模式来说,配置也与上边的操作类似,在这里就不多赘述了。

主从一致性原理

了解了主从配置后,下面就要进入正题了。

在主从中,通常的操作是主库用来写入数据,从库用来读取数据。这样的好处是避免了所有的请求压力都打在了主库上,同时系统的伸缩性也得到了很大的提升。

但是问题就来了,读从库时的数据要与主库保持一致,那就需要主库的数据在写入后同步到从库中。如何保持主库与从库的数据一致性,当有多个从库时,又如何做到呢?

1、全量复制

这是第一次同步时所发生的传递关系。看名字就知道,主库第一次就毫无保留的把所有数据都传递给了从库。

我们先来看下它们是如何发生第一次关系的(就知道你会想歪)。

图中的同步流程已经很清晰了,总共分为三部分:

(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 文件。父进程并不阻塞接收处理客户端的命令。

那么问题就产生了,当主节点把 RDB 文件发送给从节点时,主节点同时接收的命令又该如何来处理?

(3)主节点同步缓冲区命令

这一步就是来解决 RDB 文件生成后,父进程又接收到写命令同步的问题的。

为了保证主从节点数据的一致性,主节点中会使用缓冲区来记录 RDB 文件生成后接收到的写操作命令。在 RDB 文件发送完成后会把缓冲区的命令发送给从节点来执行。

到这里,主从节点的数据同步算是完成了。

2、级联操作

我们再来回顾下整个同步流程,从建立关系,生成 RDB 文件,传输给从节点到最后缓冲区命令发送给从节点。这是一个从节点与主节点同步的完整流程。

那么我们再来思考:当有多个从节点,也就是一主多从时,第一次连接时都要进行全量复制。但是在生成 RDB 文件时,父进程 fork 子进程时可能会出现阻塞,同时在传输 RDB 文件时也会占用带宽,浪费资源。

这种情况我们该如何来解决呢?

不知道你对文章开头的 主-从-从模式是否还有印象。通过对从节点再建立从节点。同步数据时从级联的从节点上进行同步,从而就减轻了主节点的压力。

网络开小差了

上面的流程我们已经知道了正常情况下主从节点的复制过程了,但是当网络中断导致主从连接失败等异常情况下,主从同步又是如何来进行的?

在这里要提到一个增量复制的名词,与全量复制不同的是,它是根据主从节点的偏移量来进行数据同步的。

什么意思呢?

还记得在全量复制里我们所提到过的缓冲区吗?就是用来存储生成 RDB 文件后的写命令的,这里我们称为缓冲区A。主从节点断开连接后,除了会将后续接收到的写命令写入缓冲区A的同时,还会写入到另一个缓冲区B里。

在缓冲区B里,主从节点分别会维护一个偏移量 offset。刚开始时,主节点的写位置与从节点的读位置在同一起点,随着主节点的不断写入,偏移量也会逐渐增大。同样地,从节点复制完后偏移量也在不断增加。

当网络断开连接时,从节点不再进行同步,此时主节点由于不断接收新的写操作的偏移量会大于从节点的偏移量。当连接恢复时,从节点向主节点发送带有偏移量的psync 命令,主节点根据偏移量来进行比较,只需将未同步写命令同步给从节点即可。

总结

主从一致性原理

  • 从节点第一次进行连接时,主节点会生成 RDB 文件进行全量复制,同时将新写入的命令存储进缓冲区,发送给从节点,从而保证数据一致性;

  • 为了减少数据同步给主节点带来的压力,可以通过从节点级联的方式进行同步。

网络开小差了

  • 网络断连重新连接后,主从节点通过分别维护的偏移量来同步写命令。

关于作者

作者:大家好,我是莱乌,BAT搬砖工一枚。从小公司进入大厂,一路走来收获良多,想将这些经验分享给有需要的人,因此创建了公众号「IT界农民工」。定时更新,希望能帮助到你。

面试官:Redis 主从复制时网络开小差了怎么整?的更多相关文章

  1. Redis面试篇 -- Redis主从复制原理

        Redis一般是用来支撑读高并发的,为了分担读压力,Redis支持主从复制.架构是主从架构,一主多从, 主负责写,并且将数据复制到其它的 slave 节点,从节点负责读. 所有的读请求全部走从 ...

  2. 面试官:Redis集群有哪些方式,Leader选举又是什么原理呢?

    哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 作为一名Java程序员,Redi ...

  3. 8年经验面试官详解 Java 面试秘诀

      作者 | 胡书敏 责编 | 刘静 出品 | CSDN(ID:CSDNnews) 本人目前在一家知名外企担任架构师,而且最近八年来,在多家外企和互联网公司担任Java技术面试官,前后累计面试了有两三 ...

  4. Redis主从复制失败(master_link_status:down)

    今天配置redis主从复制时出现master_link_status:down提示. 首先打开slave的redis.conf配置文件,确定slaveof 和masterauth 两个选项配置是否正确 ...

  5. 《PHP程序员面试笔试宝典》——如何巧妙地回答面试官的问题?

    如何巧妙地回答面试官的问题? 本文摘自<PHP程序员面试笔试宝典> 所谓"来者不善,善者不来",程序员面试中,求职者不可避免地需要回答面试官各种"刁钻&quo ...

  6. 面试官:请讲一下Redis主从复制的功能及实现原理

    摘要:Redis在主从模式下会有许多问题需要考虑,这里写了一些关于redis在多服务器下的一些问题分析和总结. Redis单节点存在单点故障问题,为了解决单点问题,一般都需要对redis配置从节点,然 ...

  7. 面试官:你对Redis缓存了解吗?面对这11道面试题你是否有很多问号?

    前言 关于Redis的知识,总结了一个脑图分享给大家 1.在项目中缓存是如何使用的?为什么要用缓存?缓存使用不当会造成什么后果? 面试官心理分析 这个问题,互联网公司必问,要是一个人连缓存都不太清楚, ...

  8. Redis——面试官考题

    总结: 本文在一次面试的过程中讲述了 Redis 是什么,Redis 的特点和功能,Redis 缓存的使用,Redis 为什么能这么快,Redis 缓存的淘汰策略,持久化的两种方式,Redis 高可用 ...

  9. 《吊打面试官》系列-Redis哨兵、持久化、主从、手撕LRU

    你知道的越多,你不知道的越多 点赞再看,养成习惯 前言 Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在Redis的使用和原理方面对小伙伴们进行360°的刁难.作为一个在互联 ...

随机推荐

  1. Js中Currying的应用

    Js中Currying的应用 柯里化Currying是把接受多个参数的函数变换成接受一个单一参数的函数,并且返回接受余下的参数且返回结果的新函数的技术,是函数式编程应用. 描述 如果说函数式编程中有两 ...

  2. day30 Pyhton 面向对象 反射

    @property # 例1 - 1 (某一个属性如果是通过计算得来的,那么计算的过程写在方法里,把这个方法伪装成属性) from math import pi # class Circle: # d ...

  3. pytest文档50-命令行参数--durations统计用例运行时间

    前言 写完一个项目的自动化用例之后,发现有些用例运行较慢,影响整体的用例运行速度,于是领导说找出运行慢的那几个用例优化下. --durations 参数可以统计出每个用例运行的时间,对用例的时间做个排 ...

  4. swoole为什么不建议使用static和global

    $http = new swoole_http_server("0.0.0.0", 9501); $http->on("request", functio ...

  5. spring boot:给接口增加签名验证(spring boot 2.3.1)

    一,为什么要给接口做签名验证? 1,app客户端在与服务端通信时,通常都是以接口的形式实现, 这种形式的安全方面有可能出现以下问题: 被非法访问(例如:发短信的接口通常会被利用来垃圾短信) 被重复访问 ...

  6. ansible用authorized_key模块批量推送密钥到受控主机(免密登录)(ansible2.9.5)

    一,ansible的authorized_key模块的用途 用来配置密钥实现免密登录: ansible所在的主控机生成密钥后,如何把公钥上传到受控端? 当然可以用ssh-copy-id命令逐台手动处理 ...

  7. py正则表达式(全是干货系列)

      正则表达式的作用在这里不多赘述了,反正处理文本任务贼六就对了.Python中的正则表达式是内置在re模块中的,我们就对这个模块进行详细地讲解.这是一篇媲美帮助文档的文章!对就这么自信,不服你顺着网 ...

  8. CSS实现鼠标移入弹出下拉框

    前言 最近比较沉迷CSS,所以我现在来做个鼠标的交互效果 HTML <ul> <li>测试</li> <li>测试</li> <li ...

  9. Linux系统安装Redis(2020最新最详细)

    2020最新Linux系统发行版ContOS7演示安装Redis 为防止操作权限不足,建议切换root用户,当然如果你对Linux命令熟悉,能够自主完成权限更新操作,可以不考虑此推荐. 更多命令学习推 ...

  10. git学习(四) git log操作

    git log操作 log命令的作用:用于查看git的提交历史: git log命令显示的信息的具体含义: commit SHA-1 校验和  commit id Author 作者跟邮箱概要信息 D ...