深入浅出Redis(八):Redis的集群模式

news2024/11/20 13:22:03

引言

Redis是一款优秀的键值对、内存非关系型数据库,单机节点下的Redis存在无法保证高可用、容量不足等问题

上篇文章介绍的哨兵主要能够保证主从架构下Redis的可用性,但是仍然存在容量不足、推举新的主节点时不能访问Redis的问题,集群可水平扩展的功能解决容量不足的问题并且能够保证高可用

本篇文章将围绕Redis集群深入浅出的介绍集群的原理、如何使用集群、使用集群需要注意的地方,理解集群是如何支持水平扩展的以及如何保证高可用

学习本篇文章内容之前,需要了解持久化以及主从复制的机制

集群原理

分片

Redis集群将数据空间分为16384个哈希槽slots,分布到各个主节点中,集群中的每个主节点负责一部分的哈希槽

需要注意的是使用集群后每个主节点只有一个数据库(单机节点情况下是可以设置多个数据库的)

image.png

当客户端对key进行读写时,通过CRC16校验后对16384取模来决定出Key所在槽【哈希槽 =CRC16(key) % 16384】,然后在去管理这个槽的主节点中读/写Key(各个redis节点之间通信保存这些槽编号信息)

主从--高可用

每个主节点管理部分的哈希槽,如果主节点发生宕机则这部分槽相关的数据就不可用了

为了提供可用性,需要有从节点来冗余数据保证可用性,因此可以把集群cluster理解成包含多个主从架构,每个主从架构负责管理一部分的哈希槽

主节点间互相发送消息维持心跳的同时交换信息,当节点发现某节点不响应时(可能下线),广播给其他主节点,其他主节点收到后与不响应的节点通信,当大多数主节点接收不到时(确认下线),广播信息给这个节点的所有从节点,从节点收到后根据raft算法推选新主节点

raft推举算法:

  1. 从节点收到后推举自己为新主节点广播给其他从节点
  2. 其他节点接到后,如果该节点还在自转则会投票给它,如果该节点已经推举别的节点了就不会响应
  3. 收到推举票后如果超过一定数量则成为新主节点,如果最高票相等则重复步骤1

还不熟悉的同学可以观看动画:raft算法动态展示

集群中默认情况下使用异步复制数据,即主节点处理客户端写命令时,并不等待从节点同步数据再响应,性能与强一致性不兼得

重定向

当使用命令行进入某主节点中请求写命令,该写命令可能所在的槽并不是当前主节点的,主节点会响应MOVED指令告诉该Key应该被哪个主节点处理

 127.0.0.1:6379> set name cl
 (error) MOVED 5798 127.0.0.1:6380

当使用redis-cli -c进入客户端时,发生这种情况则会自动将Key重定向到对应主节点进行处理

水平扩展/收缩会导致节点的槽交给其他节点管理,这就会引起所在槽的Key发生迁移(迁移到新的节点中)

水平扩容/缩容

当发生水平扩展增加主节点时,会将其他主节点负责管理的哈希槽分配给新加入的主节点,删除节点类似,总要满足管理16384个槽,且集群中最少要求三个主节点

迁移是同步阻塞的,如果要迁移大Key将会发生卡顿,因此要尽量的减少大Key

如果发生迁移时,Key已经到达了新的节点,但是还未迁移完,槽与对应节点管理关系还未发生改动,这种情况下返回MOVED指令就会发生循环重定向(A:已经迁移了你去找B,B:还未迁移,你去找A),这种情况下会返回给客户端ACKING指令

ACKING指令能在数据迁移时,防止发生循环重定向

使用集群

集群最少要求三个主节点,所以我们搭建三主三从的集群

主节点端口号:6379,6380,6381

从节点端口号:6382,6383,6384

都在本地一台机器上进行模拟

1. 编写配置文件
 #general
 daemonize yes
 loglevel verbose
 #logfile "6379.log"
 databases 16
 #bind 47.108.181.237
 port 6379
 ​
 #密码
 requirepass cl192243051
 masterauth cl192243051
 ​
 #rdb
 dir /usr/local/redis/redis-6.0.6/data
 dbfilename dump-6379.rdb
 rdbcompression yes
 rdbchecksum yes
 save 60 2
 ​
 #aof
 appendonly yes
 appendfilename appendonly-6379.aof
 appendfsync everysec
 ​
 #memory
 maxmemory-policy noeviction
 ​
 #cluster 集群配置文件主要是这里
 cluster-enabled yes #开启集群
 cluster-config-file nodes-6379.conf #该节点产生的文件
 cluster-node-timeout 10000 #如果该节点的master超时多少秒没反应就尝试推荐自己当master
 ​
 #关闭protected-mode模式 允许外网访问
 protected-mode no

当编写好模板配置文件后,其他配置文件也是一致的只需要改变端口号

使用命令将redis-6379.conf文件中6379替换为6380生成新文件redis-6380.conf

 sed "s/6379/6380/g" redis-6379.conf > redis-6380.conf
2. 启动所有节点

redis-server redis-6379.conf

image.png

3.搭建集群命令
 #如果有密码使用参数-a
 #--cluster-replicas 1 表示每个主节点携带一个从节点
 #后面跟所有节点的 IP:端口号(先主节点后从节点)
 #本地访问版
 redis-cli --cluster create --cluster-replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384
 ​
 #外网访问版
 redis-cli --cluster create --cluster-replicas 1 -a 密码 47.108.181.237:6379 47.108.181.237:6380 47.108.181.237:6381 47.108.181.237:6382 47.108.181.237:6383 47.108.181.237:6384

image-20211204165816656.png

4. 客户端测试

客户端使用redis-cli 操作不在当前节点管理槽的key会响应moved信息

当集群模式时,进入客户端使用redis-cli -c 这样它会重定向到对应的节点中

写操作

 127.0.0.1:6379> set name cl
 (error) MOVED 5798 127.0.0.1:6380
 ​
 [root@Tcl ~]# redis-cli -c
 127.0.0.1:6379> set name cl
 -> Redirected to slot [5798] located at 127.0.0.1:6380
 OK
 127.0.0.1:6380> 

读操作

故意不去6380端口

 [root@Tcl ~]# redis-cli -c -p 6381
 127.0.0.1:6381> get name
 -> Redirected to slot [5798] located at 127.0.0.1:6380
 "cl"
 127.0.0.1:6380> 

查看节点信息

在客户端使用命令cluster nodes可以查看节点信息

 127.0.0.1:6380> cluster nodes
 3c0b7cbc00846b8cca43dd94c55a0005d4d3113b 127.0.0.1:6380@16380 myself,master - 0 1638608629000 2 connected 5461-10922
 207460275205f58d47dbf3528bc3c1dedd3ce59d 127.0.0.1:6379@16379 master - 0 1638608631377 1 connected 0-5460
 d0eeaf81fcdcbaeee2f99c6598e00b239d796bea 127.0.0.1:6384@16384 slave 3c0b7cbc00846b8cca43dd94c55a0005d4d3113b 0 1638608630375 2 connected
 86fcc49d8090bfcfea7a40241c6a78c4bcbc617a 127.0.0.1:6381@16381 master - 0 1638608629375 3 connected 10923-16383
 449bceec97e103eafdfebade77decd92081a798b 127.0.0.1:6383@16383 slave 207460275205f58d47dbf3528bc3c1dedd3ce59d 0 1638608628372 1 connected
 28f122d37e1bce60749326761a6ec7adc92e834b 127.0.0.1:6382@16382 slave 86fcc49d8090bfcfea7a40241c6a78c4bcbc617a 0 1638608631000 3 connected

image-20211204170553227.png

6379主节点的从节点是6383

6380主节点的从节点是6364

6381主节点的从节点是6382

5. 模拟主从切换

现在模拟6379主机宕机,超时10s后它的从节点6383检测到主节点没响应,会发生主从切换

 127.0.0.1:6380> cluster nodes
 3c0b7cbc00846b8cca43dd94c55a0005d4d3113b 127.0.0.1:6380@16380 myself,master - 0 1638609049000 2 connected 5461-10922
 207460275205f58d47dbf3528bc3c1dedd3ce59d 127.0.0.1:6379@16379 master,fail - 1638608946026 1638608941010 1 disconnected
 d0eeaf81fcdcbaeee2f99c6598e00b239d796bea 127.0.0.1:6384@16384 slave 3c0b7cbc00846b8cca43dd94c55a0005d4d3113b 0 1638609052351 2 connected
 86fcc49d8090bfcfea7a40241c6a78c4bcbc617a 127.0.0.1:6381@16381 master - 0 1638609051000 3 connected 10923-16383
 449bceec97e103eafdfebade77decd92081a798b 127.0.0.1:6383@16383 master - 0 1638609051347 7 connected 0-5460
 28f122d37e1bce60749326761a6ec7adc92e834b 127.0.0.1:6382@16382 slave 86fcc49d8090bfcfea7a40241c6a78c4bcbc617a 0 1638609049343 3 connected

image-20211204171229115.png

6379主机失败,而6383成为新的master

再启动6379主机,6379变成了6383的从机

同时也会更新其他节点中,这俩个节点关系变更的信息

image-20211204171326196.png

6. spring boot整合jedis cluster
 <dependency>
     <groupId>redis.clients</groupId>
     <artifactId>jedis</artifactId>
     <version>3.7.0</version>
 </dependency>
 @Configuration
 public class JedisClusterConfig {
 ​
     @Value("${spring.redis.cluster.nodes}")
     private String clusterNodes;
     @Value("${spring.redis.timeout}")
     private int timeout;
     @Value("${spring.redis.jedis.pool.max-idle}")
     private int maxIdle;
     @Value("${spring.redis.jedis.pool.max-wait}")
     private long maxWaitMillis;
     @Value("${spring.redis.maxAttempts}")
     private int maxAttempts;
     @Value("${spring.redis.password}")
     private String password;
 ​
     @Bean
     public JedisCluster getJedisCluster() {
         String[] cNodes = clusterNodes.split(",");
         Set<HostAndPort> nodes = new HashSet<HostAndPort>();
         // 分割出集群节点
         for (String node : cNodes) {
             String[] hp = node.split(":");
             nodes.add(new HostAndPort(hp[0], Integer.parseInt(hp[1])));
         }
         JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
         jedisPoolConfig.setMaxIdle(maxIdle);
         jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
         // 创建集群对象
         JedisCluster jedisCluster = new JedisCluster(nodes, timeout, timeout, maxAttempts, password, jedisPoolConfig);
         return jedisCluster;
     }
 }

接下来可以使用jediscluster调用api操作redis集群

集群注意事项

  • 当有业务需要使用Set对象操作交集、并集时,要求key需要在相同的主节点中,使用{}规范命名前缀,计算槽时只有括号中的内容才会被哈希({}前缀相同,它们就会被分配到相同的槽中,由相同主节点处理)
  • mset、mget、事务等操作只有槽都被相同节点管理时才能使用,可以使用{}相同前缀解决
  • 集群下每个节点只有一个数据库

总结

本篇文章围绕Redis集群深入浅出的解析集群原理、使用集群以及注意事项

集群通过分片的策略,由多个节点管理集群中的16384个哈希槽,查询时先CRC16(key)% 16384计算key所在哈希槽,再去管理该哈希槽的主节点处理

为了保证集群的可用性,使用从节点冗余备份主节点数据,当发生确认下线时根据raft算法推举从节点发生主从切换,主从之间数据同步默认是异步的,性能和一致性不可兼得

由于Key不一定由当前服务端节点管理,服务端会使用MOVED指令重定向到管理key所在槽的节点

当发生水平扩容/缩容时,需要其他节点迁出/迁入部分管理的哈希槽,迁移是同步阻塞的,如果有大Key要迁移则会发生卡顿,使用ACKING指令防止迁移时发生循环重定向

最后(一键三连求求拉~)

本篇文章笔记以及案例被收入 gitee-StudyJava、 github-StudyJava 感兴趣的同学可以stat下持续关注喔~

有什么问题可以在评论区交流,如果觉得菜菜写的不错,可以点赞、关注、收藏支持一下~

关注菜菜,分享更多干货,公众号:菜菜的后端私房菜

本文由博客一文多发平台 OpenWrite 发布!

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

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

相关文章

#QT(串口助手-界面)

1.IDE&#xff1a;QTCreator 2.实验&#xff1a;编写串口助手 3.记录 接收框:Plain Text Edit 属性选择&#xff1a;Combo Box 发送框:Line Edit 广告&#xff1a;Group Box &#xff08;1&#xff09;仿照现有串口助手设计UI界面 &#xff08;2&#xff09;此时串口助手大…

ai脚本创作的软件有哪些?分享3款好用的工具!

随着人工智能技术的飞速发展&#xff0c;AI脚本创作软件已经成为内容创作者们的新宠。这些软件不仅能够帮助我们更高效地生成文章、视频脚本等&#xff0c;还能为我们提供独特的创意视角和无限的灵感。本文将带您深入了解几款备受瞩目的AI脚本创作软件&#xff0c;看看它们如何…

带胶囊按钮的标题是如何实现的

使用uni-app开发小程序经常会遇到胶囊按钮和标题之间融合的问题&#xff0c;因为这样可以大大提高页面的美观和整体性&#xff0c;那么接下来简单拆分步骤看下是如何实现的吧 &#x1f601; 可以看到我们设置的标题是在默认标题栏之下的&#xff08;这不是我们想要的效果 &…

许多人可能还不了解这个信息差:美赛的第一批 EI 已经录用,不用再犹豫啦

格局打开&#xff0c;美赛论文转学术论文发表 &#x1f680;&#x1f680; 各位同学&#xff0c;美赛已经结束了一段时间&#xff0c;你们是否还在焦急地等待最终成绩的公布&#xff1f;一些有远见的同学已经提前收到了一份喜讯&#xff1a;他们的美赛论文已被转化为学术论文并…

VMware虚拟机

1、虚拟机介绍 虚拟机&#xff08;Virtual Machine&#xff09;是一种软件&#xff0c;可以用来模拟具有完整硬件功能的完整的计算机系统的软件&#xff0c;并且可以和主机环境隔离开&#xff0c;互不影响。也就是&#xff0c;在实体计算机中能够完成的工作都可以通过虚拟机实…

【SQL】1068. 产品销售分析 I

题目描述 leetcode题目&#xff1a;1068. 产品销售分析 I 写法 select Product.product_name, Sales.year, Sales.price from Sales left join Product on Sales.product_id Product.product_id记录细节&#xff1a;加上表名检索效率更高。 -- ERROR: 时间超出限制 > 加…

UE4 Niagara 关卡4.1官方案例解析

we now directly supporting playing audio from arbitrary locations in particle systems.users have control over volume and pitch,and the system can directly play sound waves,or sound cues which have multiple waves in them.(我们现在直接支持在粒子系统中从任意…

一个用libcurl多线程下载断言错误问题的排查

某数据下载程序&#xff0c;相同版本的代码&#xff0c;在64位系统中运行正常&#xff0c;但在32位系统中概率性出现断言错误。一旦出现&#xff0c;程序无法正常继续&#xff0c;即使重启亦不行。从年前会上领导提出要追到根&#xff0c;跟到底&#xff0c;到年后的今天&#…

报考照片大小不能超过30k怎么设置?赶快学习起来

某些在线表格和申请表要求上传照片&#xff0c;但对文件大小有严格的限制&#xff0c;这种限制可能出现在学校申请、工作申请、签证申请、奖学金申请等各种在线表格中&#xff0c;比如有些平台要求上传报考照片大小不能超过30k&#xff0c;那么如何将图片压缩指定大小呢&#x…

长非编码RNA(lncRNA)LINC00339编码的肽段促进滋养层细胞与子宫内膜细胞粘附的研究 AbMole

胚胎植入是一个复杂的过程&#xff0c;受多种因素影响&#xff0c;尤其是子宫内膜&#xff08;endometrium&#xff09;与胚泡&#xff08;blastocyst&#xff09;之间的相互作用。子宫内膜接受性&#xff08;Endometrial Receptivity, ER&#xff09;是指子宫内膜在适当的功能…

第二门课:改善深层神经网络<超参数调试、正则化及优化>-深度学习的实用层面

文章目录 1 训练集、验证集以及测试集2 偏差与方差3 机器学习基础4 正则化5 为什么正则化可以减少过拟合&#xff1f;6 Dropout<随机失活>正则化7 理解Dropout8 其他正则化方法9 归一化输入10 梯度消失和梯度爆炸11 神经网络的权重初始化12 梯度的数值逼近13 梯度检验14 …

Word文档一键转换成电子书,告别繁琐操作!

你是否曾经为了将Word文档转换为电子书而苦恼&#xff1f;手动复制粘贴、调整格式、排版等等繁琐的操作&#xff0c;不仅耗时费力&#xff0c;还容易出错。现在我教你只需轻轻一点&#xff0c;即可将Word文档轻松转换为电子书&#xff0c;无需任何手动操作 一、Word转换电子书步…

idea配置汇总【2023】最新外观配置和常规操作配置

界面 如果是IDEA请移步去其他人之前的文章看已经烂大街了&#xff0c;这是最新版的一些新功能的配置研究&#xff0c;毕竟天天看它不好看点怎么能行 ①tool windows 在新版&#xff08;不一定是当前年份的最新版&#xff09;idea中针对界面tool window有了新的优化&#xff0c…

STM32CubeIDE基础学习-STM32CubeIDE软件配置下载器方法

STM32CubeIDE基础学习-STM32CubeIDE软件配置下载器方法 文章目录 STM32CubeIDE基础学习-STM32CubeIDE软件配置下载器方法前言第1章 配置ST-LINK下载器第2章 配置DAP下载器总结 前言 这个软件编译完之后&#xff0c;可以使用下载器进行在线下载程序或仿真调试程序&#xff0c;也…

支持向量机 SVM | 线性可分:软间隔模型

目录 一. 软间隔模型1. 松弛因子的解释小节 2. SVM软间隔模型总结 线性可分SVM中&#xff0c;若想找到分类的超平面&#xff0c;数据必须是线性可分的&#xff1b;但在实际情况中&#xff0c;线性数据集存在少量的异常点&#xff0c;导致SVM无法对数据集线性划分 也就是说&…

Seata 2.x 系列【6】微服务项目搭建

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Seata 版本 2.0.0 本系列Spring Boot 版本 3.2.0 本系列Spring Cloud 版本 2023.0.0 源码地址&#xff1a;https://gitee.com/pearl-organization/study-seata-demo 文章目录 1. 概述2. 数据库…

【MQ】消息队列概述

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;MQ ⛺️稳中求进&#xff0c;晒太阳 定义 消息队列&#xff1a;一般我们简称为MQ(Message Queue) Message Queue :消息队列中间件&#xff0c;很多初学者认为&#xff0c;MQ通过消息的发送…

linux centos系统搭建samba文件服务器 NetBIOS解析 (超详细)

CSDN 成就一亿技术人&#xff01; 作者主页&#xff1a;点击&#xff01; Linux专栏&#xff1a;点击&#xff01; CSDN 成就一亿技术人&#xff01; 前言———— Samba 是一个开源软件套件&#xff0c;可为 SMB/CIFS 客户端&#xff08;包括 Windows&#xff09;提供文件…

【JavaEE初阶】 关于JVM垃圾回收

文章目录 &#x1f343;前言&#x1f38b;死亡对象的判断算法&#x1f6a9;引用计数算法&#x1f6a9;可达性分析算法 &#x1f333;垃圾回收算法&#x1f6a9;标记-清除算法&#x1f6a9;复制算法&#x1f6a9;标记-整理算法&#x1f6a9;分代算法&#x1f388;哪些对象会进入…

vue 总结

1.vue 的生命周期 1. es6 2. vue 基本属性指令 <template><div><!--<h1>vue基本指令的使用方式</h1><a :href"url">v-bind使用链接</a><img :src"srcUrl" /><div>解决闪烁问题<p v-cloak>{{…