面试官:要不你来讲讲你最近在看的点呗?可以拉出来一起讨论下(今天我也不知道要问什么)

候选者:最近在看「Redis」相关的内容

面试官:嗯,我记得已经问过Redis的基础和持久化了

面试官要不你来讲讲你公司的Redis是什么架构的咯?

候选者:我前公司的Redis架构是「分片集群」,使用的是「Proxy」层来对Key进行分流到不同的Redis服务器上

候选者:支持动态扩容、故障恢复等等...

面试官:那你来聊下Proxy层的架构和基本实现原理?

候选者:抱歉,这块由中间件团队负责,具体我也没仔细看过

候选者:...

面试官:....

候选者:不过,我可以给你讲讲现有常见开源的Redis架构(:

面试官:那只能这样了,好吧,你开始吧

候选者:那我从基础讲起吧?

候选者:在之前提到了Redis有持久化机制,即便Redis重启了,可以依靠RDB或者AOF文件对数据进行重新加载

候选者:但在这时,只有一台Redis服务器存储着所有的数据,此时如果Redis服务器「暂时」没办法修复了,那依赖Redis的服务就没了

候选者:所以,为了Redis「高可用」,现在基本都会给Redis做「备份」:多启一台Redis服务器,形成「主从架构」

候选者:「从服务器」的数据由「主服务器」复制过去,主从服务器的数据是一致的

候选者:如果主服务器挂了,那可以「手动」把「从服务器」升级为「主服务器」,缩短不可用时间

面试官那「主服务器」是如何把自身的数据「复制」给「从服务器」的呢?

候选者:「复制」也叫「同步」,在Redis使用的是「PSYNC」命令进行同步,该命令有两种模型:完全重同步和部分重同步

候选者:可以简单理解为:如果是第一次「同步」,从服务器没有复制过任何的主服务器,或者从服务器要复制的主服务器跟上次复制的主服务器不一样,那就会采用「完全重同步」模式进行复制

候选者:如果只是由于网络中断,只是「短时间」断连,那就会采用「部分重同步」模式进行复制

候选者:(假如主从服务器的数据差距实在是过大了,还是会采用「完全重同步」模式进行复制)

面试官那「同步」的原理过程可以稍微讲下嘛?

候选者:嗯,没问题的

候选者:主服务器要复制数据到从服务器,首先是建立Socket「连接」,这个过程会干一些信息校验啊、身份校验啊等事情

候选者:然后从服务器就会发「PSYNC」命令给主服务器,要求同步(这时会带「服务器ID」RUNID和「复制进度」offset参数,如果从服务器是新的,那就没有)

候选者:主服务器发现这是一个新的从服务器(因为参数没带上来),就会采用「完全重同步」模式,并把「服务器ID」(runId)和「复制进度」(offset)发给从服务器,从服务器就会记下这些信息。

面试官:嗯...

候选者:随后,主服务器会在后台生成RDB文件,通过前面建立好的连接发给从服务器

候选者:从服务器收到RDB文件后,首先把自己的数据清空,然后对RDB文件进行加载恢复

候选者:这个过程中,主服务器也没闲着(继续接收着客户端的请求)

面试官:嗯...

候选者:主服务器把生成RDB文件「之后修改的命令」会用「buffer」记录下来,等到从服务器加载完RDB之后,主服务器会把「buffer」记录下的命令都发给从服务器

候选者:这样一来,主从服务器就达到了数据一致性了(复制过程是异步的,所以数据是『最终一致性』)

面试官:嗯...

面试官那「部分重同步」的过程呢?

候选者:嗯,其实就是靠「offset」来进行部分重同步。每次主服务器传播命令的时候,都会把「offset」给到从服务器

候选者:主服务器和从服务器都会将「offset」保存起来(如果两边的offset存在差异,那么说明主从服务器数据未完全同步)

候选者:从服务器断连之后,就会发「PSYNC」命令给主服务器,同样也会带着RUNID和offset(重连之后,这些信息还是存在的)

面试官:嗯...

候选者:主服务器收到命令之后,看RUNID是否能对得上,对得上,说明这可能以前就复制过一部分了

候选者:接着检查该「offset」是否在主服务器记录的offset还存在

候选者:(这里解释下,因为主服务器记录offset使用的是一个环形buffer,如果该buffer满了,会覆盖以前的记录)

候选者:如果找到了,那就把从缺失的一部分offer开始,把对应的修改命令发给从服务器

候选者:如果从环形buffer没找到,那只能使用「完全重同步」模式再次进行主从复制了

面试官主从复制这块我了解了,那你说到现在,Redis主库如果挂了,你还是得「手动」将从库升级为主库啊

面试官你知道有什么办法能做到「自动」进行故障恢复吗?

候选者:必须的啊,接下来就到了「哨兵」登场了

面试官:开始你的表演吧。

候选者:「哨兵」干的事情主要就是:监控(监控主服务器的状态)、选主(主服务器挂了,在从服务器选出一个作为主服务器)、通知(故障发送消息给管理员)和配置(作为配置中心,提供当前主服务器的信息)

候选者:可以把「哨兵」当做是运行在「特殊」模式下的Redis服务器,为了「高可用」,哨兵也是集群架构的。

候选者:首先它需要跟Redis主从服务器创建对应的连接(获取它们的信息)

候选者:每个哨兵不断地用ping命令看主服务器有没有下线,如果主服务器在「配置时间」内没有正常响应,那当前哨兵就「主观」认为该主服务器下线了

候选者:其他「哨兵」同样也会ping该主服务器,如果「足够多」(还是看配置)的哨兵认为该主服务器已经下线,那就认为「客观下线」,这时就要对主服务器执行故障转移操作。

面试官:嗯...

候选者:「哨兵」之间会选出一个「领头」,选出领头的规则也比较多,总的来说就是先到先得(哪个快,就选哪个)

候选者:由「领头哨兵」对已下线的主服务器进行故障转移

面试官:嗯...

候选者:首先要在「从服务器」上挑选出一个,来作为主服务器

候选者:(这里也挑选讲究,比如:从库的配置优先级、要判断哪个从服务器的复制offset最大、RunID大小、跟master断开连接的时长...)

候选者:然后,以前的从服务器都需要跟新的主服务器进行「主从复制」

候选者:已经下线的主服务器,再次重连的时候,需要让他成为新的主服务器的从服务器

面试官嗯...我想问问,Redis在主从复制的和故障转移的过程中会导致数据丢失吗

候选者:显然是会的,从上面的「主从复制」流程来看,这个过程是异步的(在复制的过程中:主服务器会一直接收请求,然后把修改命令发给从服务器)

候选者:假如主服务器的命令还没发完给从服务器,自己就挂掉了。这时候想要让从服务器顶上主服务器,但从服务器的数据是不全的(:

候选者:还有另一种情况就是:有可能哨兵认为主服务器挂了,但真实是主服务器并没有挂( 网络抖动),而哨兵已经选举了一台从服务器当做是主服务器了,此时「客户端」还没反应过来,还继续写向旧主服务器写数据

候选者:等到旧主服务器重连的时候,已经被纳入到新主服务器的从服务器了...所以,那段时间里,客户端写进旧主服务器的数据就丢了

候选者:上面这两种情况(主从复制延迟&&脑裂),都可以通过配置来「尽可能」避免数据的丢失

候选者:(达到一定的阈值,直接禁止主服务器接收写请求,企图减少数据丢失的风险)

面试官要不再来聊聊Redis分片集群?

候选者:嗯...分片集群说白了就是往每个Redis服务器存储一部分数据,所有的Redis服务器数据加起来,才组成完整的数据(分布式)

候选者:要想组成分片集群,那就需要对不同的key进行「路由」(分片)

候选者:现在一般的路由方案有两种:「客户端路由」(SDK)和「服务端路由」(Proxy)

候选者:客户端路由的代表(Redis Cluster),服务端路由的代表(Codis)

面试官要不来详细讲讲它们的区别呗?

候选者:今天有点儿困了,要不下次呗?

本文总结

  • Redis实现高可用

    • AOF/RDB持久化机制
    • 主从架构(主服务器挂了,手动由从服务器顶上)
    • 引入哨兵机制自动故障转义
  • 主从复制原理

    • PSYNC命令两种模式:完全重同步、部分重同步
    • 完全重同步:主从服务器建立连接、主服务器生成RDB文件发给从服务器、主服务器不阻塞(相关修改命令记录至buffer)、将修改命令发给从服务器
    • 部分重同步:从服务器断线重连,发送RunId和offset给主服务器,主服务器判断offset和runId,将还未同步给从服务器的offset相关指令进行发送
  • 哨兵机制

    • 哨兵可以理解为特殊的Redis服务器,一般会组成哨兵集群
    • 哨兵主要工作是监控、告警、配置以及选主
    • 当主服务器发生故障时,会「选出」一台从服务器来顶上「客观下线」的服务器,由「领头哨兵」进行切换
  • 数据丢失

    • Redis的主从复制和故障转移阶段都有可能发生数据丢失问题(通过配置尽可能避免)

欢迎关注我的微信公众号【Java3y】来聊聊Java面试,对线面试官系列持续更新中!

【对线面试官-移动端】系列 一周两篇持续更新中!

【对线面试官-电脑端】系列 一周两篇持续更新中!

原创不易!!求三连!!

那一天,我被Redis主从架构支配的恐惧的更多相关文章

  1. 10.Redis 主从架构

    作者:中华石杉 Redis 主从架构 单机的 redis,能够承载的 QPS 大概就在上万到几万不等.对于缓存来说,一般都是用来支撑读高并发的.因此架构做成主从(master-slave)架构,一主多 ...

  2. redis主从架构,分片集群详解

    写在前面:这篇笔记有点长,如果你认真看完,收获会不少,如果你只是忘记了相关命令,请翻到末尾. redis的简单介绍: 一个提供多种数据类类型储存,整个系统都在内存中运行的, 定期通过异步的方式把数据刷 ...

  3. 采用redis 主从架构的原因

    如果系统的QPS超过10W+,甚至是百万以上的访问,则光是Redis是不够的,但是Redis是整个大型缓存架构中,支撑高并发的架构非常重要的环节. 首先,你的缓存中间件.缓存系统,必须能够支撑起10w ...

  4. redis主从架构的搭建

    本项目采用主从架构,一主两从一个哨兵.在x.x.x.69上部署主节点,在70上部署从节点1和哨兵节点,在71上部署从节点2. 准备: 1.首先上传redis文件到三台linux上,目录/home/sy ...

  5. Redis主从架构搭建和哨兵模式(四)

    一主一从,往主节点去写,在从节点去读,可以读到,主从架构就搭建成功了 1.启用复制,部署slave node wget http://downloads.sourceforge.net/tcl/tcl ...

  6. Redis 主从架构搭建

    引言 准备搭建的是主从架构( Master/Slave )中的一主两从模式:其中 Master 为 Redis 的主服务器,主要负责写操作,两个 Slave 为 Redis 的从服务器,主要负责读操作 ...

  7. redis主从架构宕机问题手动解决

    1    主机宕机 1.  设置端口6379是主机,端口6380是从机,全部都正常启动 2.  验证在6379写入数据,在6380也能得到数据 3.  现在将6379主机停掉,模拟主机宕机 4.  由 ...

  8. redis主从架构及redis集群

    https://redis.io/topics/cluster-spec Redis Cluster does not support multiple databases like the stan ...

  9. Redis主从架构核心原理

    Redis-Cluster工作原理: redis集群内置了16384个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果 ...

随机推荐

  1. 腾讯首个CNCF沙箱开源项目

    作者 SuperEdge开发者.腾讯云容器产品中心边缘计算团队.腾讯开源生态管理协会 SuperEdge 进入 CNCF 沙箱 2021 年 9 月 14 日,云原生分布式边缘容器系统 SuperEd ...

  2. 1. JVM核心类加载器及类加载的全过程

    运行环境: 下面说明一下我的运行环境.我是在mac上操作的. 先找到mac的java地址. 从~/.bash_profile中可以看到 java的home目录是: /Library/Java/Java ...

  3. C++ostringstream用法

    ostringstream用法 1.类型转换 要求包含头文件; 字符串和int之间的互相转换: int num = 100; string str = ""; std::ostri ...

  4. 题解 Wide Swap

    题目传送门 题目大意 给出一个长度为 \(n\) 的排列 \(a_{1,2,...,n}\) 以及常数 \(k\),每次可以交换两个数 \(a_i,a_j\) 当且仅当 \(j-i\ge k \tex ...

  5. SpringBoot配置文件application

    配置文件 SpringBoot使用一个全局的配置文件 , 配置文件名称是固定的,有两种文件格式: application.properties 语法结构 :key=value application. ...

  6. UDP接收端和发送端_Socket编程

    UDP接收端 接收端启动文件 1 import java.net.DatagramSocket; 2 import java.net.SocketException; 3 4 public class ...

  7. Python3 网络通信 网络聊天室 文件传输

    Python3 网络通信 网络聊天室 文件传输 功能描述 该项目将实现一个文字和文件传输的客户端和服务器程序通信应用程序.它将传输和接收视频文件. 文本消息必须通过TCP与服务器通信,而客户端自己用U ...

  8. 来说说JPA、Hibernate、Spring Data JPA之间的什么关系?

    目录 JPA Hibernate Spring Data JPA 实践 来说说JPA.Hibernate.Spring Data JPA之间的什么关系 Java 持久层框架访问数据库的方式大致分为两种 ...

  9. 【实验向】问题:假设计算机A和计算机B通信,计算机A给计算机B发送一串16个字节的二进制字节串,以数组形式表示:

    问题: 假设计算机A和计算机B通信,计算机A给计算机B发送一串16个字节的二进制字节串,以数组形式表示: unsigned char[16] = {0x3f, 0xa0, 0x00, 0x00, 0x ...

  10. javascript-原生-面向对象

    1.javascript面向对象程序设计 概述:javascript不想其他面向对象编程语言那样有类的概念,javascript没有类(构造函数)的概念,只有对象的概念. 2.理解javascript ...