Redis学习[4] ——Redis集群

news2024/9/24 1:26:21

五、Redis 集群

5.1 什么是Redis集群?

如何提供一个高可用的Redis服务? —— 构建Redis集群

单服务器Redis由于数据都是存储在一台服务器,如果这台服务器出现宕机或者故障,可能会导致服务不可用甚至数据丢失

要避免这种单点故障,最好的办法是将数据被分到其他服务器上,让这些服务器也能够对外提供服务,这样即使有一台服务器发生了故障,其他服务器依然可以继续提供服务。

数据一致性?

由于多个服务器保存同一份数据,所以**如何保持数据的一致性是关键问题。Redis中有三种方案来保证数据的一致性:主从复制、哨兵机制、切片集群**。

5.2 主从复制模式

5.2.1 什么是主从复制?

主从复制模式中,主从服务器之间采用的是**「读写分离」的方式。主服务器可以进行读写操作,当发生写操作时自动将写操作同步给从服务器,而从服务器一般是只读,并接受主服务器同步过来写操作命令,然后执行这条命令。**

在这里插入图片描述

也就是说,所有的数据修改只在主服务器上进行,然后将最新的数据同步给从服务器,这样就使得主从服务器的数据是一致的。主从服务器之间的命令复制是**异步**进行的。

但是,与Raft算法不一致的是,主服务器并不会等到从服务器实际执行完命令后,再把结果返回给客户端,而是**主服务器自己在本地执行完命令后,就会向客户端返回结果了。如果从服务器还没有执行主服务器同步过来的命令,主从服务器间的数据就不一致了。所以,无法实现强一致性保证(主从数据时时刻刻保持一致),数据不一致是难以避免的**。

5.2.2 主从复制是怎么实现的?
  • 第一次同步:全量复制

    通过replicaof命令可以让服务器B成为服务器A的从服务器:

    # 服务器 B 执行这条命令
    replicaof <服务器 A 的 IP 地址> <服务器 A 的 Redis 端口号>
    

    服务器B成为服务器A的从服务器后,会发生与A服务器的第一次同步。第一次同步可以分为三个阶段:

    • 第一阶段建立连接,协商同步

      从服务器会向主服务器申请数据同步,然后主服务器向从服务器作出响应,表明复制方法(全量复制)等。

    • 第二阶段主服务器同步数据给从服务器(全量复制);

      主服务器会新开辟一个子进程来生成当前的RDB快照,然后把这个快照文件发送给从服务器;

      从服务器收到RDB快照后,清空该服务器上的数据,然后载入这个RDB快照;

      在此期间,如果主服务器收到了新的写操作命令,将会写到一个缓冲区中**replication buffer**,等待后面同步。

    • 第三阶段主服务器发送新的写操作命令给从服务器

      当从服务器载入RDB文件完成后,会发送一个确认消息给主服务器;

      主服务器会将在**replication buffer**新增的一些写操作命令同步给从服务器,从服务器执行这些命令,从而实现主从服务器的数据一致性。

      至此,第一次同步完成。

  • 提供服务期间:基于长连接的命令传播

    第一次同步完成后,主服务器和从服务器之间会维护它们所建立的TCP连接,形成一个长连接。后续主服务器在收到写操作命令时,会通过这个连接将该命令传播给从服务器执行,保持数据的一致性。这个过程被称为**基于长连接的命令传播**,通过这种方式来保证第一次同步后的主从服务器的数据一致性。

  • 出现网络断连:增量复制

    如果主从服务器之间的网络连接断开了,则无法进行命令传播,导致数据不一致,客户端可能从「从服务器」读到旧的数据当网络恢复时,该如何保证主从服务器的数据一致性?

    Redis通过**增量复制**的方式继续同步,只会把网络断开期间主服务器接收到的写操作命令,同步给从服务器。

    主服务器怎么知道要将哪些增量数据发送给从服务器呢?

    主服务器中维护了一个「环形」缓冲区**repl_backlog_buffer**,主服务器在进程命令传播时,还会将这些命令写入到这个缓冲区中,因此这个缓冲区里会保存着最近传播的写命令。

    另外,主服务器和从服务器都维护了一个标记同步进度的偏移量offset(master_repl_offsetslave_repl_offset),当网络重连时,从服务器会将自己的偏移量slave_repl_offset复制给主服务器,由主服务器决定需要如何同步:

    • 如果判断出从服务器要读取的数据还在 repl_backlog_buffer 缓冲区里,那么主服务器将采用**增量同步**的方式;
    • 相反,如果判断出从服务器要读取的数据已经不存在 repl_backlog_buffer 缓冲区里,那么主服务器将采用**全量同步**的方式。

    增量同步具体是怎么做的?

    主服务器在 repl_backlog_buffer 中找到主从服务器差异(增量)的数据后,就会将增量的数据写入到 replication buffer 缓冲区,然后经过命令传播同步给从服务器。

5.2.3 如何分担主服务器的压力?

主服务器在第一次数据同步时会有两个耗时的操作:生成RDB快照传输RDB文件

如果从服务器非常多,且每个都需要主服务器进行全量同步的话,会带来一些问题:

  • 主服务器忙于fork()创建子进程来生成RDB,导致无法正常处理请求;
  • 传输RDB文件占用了大量网络贷款,对主服务器的接收请求造成影响。

Redis为了解决这个问题,让从服务器也可以有自己的从服务器,从服务器当作**“经理”**的角色,与它的从服务器的数据同步都是由这个“经理”完成的,而不需要主服务器参与,缓解主服务器的压力。

通过这种方式,主服务器生成 RDB 和传输 RDB 的压力可以分摊到充当经理角色的从服务器

5.3 哨兵机制

5.3.1 为什么需要哨兵机制?

在 Redis 的主从架构中,由于主从模式是读写分离的,如果**主节点(master)挂了,那么将没有主节点来服务客户端的写操作请求,也没有主节点给从节点(slave)进行数据同步了,即十分依赖主节点。需要人工介入**将一个「从节点」切换为「主节点」,然后让其他从节点指向新的主节点,同时还需要通知上游那些连接 Redis 主节点的客户端,将其配置中的主节点 IP 地址更新为「新主节点」的 IP 地址。

Redis 2.8版本以后提供了**哨兵(Sentinel)机制,作用是实现主从节点故障转移,会监测主节点是否存活,如果发现主节点挂了,它就会选举一个从节点切换为主节点,并且把新主节点的相关信息通知给从节点和客户端**。

类似Raft算法中领导者选举的方式

5.3.2 哨兵机制是如何工作的?

哨兵本身也是一个(服务器)节点,和主节点、从节点类似,但是它是一种特殊的”观察者节点“,观察的对象就是主从节点。

哨兵节点负责三件事情:监控、选主、通知

所以,哨兵机制的工作内容主要有:

  • 如何**监控**节点?如何判断主节点是否真的故障了?
  • 根据什么规则选择一个**从节点切换为主节点**?
  • 怎么把新主节点的相关信息**通知**给从节点和客户端?
5.3.3 如何监控节点? —— 心跳机制

哨兵会每隔 1 秒给所有主从节点发送 PING 命令,当主从节点收到 PING 命令后,会发送一个响应命令给哨兵,即可判断它们是否在正常运行。(心跳机制)

如果主节点或者从节点没有在规定的时间内响应哨兵的 PING 命令,哨兵就会将它们标记为主观下线

5.3.4 如何判断主节点是否真的故障了?

当标记了主观下线,有可能主节点其实没有故障,而只是因为主节点的系统压力比较大导致网络阻塞,所以才没有在规定时间内响应哨兵的PING命令。因此,针对主节点,哨兵机制设置了客观下线状态。

一般来说,为了减少误判,一般会用多个节点部署成**哨兵集群**(最少需要三台机器来部署哨兵集群),通过多个哨兵节点一起判断,就可以就可以避免单个哨兵因为自身网络状况不好,而误判主节点下线的情况

如何判断主节点为「客观下线」呢?

当一个哨兵判断主节点为「主观下线」后,就会向其他哨兵发起命令。其他哨兵节点收到这个命令,会根据自身和主节点的网络状况,做出赞成投票或拒绝投票的响应。当这个哨兵的**赞同票数达到哨兵配置文件中的 quorum 配置项设定的值后,这时主节点就会被该哨兵标记为「客观下线」**。

PS:quorum 的值一般设置为哨兵个数的二分之一加 1,例如 3 个哨兵就设置 2。(超过半数)

哨兵判断完主节点客观下线后,哨兵就要开始在多个「从节点」中,选出一个从节点来做新主节点。

5.3.5 由哪个哨兵进行主从故障转移? —— 领导者选举

当主节点客观下线后,需要哨兵从从节点中选出一个新的主节点,由于有多个哨兵节点,应该**让哪个哨兵节点负责呢?**

哨兵集群中通过**「领导者选举」来选出一个哨兵节点作为Leader,让Leader进行主从切换。一般来说,哪个哨兵节点判断主节点为「客观下线」,这个哨兵节点就是候选者,所谓的候选者就是想当 Leader 的哨兵。候选者会向其他哨兵发送命令**,表明希望成为 Leader 来执行主从切换,并让所有其他哨兵对它进行投票。

每个哨兵只有一次投票机会,如果用完后就不能参与投票了,可以投给自己或投给别人,但是只有候选者才能把票投给自己。任何一个「候选者」,要满足两个条件则会成为Leader:

  • 第一,拿到半数以上的赞成票;
  • 第二,拿到的票数同时还需要大于等于哨兵配置文件中的 quorum 值。

所以,为了保证Leader选举顺利,至少需要3个哨兵节点,quorum 的值建议设置为哨兵个数的二分之一加 1,例如 3 个哨兵就设置 2,5 个哨兵设置为 3,而且哨兵节点的数量应该是奇数

5.3.6 主从故障转移的过程是怎样的?

在哨兵集群中通过投票的方式,选举出了哨兵 leader 后,就可以进行主从故障转移的过程了

在这里插入图片描述

主从故障转移操作包含以下四个步骤:

  • 第一步:在已下线主节点(旧主节点)属下的所有「从节点」里面,挑选出一个从节点,并将其转换为**「新主节点」**;

    (1)将网络状态不好的从节点过滤掉;

    (2)第一轮考察:节点的优先级(显式的根据每个节点的性能配置的);

    (2)第二轮考察:复制进度最靠前的节点;

    (3)第三轮考察:ID号更小的节点;

  • 第二步:让已下线主节点属下的所有「从节点」修改复制目标为**「新主节点」**;

    哨兵 leader 向所有从节点发送 SLAVEOF ,让它们成为新主节点的从节点:

  • 第三步:将「新主节点」的IP地址和信息,通过「发布者/订阅者机制」通知给客户端;

    **通过 Redis 的发布者/订阅者机制来实现**的。每个哨兵节点提供发布者/订阅者机制,客户端可以从哨兵订阅消息。哨兵提供的消息订阅频道有很多,不同频道包含了主从节点切换过程中的不同关键事件,几个常见的事件如下:

  • 第四步:继续监视旧主节点,当其重新上线时,将它设置为新主节点的从节点;

5.3.7 哨兵集群是如果组成的?

前面提到了Redis中的哨兵机制是通过一个哨兵集群(多个哨兵节点)组成的,那是如何组成哨兵集群的,它们之间是如何感知对方的?

哨兵节点之间是通过 Redis 的发布者/订阅者机制来相互发现的,主节点中有一个名为__sentinel__:hello的频道,不同的哨兵就是通过这个频道来相互发现和互相通信的。如下图所示,哨兵 A 把自己的 IP 地址和端口的信息发布到__sentinel__:hello 频道上,哨兵 B 和 C 订阅了该频道。那么此时,哨兵 B 和 C 就可以从这个频道直接获取哨兵 A 的 IP 地址和端口号。然后,哨兵 B、C 可以和哨兵 A 建立网络连接。

哨兵节点之间是通过向主节点发送INFO命令来获取所有「从节点」的信息,哨兵节点需要监视所有的节点,但是它并不知道从节点的信息,所以哨兵会**每隔10秒**向主节点来获取从节点的信息。

5.4 切片集群模式

5.4.1 为什么需要切片集群模式?

Redis用作缓存时,如果缓存数据量很大,无法在一台服务器上缓存,需要使用**Redis切片集群**(Redis Cluster ),数据可以分布在不同的服务器上,降低系统对单主节点的依赖。

5.4.2 切片集群是如何实现的?

对于切片集群,最重要的问题就是决定**一个缓存数据要放到哪一台服务器上。Redis Cluster 采用哈希槽(Hash Slot),来处理数据和节点之间的映射关系。在 Redis Cluster 方案中,一个切片集群共有 16384 个哈希槽**,每个数据(键值对)都会根据它的key,被映射到一个哈希槽中:

  • 根据key,使用**CRC16**算法计算一个16 bit的值;
  • 将这个16 bit的值对16384取模,得到一个0~16383之间的数,这个数就代表着哈希槽的编号。

然后,需要将这些哈希槽映射到各个Redis节点中,有两种映射方案:

  • 平均分配:使用 cluster create 命令创建 Redis 集群时,Redis会自动把所有哈希槽平均分布到集群节点上。比如集群中有 9 个节点,则每个节点上槽的个数为 16384/9 个。
  • 手动分配:使用 cluster meet 命令手动建立节点间的连接,组成集群,再使用 cluster addslots 命令,指定每个节点上的哈希槽个数。需要把 16384 个槽都分配完,否则 Redis 集群无法正常工作。

5.5 集群脑裂导致数据丢失怎么办?

5.5.1 集群脑裂是怎么出现的,如何导致数据丢失?

脑裂:是指的一个集群有多个主节点。

Redis的主从架构中,主节点提供写操作,从节点提供读操作。如果主节点由于网络问题与其他从节点失联,但是与客户端之间网络正常。此时,客户端新发送的写请求操作会被主节点存放到缓存区中。

哨兵发现了主节点失联,判断为客观下线后会在集群内布重新选择一个主节点,这时集群就有两个主节点了 — 脑裂出现了

如果此时网络恢复,由于在集群中,「旧主节点」已经被降级成为了从节点,所以「旧主节点」会向「新主节点」申请数据同步,并清空该节点中的数据。这样就会**导致断联期间客户端的一些写入的数据丢失,这就是集群产生脑裂数据丢失的问题。**

5.5.2 该如何解决?

Redis使用的策略是:当主节点发现从节点的连接数量少于某个阈值或者主从数据复制和同步的延迟超过了某个阈值,就会禁止主节点进行写入操作,直接返回错误给客户端。

即:主库连接的从库中至少有 N 个从库,和主库进行数据复制时的 ACK 消息延迟不能超过 T 秒,否则,主库就不会再接收客户端的写请求了。

资料参考

内容大多参考自:图解Redis介绍 | 小林coding (xiaolincoding.com)

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

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

相关文章

C#使用NPOI进行Excel和Word文件处理(一)

文章目录 前言文件大小性能NPOI 的优势示例代码性能优化建议总结Github 地址链接导出效果 前言 NPOI 是一个非常流行的用于在 .NET 环境中操作 Office 文件&#xff08;包括 Excel 文件&#xff09;的开源库。它的功能非常强大&#xff0c;但性能和文件大小问题可能因具体的使…

“八股文”面试题:是招聘程序员的金科玉律?

引言 随着互联网的发展&#xff0c;现代企业对程序员的需求日益增加。在招聘过程中&#xff0c;许多公司采用了“八股文”式的面试题目来筛选候选人。这些题目往往涵盖了算法、数据结构、系统设计等方面的基础知识。然而&#xff0c;对于“八股文”在实际工作中的作用&#xf…

安泰高压放大器在材料极化中的应用有哪些

高压放大器在材料极化中具有重要的应用&#xff0c;这方面是通过在材料中施加高电压来实现的。下面我们将探讨高压放大器在材料极化领域的具体应用&#xff0c;以及其在材料科学和工程中的重要性。 首先&#xff0c;让我们了解一下材料极化的基本概念。材料的极化是指在外加电场…

气象水文耦合模式WRF-Hydro安装、数据制备、代码编译、离线在线运行

目录 专题一 WRF-Hydro模型功能及运行流程、依赖库准备 专题二 WRF-Hydro模式编译、离线运行及案例实践 专题三 结合多案例进行模式数据制备及实践应用 专题四 WRF-Hydro模式耦合编译及运行、总结 更多应用 WRF-Hydro模型是一个分布式水文模型&#xff0c;‌它基于WRF‌陆…

视角 | 麻省理工学院提出出温度计校准法,专治AI大模型过度自信

在数字化浪潮的推动下&#xff0c;人工智能&#xff08;AI&#xff09;正成为塑造未来的关键力量。硅纪元视角栏目紧跟AI科技的最新发展&#xff0c;捕捉行业动态&#xff1b;提供深入的新闻解读&#xff0c;助您洞悉技术背后的逻辑&#xff1b;汇聚行业专家的见解&#xff0c;…

使用Python自动将照片文件夹转换为PowerPoint幻灯片

在这个数字时代,我们经常需要快速创建照片幻灯片来展示我们的回忆或工作成果。今天,我们将探讨如何使用Python来自动化这个过程,将一个文件夹中的所有照片转换为一个精美的PowerPoint演示文稿,每张照片占据一页,并以文件名作为标题。 C:\pythoncode\new\jpeginsertppt.py 全部…

【Python 逆向滑块】(实战二)逆向滑块,并实现用Python+Node.js 生成滑块、识别滑块、验证滑块、发送短信

逆向日期&#xff1a;2024.07.31 使用工具&#xff1a;Node.js、油猴 本章知识&#xff1a;逆向网易易盾【fp】参数 文章难度&#xff1a;中等&#xff08;没耐心的请离开&#xff09; 文章全程已做去敏处理&#xff01;&#xff01;&#xff01; 【需要做的可联系我】 AES解…

配电盘emc测试技术咨询

申请配电盘 EMC 测试技术咨询的费用因机构、测试项目和服务内容的不同而有所差异。一般来说&#xff0c;测试机构会根据测试项目的复杂程度、测试时间和场地等因素来确定费用。 影响配电盘 EMC 测试技术咨询办理费用的因素有很多&#xff0c;其中主要的因素有&#xff1a; 1、检…

windows 环境测试使用 Visual Studio 2022 MSVC 自带的 cl + nmake 版本的 Makefile 编译代码

前言&#xff1a; windows 环境的 cl 和 nmake 就相当于 Linux 环境的 gcc、g 和 make&#xff1b;linux 中可以在 Makefile 中写 gcc、g 语句&#xff0c;然后执行 make&#xff1b;同样的&#xff0c;在 windows中也可以新建 Makefile 文件&#xff0c;在里面写 cl 语句&…

基于springboot+vue+uniapp的养老院管理系统小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

45.二维数组练习:计算季度营业额和年总营业额

/* 某商场每个季度营业额如下,单位&#xff1a;万元 第一季度&#xff1a;22&#xff0c;66&#xff0c;44 第二季度&#xff1a;77&#xff0c;33&#xff0c;88 第三季度&#xff1a;25&#xff0c;45&#xff0c;65 第四季度&#xff1a;11&#xff0c;66&#xff0c;99 要求…

贵州桐梓影像大赛启动 百名摄影师齐聚桐梓采风创作

夏季的桐梓&#xff0c;山水秀美&#xff0c;天空湛蓝。近日&#xff0c;贵州桐梓首届旅游影像大赛启动&#xff0c;来自全省各地的100余名摄影师共聚一堂&#xff0c;开展一场别具一格的采风创作活动。他们带着镜头&#xff0c;追寻着光影的脚步&#xff0c;捕捉桐梓的自然风光…

使用WebSocket实现log日志流的实时展示-从轮询到通知

场景介绍 最近开发一个系统&#xff0c;其中一个模块需要展示实时的执行过程&#xff0c;过程日志可能比较多。以前的方案都是前端定时轮询&#xff0c;比如每秒查一次后端接口&#xff0c;将拉取回来的日志重新展示。轮询方案简单容易实现&#xff0c;但是比较消耗资源&#…

ctfhub-SQL注入-1-基础题目详解

1.打开题目在url上判断是数字型注入还是字符型注入 1 //无回显&#xff0c;说明是报错了&#xff0c;‘和后面的‘冲突了 1’ -- //有回显&#xff0c;是因为--把后面的‘注释掉了 2.使用命令判断列数 1order by 1-- //有回显 1order by 2 -- //有回显 1order by …

推荐Nodejs下高效存储树到数据库工具库-FlexTree

官网 | English FlexTree是Nodejs下一个基于左右值算法的树结构库&#xff0c;它提供了一种简单的方式来存储和操作树形结构数据。 FlexTree提供了简单而丰富的API让你可以轻松的操作树&#xff0c;如增删改查、遍历、移动、查询等。 主要特性&#xff1a; 基于左右值算法&a…

AMEYA360:纳芯微高集成单芯片SoC如何高效智能控制车载步进电机?

随着现代汽车电子技术的快速发展&#xff0c;步进电机作为一种精确且可靠的执行元件&#xff0c;在汽车电子系统中的应用日益广泛。为了实现车载步进电机应用的精确控制&#xff0c;纳芯微推出了集成LIN和MOSFET功率级的单芯片车用小电机驱动SoC——NSUC1610&#xff0c;可以帮…

全面掌握VS Code:提升开发效率的终极指南

Visual SCode Visual Studio Code&#xff08;简称VS Code&#xff09;是一款由微软开发的免费、开源且跨平台的代码编辑器。它支持多种编程语言&#xff0c;通过其强大的扩展库&#xff0c;可以满足各种开发需求。本教程将详细介绍如何从安装到高级使用&#xff0c;帮助你充分…

降低Anki对C盘空间占用的四种方法

Anki安装后&#xff0c;笔记中所用到的各种媒体和资源文件默认保存在C盘&#xff0c;例如我的电脑上是保存在“C:\Users\asus\AppData\Roaming\Anki2”&#xff0c;其中asus是我电脑的登录用户名。随着笔记收集越来越多&#xff0c;对C盘的占用也越来越大&#xff0c;因此&…

5问5答!您想了解的数据采集DAQ关键指标都在这里了

1、什么是采样率&#xff0c;它对测量结果有何影响&#xff1f; 采样率是数据采集卡每秒采集数据的次数。采样率对测量结果的准确性有直接影响。如果采样率过低&#xff0c;可能会错过信号的重要部分&#xff0c;导致数据失真。 理论上根据采样定理&#xff0c;采样率应为信…

【C++BFS】802. 找到最终的安全状态

本文涉及知识点 CBFS算法 LeetCode802. 找到最终的安全状态 有一个有 n 个节点的有向图&#xff0c;节点按 0 到 n - 1 编号。图由一个 索引从 0 开始 的 2D 整数数组 graph表示&#xff0c; graph[i]是与节点 i 相邻的节点的整数数组&#xff0c;这意味着从节点 i 到 graph…