Redis 的集群模式实现高可用
来源:Redis高可用:武林秘籍存在集群里,那稳了~ (qq.com)
1. 引言
前面我们已经聊过 Redis 的主从同步(复制)和哨兵机制,这期我们来聊 Redis 的集群模式。
但是在超大规模的互联网应用中,业务规模不断扩展,用户量持续增多时,原有的主从+哨兵机制已经不满足我们的需求了。如:性能问题,数据量过多、并发量过高导致 Redis 服务器响应太慢。
1.1 自古功夫出少林
如果把 Redis 比作江湖里的门派,少林寺作为武林中最有威望的名门正派,提供了武功秘籍(缓存数据)的存储服务。
由于少林存储的可用性做的很好,武功秘籍几乎不会丢失。而且,每次去获取武林同道的秘籍时,响应也很快,所以少林威望不断提升,后得千古美誉:“自古功夫出少林”。
少林的武功秘籍存储方案为什么这么稳定呢?
这得从头说起。
1.2 累坏的掌门人
在武林大会 3.0 之前,已经有很多武林同道在少林寺存取武功秘籍了,而少林掌门作为权力的中心,不仅披星戴月和外宾打交道(Client 请求),还得在管理物资之余(数据存储和输出)给副掌门做业务培训(数据备份)。
虽然在武林大会 2.8 时,少林和武当一样,已经新增了哨兵部门,从此不用担心掌门嗝屁的问题。
详见上一篇文章:深入浅出Redis高可用:哨兵机制
但掌门人日理万机,应接不暇,还是把头发都愁掉了!
为了掩饰尴尬,从此少林弟子不准留头发 🐶
这时可能有小伙伴产生疑问了,性能不好,那就加 CPU、加内存或者网络带宽呗?!
只能说太天真!当数据量增大、并发增高时,一味地增加 Redis 服务器的CPU、内存和网络带宽,往往不能起到很好的优化效果。
毕竟,服务器也和人的体能极限一样,不是吃得越多,就可以干活越快的。
而纵向扩展不管用,我们就只能考虑横向扩展了:团结就是力量,一个人忙不过来,那就再来十个。
于是乎,今天的主角——Redis 集群模式应时而生。
2. 集群模式:分权
Redis3.0 之后,加入了 Redis 集群模式,即 Redis Cluster:可以自动在多个节点上分布数据,节点间的数据能共享,也能动态地调整数据分布。
2.1 集群架构
Redis 集群采用去中心化的思想,没有中心节点的说法。
对于客户端来说,整个集群可以看成是一个整体,可以连接任意的节点进行数据操作,就像操作单实例 Redis 一样,也不需要任何的代理中间件。
少林掌门:帮手来了,不用一个人掉头发了!
最重要的是,Redis 集群具有高可用性,支持多个 master 节点,每个 master 节点都可以挂载多个 slave 节点,当 master 节点挂掉以后,集群会选出一个新的 master 节点。
自武林大会 3.0 以来,少林为了解决事务变多,掌门人疲于应对的问题,引入了多掌门模式:每个掌门平级,共同处理门派事务,也可以发展自己的副掌门,以作平替。
当有新的外宾访问时,会首先通过少林寺通信部(Client)来将请求转发给各掌门,再分别处理。
相当于一个人的活可以数以千计个人一起干,不得不说,这很强!
那这个过程是如何建立起来的呢?
2.2 集群组建
首先,少林会选出多个掌门人(根据武林秘籍的数量决定),然后找一个掌门人负责集群组建的主持工作。
武林规定,一个门派不超过 1000 个掌门人:master 节点个数尽量在 1000 个以下
假设我们用三个 master 节点作为集群成员,它们的建连过程如下图所示:
为了提升工作效率,掌门人之间需要加群方便沟通,在 Redis 中,master1 可以向 master2 节点发送以下命令建连:
CLUSTER MEET 127.0.0.2 6379
当 master2 节点回复响应时,一个 Redis Cluster 便组建成功了。
群聊组建成功后,掌门人们便开始各自管理事务。但少林存放的武林秘籍这么多,每个掌门该如何分配管理呢?
2.3 集群数据分片
在少林里,有专门的算法机制以及秘籍库来管理武林秘籍。
首先:将每本武功秘籍都赋予一个唯一标识,并将唯一标识分类后放到不同的秘籍库,然后交由不同的掌门人进行管理。
其中:算法机制用的是 CRC16,秘籍库有 16384 个
结合集群中各 master 节点的交互包大小、节点数量的最大值来考量:Redis 官方将集群中所有的数据划分到 16384(2 的 14 次方)个哈希槽(slots)里面,每个 master 节点管理一部分 slot。
当 master 节点数为 N 时,每个节点的哈希槽(slot)个数为 16384/N 个,基本保证均匀分布。
当然,这是可以人为控制的,如果某个节点的性能较好,就可以多分配一些 slot。命令如下:
redis-cli -h 127.0.0.1 -p 6379 cluster addslots 0, 5460
能者多劳,这在掌门人之间也达成了共识。
2.4 数据存取流程
我们知道,江湖中每天都会新增不可计数的武林秘籍,而少林要求这些武林秘籍都有一个唯一标识 key,真实的秘籍信息存放在 value 里面。
少林会根据 key 的不同,将它们归为不同的秘籍库,然后再根据秘籍库的编号,让不同的掌门人分属管理。
当对秘籍进行存取时,少林通信部会使用 CRC16 算法对秘籍 key 进行计算并对 16384 取模,得到的结果就是这个武功秘籍存放的秘籍库 slot:
slot = CRC16(key)% 16384
然后,通信部会根据掌门人群组返回的 {slot,Redis实例IP} 映射表,通过秘籍库 ID 去找到对应的掌门人住址,最后向此掌门人存储或索要 key 对应的武功秘籍 value。
3. 集群的扩容与访问
这时,有聪明的武林同道发现了问题:既然秘籍库的数量是固定的 16384,当少林寺新增掌门人时,岂不是没有秘籍库可以管理了?
这个问题很好,当哈希 slot 已经被分配完毕,并已经存储数据时,如果后续在线上需要新增 master 节点,那新增的哈希 slot 从哪里来呢?
既然蛋糕不会变大,那只能把现有的蛋糕分出来了。
怎么分?那当然是一人分一点出来!大家都不愿意吃亏,所以分出来的地盘尽可能相同。
3.1 数据迁移:一人分一点
当少林寺宣布要新增一个四掌门时,大家纷纷开始工作。
首先,三个掌门首先会划出一部分秘籍库出来,准备移交到四掌门管辖。
确定好迁移的秘籍库后,通信部会做以下几件事:
- 对目标节点(即四掌门:127.0.0.4: 6385)发送 cluster setslot {slot} importing 127.0.0.4 命令,让目标节点准备导入槽数据;
- 对源节点(大掌门、二掌门、三掌门 3 个节点)发送 cluster setslot {slot} migrating 127.0.0.4 命令,让源节点准备迁出槽数据;
- 源节点上循环执行 cluster getkeysinslot {slot} {count} 命令,获取 count 个数据槽 {slot} 的 key;
- 在源节点上执行 migrate 127.0.0.1 6379 key 0 {timeout} 命令将指定的 key 进行迁移。
重复 3,4 步骤直到槽下所有的键值数据迁移到目标节点。
当迁移结束后,向集群中所有的主节点发送通知,slot 集合已经分配给了目标节点。
3.2 数据访问:秘籍怎么取
上面我们已经说过了,在少林寺存储的武林秘籍由各掌门共同处理。那么,当外宾想要获取存储的秘籍时,该如何获取呢?
如上图所示,当 Client 首次访问 Redis 时,会经过三个步骤:
- 客户端(Client)连接某个实例,获取到 slots 和实例节点的映射关系,并将这个映射关系存储在本地缓存;
- 将需要存取的 key 经过 CRC16 计算后,再用 16384 对其取模,获取 slot 的值;
- 根据映射表得到 slot 对应的实例,将 key 存取的请求发送到这个实例上进行操作。
正常访问是这个流程,但如果新增节点后,key 对应的 slot 被迁移了怎么办呢?
3.3 slot已迁移,秘籍找谁要
当通信部第一次访问秘籍 key1 时,计算得出 slot(key1) = 5000,然后被掌门人群组告知:这个 slot 5000 对应的武功秘籍存放在大掌门那里,于是通信部将 {slot=5000, 大掌门} 这个映射信息存了下来。
但是,当客户端第二次访问 key1 时,slot 5000 已经被大掌门分给了四掌门,由于秘籍迁移的过程需要一定的时间,所以分两种情况讨论:
- 如果 slot 迁移已经结束,就会出现 MOVED 重定向,代表数据已经转移了;
- 如果 slot 正在迁移,就会出现 ASK 重定向,代表不确定该 key 是否迁移完成,需要通信部去四掌门那里问一下。
当请求的 slot 发生迁移时,redis-cluster 交互时序图如下:
首先,通信部成员根据 slot 5000 和武功秘籍的唯一标识 key1 屁颠屁颠去找大掌门索要武功秘籍,但是大掌门说:这个 key1 对应的武功秘籍找不到,我这会在做秘籍迁移呢,我先看下 slot 5000 秘籍库的钥匙有没有在我这里吧:
- 钥匙还在,说明迁移正在进行,则 key1 可能在四掌门那里,你去他那里问下。然后大掌门甩给了通信部成员一个 ASK 重定向异常。
- 钥匙已经不在了,秘籍库在老四那里,你直接找他吧,并甩给通信部成员一个 MOVED 重定向异常。
客户端收到 Cluster 返回的异常后判断:
- 如果是 ASK 异常,则发送 ASK 命令到 master4 节点建连,再执行 key 命令:如果存在则执行返回数据,不存在则返回不存在信息;
- 如果是 MOVED 异常,客户端会直接去 master4 请求 key 数据,并更新本地缓存,后续访问同一个 key 的数据都去请求 master4 节点 。
这时,有小伙伴要问了:都是重定向,MOVED 和 ASK 有什么实质性区别吗?
其实,和 HTTP 请求里的重定向 301、302 类似,MOVED 和 ASK 就是永久重定向和临时重定向的区别,分别代表 key 已迁移和不确定 key 已迁移的异常状态。
4. 小结
当业务规模不断扩展,用户量和并发量都很大时,用主从复制+哨兵机制来支撑 Redis 的高可用还是不能解决单机主实例的性能问题:比如数据响应太慢。
同时,在面对千万级甚至亿万级的数据流量时,利用分治法来进行实例扩展尤为重要。
而 Redis 集群,不仅原生支持了主从复制,每个主节点都用备用节点,而且还支持哨兵机制,当某个主节点宕机时,Cluster 会自动将对应的 Slave 节点选为 Master,以实现故障转移。
相关文章:

Redis 的集群模式实现高可用
来源:Redis高可用:武林秘籍存在集群里,那稳了~ (qq.com) 1. 引言 前面我们已经聊过 Redis 的主从同步(复制)和哨兵机制,这期我们来聊 Redis 的集群模式。 但是在超大规模的互联网应用中,业务规…...
21、嵌套路由实战操作
1、创建内嵌子路由,你需要添加一个vue文件,同时添加一个与该文件同名的目录用来存放子视图组件。 2、在父组件(.vue)内增加用于显示子视图内容 新建文件 pages\index_id.vue 生成的对应路由 {path: "/",component: _…...
WPF 控件的缩放和移动
WPF 控件的缩放和移动 1.页面代码 <ContentControl ClipToBounds"True" Cursor"SizeAll"><Viewboxx:Name"viewbox"MouseDown"viewbox_MouseDown"MouseMove"viewbox_MouseMove"MouseWheel"Viewbox_MouseWhee…...
Python and和or的优先级实例比较
Python and和or的优先级 and和or都是Python的逻辑运算符,都为保留字。通常情况下,在没有括号影响,and和or的优先级中and在代码的逻辑运算过程中会相对优先一些,及在同一行的Python代码中,and会优先与or执行。下面将通…...

数据结构与算法编程题2
逆置线性表,使空间复杂度为 O(1) #include <iostream> using namespace std;typedef int ElemType; #define Maxsize 100 #define OK 1 #define ERROR 0 typedef struct SqList {ElemType data[Maxsize];int length; }SqList;void Init_SqList(SqList& …...
Java开发者的Python快速进修指南:控制之if-else和循环技巧
简单介绍 在我们今天的学习中,让我们简要了解一下Python的控制流程。考虑到我们作为有着丰富Java开发经验的程序员,我们将跳过一些基础概念,如变量和数据类型。如果遇到不熟悉的内容,可以随时查阅文档。但在编写程序或逻辑时&…...

二进制部署k8s集群-过程中的问题总结(接上篇的部署)
1、kube-apiserver部署过程中的问题 kube-apiserver.conf配置文件更改 2、calico的下载地址 curl https://docs.projectcalico.org/v3.20/manifests/calico.yaml -O 这里如果kubernetes的节点服务器为多网卡配置会产生报错 修改calino.yaml配置文件 解决方法: 调…...
IOS 关于CoreText的笔记
放大 一.CoreText计算attributeString显示所占区域 百度搜索有三种方法: 1.方法 - (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options context:(nullable NSStringDrawingContext *)context 2.使用CTFrameRef 的 CTFrameGetLin…...

基础课6——开放领域对话系统架构
开放领域对话系统是指针对非特定领域或行业的对话系统,它可以与用户进行自由的对话,不受特定领域或行业的知识和规则的限制。开放领域对话系统需要具备更广泛的语言理解和生成能力,以便与用户进行自然、流畅的对话。 与垂直领域对话系统相比…...
Hive常见的面试题(十二道)
Hive 1. Hive SQL 的执行流程 ⾸先客户端通过shell或者Beeline等⽅式向Hive提交SQL语句,之后sql在driver中经过 解析器(SQL Parser):将 SQL 字符串转换成抽象语法树 AST,这一步一般都用第三方工具库完成,比如 ANTLR&…...
1688商品详情API跨境专用接口php java
一、引言 随着全球电子商务的快速发展,跨境电子商务已经成为一种重要的国际贸易形式。1688作为全球最大的B2B电子商务平台之一,不仅拥有大量的商品资源,还为商家提供了丰富的API接口,以实现更高效、更便捷的电子商务活动。其中&a…...
h264流播放
参考文章: Android MediaCodec硬解码H264文件-CSDN博客...

02-1解析xpath
我是在edge浏览器中安装的xpath,需要安装的朋友可以参考下面这篇博客最新版edge浏览器中安装xpath插件 一、xpathd的使用 安装lxml pip install lxml ‐i https://pypi.douban.com/simple导入lxml.etree from lxml import etreeetree.parse() 解析本地文件 htm…...
Python算法——树的镜像
Python中的树的镜像算法详解 树的镜像是指将树的每个节点的左右子树交换,得到一棵新的树。在本文中,我们将深入讨论如何实现树的镜像算法,提供Python代码实现,并详细说明算法的原理和步骤。 树的镜像算法 树的镜像可以通过递归…...

ModStartCMS v7.6.0 CMS备份恢复优化,主题开发文档更新
ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用,支持后台一键快速安装,让开发者能快的实现业务功能开发。 系统完全开源,基于 Apache 2.0 开源协议,免费且不限制商业使用。 功能特性 丰富的模块市…...

vscode 推送本地新项目到gitee
一、gitee新建仓库 1、填好相关信息后点击创建 2、创建完成后复制 https,稍后要将本地项目与此关联 3、选择添加远程存储库 4、输入仓库地址,选择从URL添加远程存储仓库 5、输入仓库名称,确保仓库名一致...
C++函数指针变量
#include <iostream> using namespace std;void MyFun(int x){cout << x << endl; }//函数指针的声明 void (*FunP) (int);/*** MyFun的函数名与FunP函数指针都是一样的,即都是函数指针* MyFun函数名是一个“函数指针常量”* FunP是一个“函数指针…...

各类语言真实性能比较列表
这篇文章是我所做或将要做的所有真实世界性能比较的索引。如果你对想要看到的其他真实世界案例有建议,请在评论中添加。 用例 1 — JWT 验证 & MySQL 查询 该用例包括: 从授权头部获取 JWT验证 JWT 并从声明中获取电子邮件使用电子邮件执行 MySQL…...

华为笔记本MateBook D 14 2021款锐龙版R7集显非触屏(NbM-WFP9)原装出厂Windows10-20H2系统
链接:https://pan.baidu.com/s/13Kyy95GME-asli4woNN_ww?pwdbqa8 提取码:bqa8 HUAWEI华为MateBookD14原厂Win10系统自带所有驱动、出厂主题壁纸、系统属性专属LOGO标志、Office办公软件、华为电脑管家等预装程序...

Springboot 对于数据库字段加密方案(此方案是对字符串处理的方案)
背景:在erp开发中,有些用户比较敏感数据库里的数据比较敏感,系统给用户部署后,公司也不想让任何人看到数据,所以就有了数据库字段加密方案。 技术 spring boot mybatisplus 3.3.1 mybatisplus 实际提供了 字段加密方案 第一 他…...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
Unit 1 深度强化学习简介
Deep RL Course ——Unit 1 Introduction 从理论和实践层面深入学习深度强化学习。学会使用知名的深度强化学习库,例如 Stable Baselines3、RL Baselines3 Zoo、Sample Factory 和 CleanRL。在独特的环境中训练智能体,比如 SnowballFight、Huggy the Do…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...