专栏首页编程大道《【面试突击】— Redis篇》-- Redis的主从复制?哨兵机制?

《【面试突击】— Redis篇》-- Redis的主从复制?哨兵机制?

Redis如何保证高并发,高可用?

高并发:redis的单机吞吐量可以达到几万不是问题,如果想提高redis的读写能力,可以用redis的主从架构,redis天热支持一主多从的准备模式,单主负责写请求多从负责读请求,主从之间异步复制,把主的数据同步到从。

高可用:首先利用redis的主从架构解决redis的单点故障导致的不可用,然后如果使用的是主从架构,那么只需要增加哨兵机制即可,就可以实现,redis主实例宕机,自动会进行主备切换。以此来达到redis的高可用。

你刚才说主从复制,那你能具体聊一下主从复制的原理吗?

在redis主从架构中,master负责接收写请求,写操作成功后返回客户端OK,然后后将数据异步的方式发送给多个slaver进行数据同步,不过从redis 2.8开始,slave node会周期性地确认自己每次复制的数据量。

当启动一个slave node的时候,它会发送一个PSYNC命令给master node。如果slave node是重新连接master node,那么master node仅仅会复制给slave部分缺少的数据; 否则如果是slave node第一次连接master node,那么会触发一次full resynchronization全量复制。

开始full resynchronization的时候,master会启动一个后台线程,开始生成一份RDB快照文件,同时还会将从客户端收到的所有写命令缓存在内存(内存缓冲区)中。RDB文件生成完毕之后,master会将这个RDB发送给slave,slave会先写入本地磁盘,然后再从本地磁盘加载到内存中。然后master会将内存中缓存的写命令发送给slave,slave也会同步这些数据。

另外slave node做复制的时候,是不会block master node的正常工作的,也不会block对自己的查询操作,它会用旧的数据集来提供服务; 但是复制完成的时候,需要删除旧数据集,加载新数据集,这个时候就会暂停对外服务了。slave node主要用来进行横向扩容,做读写分离,扩容的slave node可以提高读的吞吐量。slave与高可用性有很大的关系。

主从复制的过程中如果因为网络原因停止复制了会怎么样?

如果出现网络故障断开连接了,会自动重连的,从redis 2.8开始,就支持主从复制的断点续传,可以接着上次复制的地方,继续复制下去,而不是从头开始复制一份。

master如果发现有多个slave node都来重新连接,仅仅会启动一个rdb save操作,用一份数据服务所有slave node。

master node会在内存中创建一个backlog,master和slave都会保存一个replica offset,还有一个master id,offset就是保存在backlog中的。如果master和slave网络连接断掉了,slave会让master从上次的replica offset开始继续复制。

但是如果没有找到对应的offset,那么就会执行一次resynchronization全量复制。

好的,那你能说说什么是哨兵有什么作用吗?

哨兵是redis集群架构中非常重要的一个组件,主要功能如下 (1)集群监控,负责监控redis master和slave进程是否正常工作 (2)消息通知,如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知给管理员 (3)故障转移,如果master node挂掉了,会自动转移到slave node上 (4)配置中心,如果故障转移发生了,通知client客户端新的master地址

哨兵本身也是分布式的,作为一个哨兵集群去运行,互相协同工作 (1)故障转移时,判断一个master node是宕机了,需要大部分的哨兵都同意才行,涉及到了分布式选举的问题 (2)即使部分哨兵节点挂掉了,哨兵集群还是能正常工作的,因为如果一个作为高可用机制重要组成部分的故障转移系统本身是单点的,那就很坑爹了。

目前采用的是sentinal 2版本,sentinal 2相对于sentinal 1来说,重写了很多代码,主要是让故障转移的机制和算法变得更加健壮和简单。

为什么redis哨兵集群只有2个节点无法正常工作?

如果两个哨兵实例,即两个redis实例,一主一从的模式。

则redis的配置quorum=1,表示一个哨兵认为master宕机即可认为master已宕机。

但是如果是机器1宕机了,那哨兵1和master都宕机了,虽然哨兵2知道master宕机了,但是这个时候,需要majority,也就是大多数哨兵都是运行的,2个哨兵的majority就是2(2的majority=2,3的majority=2,5的majority=3,4的majority=2),2个哨兵都运行着,就可以允许执行故障转移。

但此时哨兵1没了就只有1个哨兵了了,此时就没有majority来允许执行故障转移,所以故障转移不会执行。

主备切换的时候会有数据丢失的可能吗?

会有,而且有两种可能,一种是异步复制,一种是脑裂导致的数据丢失。

简单描述一下这两种数据丢失的过程吧

好的,第一种很好理解,因为master 到 slave的复制是异步的,所以可能有部分数据还没复制到slave的时候,master就宕机了,此时这些部分数据就丢失了。虽然master会做持久化,但是哨兵将slave提升为master后,如果旧的master这时候好了,会当做slave挂到新的master上,从新的master同步数据,原来的数据还是会丢失。

第二种,也就是说,某个master所在机器突然脱离了正常的网络,跟其他slave机器不能连接,但是实际上master还运行着,即集群分区现象。此时哨兵可能就会认为master宕机了,然后开启选举,将其他slave切换成了master.

这个时候,集群里就会有两个master,也就是所谓的脑裂。

此时虽然某个slave被切换成了master,但是可能client还没来得及切换到新的master,还继续向旧master写数据,这部分数据可能就丢失了。因此旧master再次恢复的加入到主从结构中时,会被作为一个slave挂到新的master上去,自己的数据会清空,重新从新的master复制数据,原来的写到旧master的数据就丢失了。

那有什么办法解决这个数据丢失的问题吗?

数据丢失的问题是不可避免的,但是我们可以尽量减少。 在redis的配置文件里设置参数

min-slaves-to-write 1
min-slaves-max-lag 10

min-slaves-to-write默认情况下是0,min-slaves-max-lag默认情况下是10。

上面的配置的意思是要求至少有1个slave,数据复制和同步的延迟不能超过10秒。如果说一旦所有的slave,数据复制和同步的延迟都超过了10秒钟,那么这个时候,master就不会再接收任何请求了。

上面两个配置可以减少异步复制和脑裂导致的数据丢失。

设置了这俩参数具体是怎么减少数据丢失的呢?

以上面配置为例,这两个参数表示至少有1个salve的与master的同步复制延迟不能超过10s,一旦所有的slave复制和同步的延迟达到了10s,那么此时master就不会接受任何请求。

我们可以减小min-slaves-max-lag参数的值,这样就可以避免在发生故障时大量的数据丢失,一旦发现延迟超过了该值就不会往master中写入数据。

那么对于client,我们可以采取降级措施,将数据暂时写入本地缓存和磁盘中,在一段时间后重新写入master来保证数据不丢失;也可以将数据写入kafka消息队列,隔一段时间去消费kafka中的数据。

通过上面两个参数的设置我们尽可能的减少数据的丢失,具体的值还需要在特定的环境下进行测试设置。

好的,今天回答的还不错,下一轮面试继续努力哦~

本系列文章在于面试突击,不是教程,要是细挖,能讲好多,而面试你只需要把这个原理说出来就行了,如果边讲边画图那就更好了。 该系列文章在于快速突击,快速拾遗,温习。

本文分享自微信公众号 - 编程大道(learn_code),作者:ITwalking

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-01-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 服务器上部署Java项目安装JDK还是JRE?

    在上一篇文章中,我们了解到了JDK和JRE的关系,知道了运行Java程序只需要JRE就行了。

    编程大道
  • [需求设计]从一个小需求感受Redis的独特魅力

    Redis在实际应用中使用的非常广泛,本篇文章就从一个简单的需求说起,为你讲述一个需求是如何从头到尾开始做的,又是如何一步步完善的。之前写过一篇《如何实现页面广...

    编程大道
  • java基础-抽象类抽象方法

    你好! 这篇文章将讲述java中的抽象类和抽象方法的知识点,这个是最简单的,也是最容易被遗忘的。

    编程大道
  • Keepalived+双主实现mysql高可用

    生产环境中一台 mysql 主机存在单点故障,所以我们要确保 mysql 的高可用性,即两台 MySQL服务器如果其中有一台 MySQL 服务器...

    L宝宝聊IT
  • 手把手学会MySql主从配置

    CREATE USER 'mysync'@'masterhostaddr' IDENTIFIED BY '123123'; GRANT REPLICATION...

    justmine
  • redis

    只要问到缓存,上来第一个问题,肯定能是先问问你项目哪里用了缓存?为啥要用?不用行不行?如果用了以后可能会有什么不良的后果?

    大学里的混子
  • ROS通信架构(上)

    在ROS的世界里,最小的进程单元就是节点(node)。一个软件包里可以有多个可执行文件,可执行文件在运行之后就成了一个进程(process),这个进程在ROS中...

    小飞侠xp
  • vscode编写插件详细过程

    前言 之前编写了一个vscode插件用vscode写博客和发布,然后有园友要求写一篇来介绍如何开发一个vscode扩展插件,或者说介绍开发这个插件的过程。然而文...

    逸鹏
  • Linux下Redis主从复制以及SSDB主主复制环境部署记录

    前面的文章已经介绍了redis作为缓存数据库的说明,本文主要说下redis主从复制及集群管理配置的操作记录: Redis主从复制(目前redis仅支持主从复制模...

    洗尽了浮华
  • kettle基础概念的学习

    1、转换。Kettle在运行转换的时候,根据用户的设置,可以将数据以不同的方式发送到多个数据流中。 注意:有两种基本发送方式,即分发和复制,分发类似于发扑克牌,...

    别先生

扫码关注云+社区

领取腾讯云代金券