Redis高级----主从、哨兵、分片、脑裂原理

news2024/11/15 7:52:56

目前已更新系列:

当前:Redis高级----主从、哨兵、分片的原理

计算机网络--面试知识总结一

计算机网络-----面试知识总结二

计算机网络--面试总结三(Http与Https)

计算机网络--面试总结四(HTTP、RPC、WebSocket、SSE)-CSDN博客

知识积累之ThreadLocal---InheritableThreadLocal总结

本次Redis的总结是基于黑马的redis课程视频进行总结的,主要是梳理逻辑以及总结面试的时候能按照梳理的顺序进行作答不卡顿,大家向详细学习,可以去bilibili学习

主从同步的原理

全量同步

完整流程描述:

  • slave节点请求增量同步
  • master节点判断该请求的replid,发现不一致,说明是第一次进行主从同步拒绝增量同步
  • master将执行bgsave命令将完整内存数据生成RDB,发送RDB到slave
  • slave清空本地数据,加载master的RDB
  • master将RDB期间的客服端发送过来的新命令记录在repl_baklog,并持续将log中的命令发送给slave
  • slave执行接收到的命令,保持与master之间的同步

这里有一个问题,master如何得知salve是第一次来连接呢??---》replid相同即代表不是第一次连接,因为如果是第一次连接主节点会将自己的replid发送给从节点然后从节点就将其设置为自己的replid

有几个概念,可以作为判断依据:

  • Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid
  • offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。

增量同步

全量同步需要先做RDB,然后将RDB文件通过网络传输个slave,成本太高了。因此除了第一次做全量同步,其它大多数时候slave与master都是做增量同步

slave重启之后会执行增量同步,因为slave由于宕机那么master节点中记录这宕机期间所有的新命令到repi_baklog中,然后发送给刚恢复的该从节点,那么该从节点就开始做同步工作了

什么是增量同步?就是只更新slave与master存在差异的部分数据。如图:

由于不是第一次连接,那么此时master节点并不会将repl_baklog中的命令全部发给slave节点而是,将从节点发来的offset的位置开始读操作,然后就可以将slave错过的消息重新加载

流程:

  • slave节点重启后会向主节点发送请求,请求中会带上replid和当前节点所更新到的位置即offset偏移量
  • 主节点收到请求后对从节点发过来的replid进行检查,发现和自己的replid一样,说明不是第一次做主从同步,那么主节点会向从节点发送continue给从节点,高数从节点不用做RDB全量同步
  • 接着主节点会取缓冲文件repl_log中对比当前自己的最新偏移量和slave发送过来的偏移量,然后就开始发送从节点到主节点的偏移量区间的命令,相当于从节点就开始一直追着主节点的offset走,最终达到同步的效果
  • 但是当slave节点宕机的时间太长,此时主节点中写的新命令覆盖了原来从节点的offset位置,那么此时就只有做全局同步操作,才能确保主从一致了

主从同步的优化

可以从两个方面进行考虑

  • 提高全量同步的性能
  • 减少全量同步(优先考虑)

可以从以下几个方面来优化Redis主从就集群:

  • 提高全量同步的性能
    • 在master中配置repl-diskless-sync yes启用无磁盘复制即当我们要开始写RDB文件时,不把它写在磁盘中,而是直接写在网络中,这样就能避免全量同步时的磁盘IO。
      • 将master中的redis.conf配置文件的repl-diskless-sync yes 改为yes表示,当我们在写RDB时我们不把他写道磁盘中,而是通过网络直接发给slave,使用场景,
      • 使用场景:磁盘读写比较慢,网络带宽良好,
    • Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO
  • 减少全量同步:
    • 适当提高repl_baklog的大小,因为触发全量同步的另外一个因素就是,主节点写的新命令覆盖了slave还未同步命令,此时就会做全量同步,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
    • 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力

小结:

全量同步和增量同步的区别

  • 全量同步:master会将内存中的数据生成RDB,发送RDB到slave,后续的命令则记录在repl_backlog中,然后逐个发送给slave
  • 增量同步:slave节点提交自己的offset给master,master收到之后,会从repli_backlog中将从节点偏移量offset之后的命令发送给slave

什么时候执行全量同步

  • slave节点第一次连接master节点时
  • slave节点断开时间太久,repl_backlog的offset已经被覆盖时

什么时候执行增量同步

  • slave节点断开后又恢复且再主节点的repl_backlog中能找到从节点的offset时

哨兵的结构如图:

哨兵模式

哨兵的作用如下:

哨兵同时也是一个集群,因为如果哨兵挂了,那么不就不能监控了

  • 监控:Sentinel 会不断检查您的master和slave是否按预期工作
  • 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主,即故障节点恢复后就变成从节点了
  • 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端

集群监控原理

Sentinel是基于心跳机制监测服务状态,会每隔1秒向集群的每个实例发送ping命令:

•主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线

•客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。

这个指定数量(quorum)可以通过配置文件来配置

当master客观下线之后,sentinel就会重新选一个master选取规则为

  • 判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds*10)则会排除该slave节点,断开时间越长不就代表着数据未同步的越多,因此首先排除
  • 然后判断每个slave节点的优先级slave-priority的值,值越小优先级越高,如果是0则用不参加选举,刚开始优先级默认值都一样
  • 如果优先级一样,则判断slave节点的offset值(偏移量,在repl_baklog中的偏移量),越大说明数据越新,那么优先级越高
  • 最后如果偏移量都一样,那么就随便挑一个作为主节点,一般选取slave节点的运行id值,越小优先级越高

选中slave节点后怎么实现故障转移?

当选中了一个slave为新的master节点后,故障转移步骤如下:

  • 1、sentinel会给备选的slave1节点发送slaveof no one(永不为奴)命令,让该节点称为master
  • 2、sentinel会给所有其他的slave发送slaveof 192.168.64.211:7001(选取的新master地址)命令,让这些slave称为新的master的从节点,开始从新的master上同步数据
  • 3、最后,sentinel会强制更改原来故障Master节点的配置文件,将其标记为slave节点标记命令为(slaveof 192.168.64.211;7001,新master地址),当故障节点恢复后自动称为新master的从节点

3.1.4.小结

Sentinel的三个作用是什么?

  • 监控
  • 故障转移
  • 通知

Sentinel如何判断一个redis实例是否健康?

  • 每隔1秒发送一次ping命令,如果超过一定时间没有相向则认为是主观下线
  • 如果大多数sentinel都认为实例主观下线,则判定服务下线

故障转移步骤有哪些?

  • 首先选定一个slave作为新的master,执行slaveof no one
  • 然后让所有节点都执行slaveof 新master
  • 修改故障节点配置,添加slaveof 新master

分片集群

有什么用

分片集群主要是为了解决

1、海量数据存储问题

2、高并发写的问题

因为我们通过主从、哨兵模式可以解决redis中的高并发读问题和高可用问题但并没解决该问题

原理

首先分片集群的特征就是

  • 集群中有多个master节点、每个master保存不同的数据
  • 每个master都可以由多个从节点(slave)
  • master之间同样是通过ping监测彼此的健康状态
  • 客户端可以访问集群中的任意节点,最终都会被路由转发到正确的节点位置

注意分片集群中默认不是采用读写分离的形式,默认情况下,所有的读写操作都会发送到负责相应哈希槽的主节点(master node)。如果需要读写分离那么需要再重新配置读写分离配置

分片原理

插槽原理

redis分片集群主要采用插槽来进行分片存储,即redis中会将16384个插槽分配给你设置的主节点,就相当于每个主节点会映射到某段插槽范围,当我们进行写数据或者读数据的时候都会先根据你要读写的key,来计算这个key中用于计算哈希值得有效部分,得到对应的哈希值,然后将哈希值对16384进行取余得到该key对应的插槽位置,得到该位置后,就会看看该插槽位置是属于哪个主节点所管理的插槽区间,然后就找到该主节点进行读写操作。

redis中为甚么要将数据和插槽进行绑定

为什么我们的key是跟插槽进行绑定,而不是直接根redis进行绑定,这是因为redis的主节点是可能出现宕机的情况或者说redis可能进行集群扩容或集群收缩使得master节点增加或者减小,导致节点上的数据丢失了,

但是如果key跟着插槽绑定,当节点宕机时我们可以将这个节点对应的插槽转移到活着的节点,集群扩容时,我们也可以将插槽进行转移,这样数据跟着插槽走就可以永远的找到数据的位置

Redis会把每一个master节点映射到0~16383共16384个插槽(hash slot)上,查看集群信息时就能看到:

其中有效key的使用规则

数据key不是与节点绑定,而是与插槽绑定。redis会根据key的有效部分计算插槽值,分两种情况:

  • key中包含"{}",且“{}”中至少包含1个字符,“{}”中的部分是有效部分
  • key中不包含“{}”,整个key都是有效部分

使用场景:

  • 同一类数据固定保存在同一个Redis实例,避免访问同一类数据时进行路由重定向,耗费资源

如何将同一类数据固定保存在桶一个Redis实例?

因为如果这类数据不在同一台主节点上,那么我们在查询数据的时候就会有对请求的重定向,而重定向需要重新建立连接,性能上会有一定损失,因此如果将同一类数据放在同一台实例上那么在查询该类数据时我们就只从这台实例上去查,这样就避免了重定向问题

解决方法:让着一系列同类型的数据在存放时,让该类数据key的有效部分相同,那么计算出来的插槽值就一定相同了,从而达到存放在同一态实例上的效果,级让该类数据的key将相同的有效部分用大括号括起来

例如:key是num,那么就根据num计算,如果是{itcast}num,则根据itcast计算。计算方式是利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是slot值。

简单举例和使用细节

路由重定向演示

如图,在7001这个节点执行set a 1时,对a做hash运算,对16384取余,得到的结果是15495,因此要存储到70003节点。

到了7003后,执行get num时,对num做hash运算,对16384取余,得到的结果是2765,因此需要切换到7001节点

执行一次对key,的访问操作

Redis中如何判断某个key应该在哪个实例中(在哪台主节点上)

  • 将16384个插槽分配到不同实例上
  • 根据key的有效部分计算出哈希值,对16384取余,
  • 余数就是对应的插槽位置,然后看看这个插槽位置是在哪个主节点映射的插槽范围下,最终得到该key的结果

分片集群扩容、缩容原理

扩容

当你想要在集群中添加一个节点,

  • 如果想添加从节点那只执行add-node命令时要指明要成为谁的从节点
  • 如果是想要添加主节点的话,就要执行add-node命令(该命令中需要指明添加节点的ip和端口,和现在集群中的任意一个节点,用于通知集群),此时刚添加的主节点的插槽默认是0个,所以所有的写操作都不会分配到该新加的主节点上,因此我们需要为其分配插槽
    • 根据redis-cli --cluster help查出分配插槽的命令为redis-cli --cluster reshard然后分局命令看是从哪个已分配插槽的节点上转移一部分插槽作为新节点的插槽

删除:

在对主节点进行删除操作时,首先需要先将该节点上已经分配的插槽进行转移,然后此时该节点插槽数为空就可以执行 del-node操作

案例

需求:向集群中添加一个新的master节点,并向其中存储 num = 10

  • 启动一个新的redis实例,端口为7004
  • 添加7004到之前的集群,并作为一个master节点
  • 给7004节点分配插槽,使得num这个key可以存储到7004实例

这里需要两个新的功能:

  • 添加一个节点到集群中
  • 将部分插槽分配到新插槽

想要完成该扩容任务,需要核心在于,创建一个节点将其设置为主节点,然后看看key为num的哈希槽位置在哪,然后通过插槽看看时属于原来的哪个主节点,之后再该主节点中转移一段包含该哈希槽的槽位给新的主节点即可

故障转移

自动故障转移:

redis集群具有自动的主从切换功能即不需要哨兵,当你的主节点宕机了,那么会将该主节点的从节点选一个

来充当主节点,然后当原来的主节点重新恢复,此时会将其设置为原来从节点的从节点

手动故障转移

为甚要有手动手动故障转移?

假设这样一种场景:我们这个集群中7001这个master但是他的及其需要进行维护升级,此时我们启动一个性能比较好的新节点作为7001这个节点的从节点,然后手动的将其替换成7001作为主节点(手动是因为,如果自动故障转移,那么选取的节点是我们不受控的,即当我们从节点数不止一个时,那么就不一定能选取到我们想要的新节点作为主节点)

怎么做:

在新的子结点上利用cluster failover命令可以手动让集群中的某个master宕机,切换到执行cluster failover命令的这个slave节点,实现无感知的数据迁移。其流程如下:

这种failover命令可以指定三种模式:

  • 缺省:默认的流程,如图1~6歩
  • force:省略了对offset的一致性校验
  • takeover:直接执行第5歩,忽略数据一致性、忽略master状态和其它master的意见

出现脑裂问题怎么保证集群还是高可用的

什么是脑裂问题

脑裂说的就是当我们的主节点没有挂,但是因为网络延迟较大,然后和主节点相连的哨兵通信较差,之后主从之间的同步就会受影响,主节点和哨兵之间的信号也不好,但是客户端和主节点之间还能进行通信,此时向主节点更新了一条数据,而由于网络问题,从节点未能同步,且由于哨兵集群和主节点之间的通信较差每次ping都收到主节点的恢复,那么哨兵集群就会判断主节点从主观下线到了客观下线(超过了设置的客观下线的数量),那么此时哨兵就会认为主节点挂了,此时会选取一个哨兵作为主节点,然后强行修改原来主节点的配置将其设置为该slave节点的从节点(然后向新的主节点发起主从同步的时候就会进行全量同步,因此原来主节点中更新的那个消息就会彻底丢失),但是此时的问题就是新的从节点并没有原来更新的那条数据的信息,这样就造成了数据的不一致。这就是脑裂问题

解决的核心思路就是

由于是因为主节点能处理客服端的更新操作和,网络延迟导致主从不一致,然后又由哨兵选取从节点变更为主节点导致的数据丢失,那么我们就可以采取这样的操作,即当发生这种网络延迟问题时,我们就拒绝客服端发过来的请求,这样就保证网络延迟期间主从的一致性,此时就算哨兵将从节点设置为新的主节点也没关系,因为数据被没有被更新,从节点中还是有所有数据

具体解决

具体解决就可以在配置文件中进行配置主节点发现从节点下线或者通信超时的总数量小于阈值

当主节点发现从节点下线或者通信超时的总数量小于阈值时,那么禁止主节点进行写数据,直接把错误返回给客户端。

在 Redis 的配置文件中有两个参数我们可以设置:

  • min-slaves-to-write x,与主节点能连接的同的从节点个数只有超过x时才能进行写操作,否之拒绝写操作
  • min-slaves-max-lag x,主从数据同步的延迟不能超过 x 秒,如果超过,主节点会禁止写数据。

我们可以把 min-slaves-to-write 和 min-slaves-max-lag 这两个配置项搭配起来使用,分别给它们设置一定的阈值,假设为 N 和 T。

这就表示这两个配置项组合后的要求是,主库连接的从库中至少有 N 个从库,和主库进行数据复制时的 ACK 消息延迟不能超过 T 秒,否则,主库就不会再接收客户

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2084818.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 11 ,Android Studio 三方APP调用系统 system/lib 目录下so库使用过程中的BUG(坑)。

背景介绍:最近在做文件管理器,需要把图库的功能集成到文件管理器中,实现在文件管理器中打开图片、切换图片的功能。在实现gif图片打开功能的时候,需要用到系统现成的gifplayer so库,导入Android studio的时候遇到了一堆…

游戏发行技术体系之SDK技术体系

在上篇文章中提现过,SDK主要分为充值、登录、合规、数据、聚合和后台管理。 下面是针对SDK技术体系进行拆分 这个地方没有写账号,是因为我会账号独立出来,这块会在后面的账号技术体系单独规划。

爆改YOLOv8|利用分层特征融合策略MSBlock改进yolov8,暴力涨点

1,本文介绍 MSBlock 是一种分层特征融合策略,用于改进卷积神经网络中的特征融合效果。它通过分层次地融合不同尺度的特征图来提高网络的表达能力和性能。MSBlock 采用多尺度特征融合的方法,确保网络能够有效地捕捉不同层次和尺度的信息&…

FPGA实现HDMI传输(二)

之前的文章简单介绍了HDMI接口、TMDS编码以及ADV611工作原理和寄存器配置,本篇博客将给出具体的代码以及板级验证结果,代码参考自米联客的教程。 一.ADV7611配置 1.i2c驱动模块 timescale 1ns / 1psmodule uii2c# (parameter WMEN_LEN …

Git使用教程(小白也能看懂)

git的使用教程(学习和工作中都能用到) 1、所需工具 git bash 1)安装git bash 官网:https://git-scm.com/download/win 2)在文件夹空白处鼠标右键 若出现 上图说明安装成功 2、使用 1)我们想要克隆一…

DHT11 实现温湿度传感器

DHT11 DHT11是一款含有已校准数字信号输出的温湿度复合传感器,它结合了电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。通过采用专用的数字模块采集技术和温湿度传感技术,DHT11确保了产品的高可靠性和长期稳定性 DHT11时序…

android studio 新建java工程, 安卓新建项目,android studio2024 如何新建java项目

主要解决,新增安卓工程,没有java选项 1. 点击左上角FIle -> New -> 2. 选择 no activity 选项, 然后next 3. langua 就可以选择java 了。name自己定义项目名称,项目存储地址,包名。 配置完成选择finish. 4. fin…

【C++】vector(下)--上篇

个人主页~ vector(上)~ vector 二、vector的模拟实现1、了解组成2、vector.h(1)为什么有了size_t参数的vector构造函数还要再写一个int参数的重载vector构造函数(2)为什么reserve不用memcpy(3&…

Mysql剖析(三)----MySql的事务详解

事务(Transaction):一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中的各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL、C或Java)书写的用户程序的执行所引…

Python脚本实现向飞书发送卡片消息

目录 1 先创建一个卡片消息2 Python脚本2.1 告警测试2.2 告警恢复 总结 1 先创建一个卡片消息 飞书卡片搭建工具 根据自己的需要创建一个消息卡片: 可以在 卡片源代码 中看到这个卡片的代码信息 2 Python脚本 2.1 告警测试 test.py 文件 ""&quo…

MacOS安装Docker Desktop

目录 安装Docker Desktop 1.下载 2.安装 3.验证 安装Docker Desktop 1.下载 访问Docker官方网站下载页面:https://www.docker.com/products/docker-desktop 选择自己所需的版本下载即可 2.安装 3.验证 1.查询版本号 docker --version 2.也可以运行一个简单的…

【vue、Electron】搭建一个Electron vue项目过程、将前端页面打包成exe 桌面应用

文章目录 前言使用 electron-vue 创建项目1. 安装 vue-cli(如果未安装)2. 使用 electron-vue 模板创建项目3. 安装和配置 electron-builder4. 运行Electron项目5. 打包应用 可能遇到的问题解决Electron vue首次启动巨慢无法加载执行npm run electron:bui…

从地图信息实时检测路口的各向通行状况、红绿灯及溢出情况

高德地图、百度地图都能获得实时的道路信息。 C# 编写的路况信息爬虫可获得准实时(1分钟间隔)的路口的各向通行状况、红绿灯及溢出情况。 优势: 投入少,效果好,无需安装设备; 缺陷: 时间间隔…

数据集不够用?3DGS助力生成带标注的全新扩展数据!

作者主页:https://louiszengcn.github.io/ 论文标题: Realistic Surgical Image Dataset Generation Based On 3D Gaussian Splatting 导读: 近年来,随着AI技术的飞速发展,数据量的增加为数据驱动的神经网络提供了更强…

汽车免拆诊断案例 | 2012 款大众速腾车发动机偶尔抖动

故障现象 一辆2012款大众速腾车,搭载CST发动机和干式双离合变速器,累计行驶里程约为17万km。车主反映,发动机偶尔抖动。 故障诊断 接车后试车,确认发动机怠速偶尔抖动,且在D挡起步时抖动明显。用故障检测仪检测&…

专题◉万字长文!盘点过去一年最出圈的Prompt项目教程,有3份在悄悄更新

1. OpenAI 官方出品 | 提示工程最权威的教程 (最新版) 2023年6月,OpenAI 发布了一篇〖*GPT Best Practice (GPT 最佳实践)* 〗教程,详细介绍 ChatGPT Prompt 交互策略&技巧,并且给出了示例说明。 一年时间过去了,OpenAI 不…

Unity射击游戏开发教程:(33)控制飞机左右移动

在本文中,我将介绍如何在玩家朝该方向移动时添加向左和向右转动的动画。 我们已经将左转和右转动画导入到我们的项目中。在我使用的动画中,它们只有两帧,因为我们希望飞机倾斜得很快,这样玩家在按下相应按钮时就能直接感觉到转弯。 </

为什么帕金森病患者在紧张或焦虑状态下震颤会加重?

为什么帕金森病患者在紧张或焦虑状态下震颤会加重&#xff1f; 帕金森病患者在紧张或焦虑状态下震颤加重的原因可能与多个因素有关。首先&#xff0c;帕金森病与大脑中多巴胺水平的降低有关&#xff0c;这种神经递质的失衡会影响运动控制。当患者感到紧张时&#xff0c;大脑皮…

嵌入式软件开发之状态机与事件驱动分析

状态机是一种程序架构,事件驱动也是一种程序架构,在某些开发场景里面,两者是可以一同合并使用的。 事件驱动的概念 生活中有很多事件驱动的例子,上自习瞒着老师偷睡觉就是很生动的一个。 我们都是从高中时代走过来的,高中的学生苦啊,觉得睡觉是世界上最奢侈的东西, 有时…

运维监控工具 PIGOSS BSM :PostgreSQL数据库监控指标

在PostgreSQL数据库中&#xff0c;为了确保其稳定运行和性能优化&#xff0c;我们需要监控一系列关键的指标。以下是一些主要的PostgreSQL监控指标介绍&#xff1a; 连接数&#xff08;Connections&#xff09;&#xff1a; 定义&#xff1a;连接数是指当前正在与数据库建立连…