【Redis】高可用之三:集群(cluster)

本文是Redis系列第6篇,前5篇欢迎移步 

【Redis】不卡壳的 Redis 学习之路:从十大数据类型开始入手_AQin1012的博客-CSDN博客关于Redis的数据类型,各个文章总有些小不同,我们这里讨论的是Redis 7.0,为确保准确,我们直接看官网。https://blog.csdn.net/aqin1012/article/details/130365083

【Redis】持久化机制详解:从RDB到AOF,你需要知道的一切_AQin1012的博客-CSDN博客持久化其实就4个单词:加强数据安全Redis支持两种不同的持久化机制,RDB和AOF。https://blog.csdn.net/aqin1012/article/details/130481261

【Redis】不卡壳的 Redis 学习之路:事务_AQin1012的博客-CSDN博客数据库中的事务是指在一次与数据库连接的会话中,所有的SQL语句,要么都成功,要么都失败。在Redis中,事务是指可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会被序列化,按顺序地串行执行而不会被其他命令插入开启:以MULTI开始一个事务入队:将多个命令入队到事务中,接到这些命令并不会立即执行,而是放到等待执行的事务队列里面执行:由EXEC命令触发事务。https://blog.csdn.net/aqin1012/article/details/131474273?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22131474273%22%2C%22source%22%3A%22aqin1012%22%7D

【Redis】高可用之一:复制(replica)_AQin1012的博客-CSDN博客官网地址: https://redis.io/docs/management/replication/其实就是主从复制,master以写为主,slave以读为主当master数据变化的时候,自动将新的数据异步同步到其它slave数据库主机(master)能读能写,从机(slave)只能读无论主机已经写了多少数据,从机一旦启动,就会全部复制过来,后续主机写,从机跟配置文件🆚命令配置使用配置文件进行主从配置时,如果主机挂了,从机不会变化,还可以提供读的功能,等待主机恢复(重启后主从关系仍在)https://blog.csdn.net/aqin1012/article/details/131531792?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22131531792%22%2C%22source%22%3A%22aqin1012%22%7D

【Redis】高可用之二:哨兵(sentinel)_AQin1012的博客-CSDN博客哨兵会巡查监控后台master主机,查看是否存在故障,如果故障了,就会根据投票数自动将某一个从库转换为新主库,继续对外服务(解决复制的痛点)官方网址简单来讲,哨兵就是一种无人值守的运维机制3个哨兵自动监控和维护集群,不存放数据,只是“吹哨人”1主2从用于数据读取和存放主机宕机,从机数据还在会从剩下的两台主机中选出新的主机如果宕机的主机恢复,不会出现主机冲突,恢复的主机将变为新主机的从机。https://blog.csdn.net/aqin1012/article/details/131595489本文目录

什么是集群

能做啥

集群算法

槽位slot

分片

使用槽位+分片的优势

槽位的映射方案

哈希取余分区

缺点

一致性哈希算法分区

是什么

一致性Hash算法背景

3大步骤

算法构建一致性哈希环

服务器IP节点映射

key落到服务器的落键规则

Hash环的数据倾斜问题

优点

缺点

哈希槽分区

为什么Redis的槽数是16384?


什么是集群

官网地址

https://redis.io/docs/reference/cluster-spec/

由于数据量过大,单个Master复制集难以承担,因此需要对多个复制集进行集群,形成水平扩展。每个数据集只负责存储整个数据集的一部分,这就是Redis的集群,其作用是提供在多个Redis节点间共享数据的程序集

Redis集群可以支持多个Master,从哨兵到集群

哨兵
集群

能做啥

  • Redis集群支持多个Master,每个Master又可以挂载多个Slave
    • 读写分离
    • 支持数据的高可用
    • 支持海量数据的读写存储操作
  • 由于Cluster自带Sentinel的故障转移机制,内置了高可用的支持,无需再去使用哨兵功能
  • 客户端与Redis的节点连接,不再需要连接集群中所有的节点,只需要任意连接集群中的一个可用节点即可
  • 槽位slot负责分配到各个物理服务节点,由对应的集群来负责维护节点、插槽和数据之间的关系

集群算法

槽位slot

Redis集群没有使用一致性hash,而是引入了哈希槽的概念。

集群的有16384个槽,有效地设置了16384个主节点的集群大小上限(但是官网建议的最大节点大小约为1000个节点),每个key通过CRC16校验后对16384取模(HASH_SLOT = CRC16(key) mod 16384)来决定放置在哪个槽,集群的每个节点负责一部分hash槽(数据分片)。

当没有集群重新配置正在进行时(即哈希槽从一个节点移动到另一个节点),集群是稳定的。

当集群稳定时,单个哈希槽将由单个节点提供服务(但是,服务节点可以有一个或多个副本,在网络分裂或故障的情况下替换它,并目可以用于扩展读取陈旧数据是可接受的操作)

分片

使用Redis集群时,我们会将存储的数据分散到多台Redis机器上,这就是分片。换句话说,就是集群中的每个Redis实例都被认为是整个数据的一个分片。

那么如何找到给定key的分片呢?

即对key进行CRC16(key)算法处理并通过总分片数量取模,然后,使用确定性哈希函数,这意味着给定的key将始终映射到同一个分片,因此可以推断将来读取特定key的位置

使用槽位+分片的优势

最大优势:方便扩缩容数据分派查找

这种结构很容易添加或者删除节点。

举个例子🌰:

如果我想新添加个节点D,就需要从节点A、B、C中得部分槽到D上

如果我想移除节点A,需要将A中的槽移到B和C节点上,然后将没有任何槽的A节点从集群中移除即可

由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态

槽位的映射方案

slot槽位映射,一般业界有3种解决方案:哈希取余分区、一致性哈希算法分区和哈希槽分区,我们一一来介绍下他们。

哈希取余分区

公式 hash(key)%n

  • n 为机器台数

缺点

原来规划好的节点,进行扩容或者缩容就比较麻烦。不管扩缩,每次数据变动导致节点有变动,映射关系需要重新进行计算,在服务器个数固定不变时没有问题,如果需要弹性扩容或故障停机的情况下,原来的取模公式就会发生变化。

举个例子,2亿条记录就是2亿个k,v,单机不行就要考虑分布式多机,假设有3台机器构成一个集群,用户每次读写操作都是根据公式hash(key)%N个机器台数,计算出哈希值,用来决定数据映射到哪一个节点上。

如果原来有3台,增加了1台,就会从Hash(key)%3变成Hash(key)%4。

此时地址经过取余运算的结果将发生很大变化,根据公式获取的服务器也会变得不可控。即某个redis机器宕机了,由于台数数量变化,会导致hash取余全部数据重新洗牌。

一个词总结 -> 不一致

于是我们有了👇 —— 一致性哈希算法分区

一致性哈希算法分区

是什么

一致性Hash算法背景

一致性哈希算法在1997年由麻省理工学院中提出的,设计目标是为了解决分布式缓存数据变动映射问题(当服务器个数发生变动时,尽量减少影响客户端到服务器的映射关系),某个机器宕机了,分母数量改变了,自然取余数不行了。

3大步骤

算法构建一致性哈希环

将节点全部放到一个虚拟的圆环上,圆环上0在2^32处重合,其节点范围在0-2^32-1

一致性哈希算法必然有个哈希函数并按照算法产生哈希值,这个算法的所有可能哈希值会构成一个全量集,这个集合可以成为一个hash空间[0,2^32-1],这个是一个线性空间,但是在算法中,我们通过适当的逻辑控制将它首尾相连(0=2^32),这样让它逻辑上形成了一个环形空间。它也是按照使用取模的方法,不过前面介绍的哈希取余分区取模法是对节点(服务器)的数量进行取模,而一致性哈希算法是对2^32取模(因此解决了取模数会变化的问题),简单来说,一致性哈希算法就是将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数的值空间为0~2^32-1(即哈希值是一个32位无符号整形),整个哈希环如下图:

整个空间按顺时针方向组织,圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4……直到2^32-1,也就是说0点左侧的第一个点代表2^32-1,0和2^32在零点中方向重合,我们把这个由2^32个点组成的圆环称为Hash环。

服务器IP节点映射

IP或者主机名

节点映射

将集群中各个IP节点映射到环上的某一个位置。

将各个服务器使用Hash()进行次哈希,具体可以选择服务器的IP或主机名作为关键字,这样每台机器就能确定其在哈希环上的位置。举个例子,如下图4个节点NodeA、B、C、D,经过IP地址的哈希函数计算Hash(IP),使用IP地址哈希后在环空间的位置如下:

key落到服务器的落键规则

当我们需要存储一个kv键值对时,首先计算key的hash值(hash(key))将这个key使用相同的哈希函数计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器,并将该键值对存储在该节点上。

举个例子,如下图中Object A和Object 两个数据对象,经过哈希计算后,在环空间上的位置如下图所示:

根据一致性哈希算法,Object A会被定位到Node B上,Object B定位到Node D上

Hash环的数据倾斜问题

一致性哈希算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜的问题

即被缓存的对象大部分集中缓存在某一台服务器上,举个例子,如果只有两台服务器,就容易出现大部分数据都存在其中一个服务器上的情况,如下图所示:

其实,搞个环也就是为了在节点数目发生改变时,尽量少的迁移数据,将所有的节点排列在首尾相接的Hash环上,每个key在计算后会顺时针找到邻近的储存节点存放,而当有节点加入或者退出时仅影响该节点在Hash环上顺时针相邻的后续节点

优点

加入和删除只影响hash环中顺时针方向相邻的节点,对其他节点无影响

缺点

数据的分布和节点的位置有关,因为这些节点不是均匀的分布在哈希环上的,所以数据在进行存储时达不到均匀分布的效果。

这就是一致性哈希算法在节点较少时会有数据倾斜的问题,因此我们有了👇 —— 哈希槽分区

哈希槽分区

为了解决一致性哈希算法数据倾斜的问题,产生了哈希槽分区

其实质就是一个数组,数组[0, 16383]形成哈希槽空间(共16384个槽位)

16384就是2^14-1

没有什么是加一层解决不了的,如果有,那就再加一层

解决均匀分配的问题,在数据和节点之间又加了一层,把这层称为哈希槽(slot),用于管理数据和节点之间的关系,就相当于节点上放的是槽,槽里放的是数据。

槽解决粒度的问题,相当于粒度调大了,便于数据的移动。哈希解决的是映射问题,使用key的哈希值来计算所在的槽,便于数据分配。

一个集群只能有16384个槽,编号0-16383(0~2^14-1),这些槽会分配给集群中的所有主节点,分配策略没有要求。

集群会记录节点和槽的对应关系,解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取模,余数是几key就落入对应的槽里(HASH_SLOT=CRC16(key)mod 16384)。

以槽为单位移动数据,因为槽的数目是固定的,处理起来比较容易,这样数据移动问题就解决了。

为什么Redis的槽数是16384?

Redis集群并没有使用一致性hash而是引入了哈希槽的概念。

Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置那个槽,集群的每个节点负责一部分哈希槽,但为什么哈希槽的数量是16384(2^14)个呢?

CRC16算法产生的哈希值有16bit,该算法可以产生2^16=65536个值,换句话说值是分布在0~65535之间,有更大的65536不用为什么只用16384呢?

我们看下作者的解释

https://github.com/redis/redis/issues/2576

The reason is:

  1. Normal heartbeat packets carry the full configuration of a node, that can be replaced in an idempotent way with the old in order to update an old config. This means they contain the slots configuration for a node, in raw form, that uses 2k of space with16k slots, but would use a prohibitive 8k of space using 65k slots.
  2. At the same time it is unlikely that Redis Cluster would scale to more than 1000 mater nodes because of other design tradeoffs.

So 16k was in the right range to ensure enough slots per master with a max of 1000 maters, but a small enough number to propagate the slot configuration as a raw bitmap easily. Note that in small clusters the bitmap would be hard to compress because when N is small the bitmap would have slots/N bits set that is a large percentage of bits set.

简单翻译下:

  1. 正常的心跳数据包带有节点的完整配置,可以用幂等方式用旧的节点替换旧节点,以便更新旧的配置。这意味着它们包含原始节点的插槽配置,该节点使用2k的空间和16k的插槽,但是会使用8k的空间(使用65k的插槽)。
  2. 同时,由于其他设计折衷,Redis集群不太可能扩展到1000个以上的主节点。

因此16k处于正确的范围内,以确保每个主机具有足够的插槽,最多可容纳1000个矩阵,但数量足够少,可以轻松地将插槽配置作为原始位图传播。请注意,在小型群集中,位图将难以压缩,因为当N较小时,位图将设置的slot/N占设置位的很大百分比。

(1)如果槽位为65536,发送心跳信总的消息头达8k,发送的心跳包过于庞大。

在消息头中最占空间的是myslots[CLUSTER_SL0TS/8],当槽位为65536时,这块的大小是:65536÷8÷1024=8kb;当槽位为16384时,这块的大小是:6384÷8÷1024=2kb

因为每秒钟,Redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,会浪费带宽。

(2)Redis的集群主节点数量基本不可能超过1000个。

集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。

因此Redis作者不建议redis cluster节点数量超过1000个,而对于节点数在1000以内的redis cluster集群,16384个槽位够用了,没有必要拓展到65536个。

(3)槽位越小,节点少的情况下,压缩比高,容易传输

Redis主节点的配置信息中它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中会对bitmap进行压缩,但是如果bitmap的填充率slots/N很高的话(N表示节点数),bitmap的压缩率就很低。如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率也会很低。

总结起来就是:适用、小巧、精干

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

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

相关文章

Linux基础(三)端口、进程及主机状态管理、环境变量、文件管理

目录 端口 nmap netstat 进程管理 查看进程 关闭进程 主机状态监控 系统资源top命令 磁盘信息监控 网络状态监控 环境变量 $符号 自己设置环境变量 自定义环境变量PATH Linux的文件和下载 压缩和解压 tar命令 zip和unzip命令 端口 每个电脑有一个ip地址&#xff…

Vue项目实现在线预览pdf,并且可以批量打印pdf

最近遇到一个需求,就是要在页面上呈现pdf内容,并且还能用打印机批量打印pdf,最终效果如下: 当用户在列表页面,勾选中两条数据后,点击“打印表单”按钮之后,会跳到如下的预览页面: 预览页面顶部有个吸顶的效果,然后下方就展示出了2个pdf文件对应的内容,我们接着点击“…

echarts 地图点击常见问题

echats 散点图不支持缩放 echarts 地图点击激活label如何去除 高德loca 1.4版本热力图报错 绘制的颜色区间是 0 --1 高德地图销毁不生效 自己傻逼,每次没有清空数组导致叠加数据,约点数据越多。 为何用高德地图district.search查询不到别的省数据&…

[微信小程序] movable-view 可移动视图容器 - 范围问题

movable-view 可移动视图容器 可移动视图容器&#xff0c;在页面中可以拖拽滑动。movable-view必须在 movable-area 组件中&#xff0c;并且必须是直接子节点 <view><movable-area style"width: 750rpx;height: 200rpx;background-color: gainsboro;">&l…

Java的数据结构-Map集合

文章目录 Map概述Map常用方法Map遍历元素的方法1.方法一&#xff1a;keySet()2.方法二&#xff1a;entrySet() HashMap Map概述 1、Map和collection没有继承关系2、Map集合以key和value的方式存储数据&#xff1a;键值对key和value都是引用数据类型。key和value都是存储对象的…

(栈队列堆) 剑指 Offer 31. 栈的压入、弹出序列 ——【Leetcode每日一题】

❓ 剑指 Offer 31. 栈的压入、弹出序列 难度&#xff1a;中等 输入两个整数序列&#xff0c;第一个序列表示栈的压入顺序&#xff0c;请判断第二个序列是否为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如&#xff0c;序列 {1,2,3,4,5} 是某栈的压栈序列&#xff0c;序…

Appium Android ——利用 TestNG 并行执行用例

目录 前言&#xff1a; 一、测试类 二、连接两个 Android 设备或启动两个虚拟机 三、项目路径下新建两个 testng.xml 四、开启两个 appium server 五、导出依赖 六、执行测试 七、查看报告 前言&#xff1a; Appium是一个流行的移动应用自动化测试工具&#xff0c;…

使用semanage管理SELinux安全策略

semanage命令用于管理SELinux的策略&#xff0c;格式为“semanage [选项] [文件]”。 SELinux服务极大地提升了Linux系统的安全性&#xff0c;将用户权限牢牢地锁在笼子里。semanage命令可以设置文件、目录的策略&#xff0c;还可以管理网络端口、消息接口。 常用参数&#xf…

vue3+vite配置 unplugin-vue-component 找不到 Vant 组件的问题

使用 vue3 vite Vant 搭建移动端项目&#xff0c;为了避免全量引入 vant 导致打包体积过大&#xff0c;又不想一个一个组件手动导入&#xff0c;所以就选择了 vant 官方推荐的方法&#xff0c;使用 unplugin-vue-components 插件自动引入组件&#xff0c;并按需引入组件的样式…

Qgis3.16ltr+VS2017二次开发环境搭建(保姆级教程)

1.二次开发环境搭建 下载osgeo4w-setup.exeDownload QGIShttps://www.qgis.org/en/site/forusers/download.html 点击OSGeo4W Network Installer 点击下载 OSGeo4W Installer 运行程序 osgeo4w-setup.exe&#xff0c;出现以下界面&#xff0c;点击下一页。 选中install from i…

力扣206. 反转链表

给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1]示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1]示例 3&#xff1a; 输入&am…

MySQL进阶

目录 一、存储引擎 1、MySQL体系结构 2、存储引擎简介 3、存储引擎特点 InnoDB MyISAM Memory 4、存储引擎选择 二、索引 1、索引概述 2、索引结构 3、索引分类 4、索引语法 5、SQL性能分析 5.1 SQL执行频率 5.2 慢查询日志 5.3 profile详情 5.4 explain执行…

Sentinel流量规则模块(新增)

系统并发能力有限&#xff0c;比如系统A的QPS支持1个请求&#xff0c;如果太多请求过来&#xff0c;那么系统A就应该进行流量控制了&#xff0c;比如其他请求直接拒绝 新增流控规则介绍:新增流控规则窗口 1.资源名&#xff1a;默认请求路径。 2.针对来源&#xff1a;Se…

基于51单片机和proteus的温室大棚系统

此系统是基于51单片机和proteus的仿真设计&#xff0c;功能如下&#xff1a; 1. LCD1602实时显示光照/土壤湿度/温度值及设定值。 2. 按键可增减光照/土壤湿度/温度设定阈值。 3. 获取到的温度低于设定温度则打开加热设备。 4. 获取到的光照值低于设定光照值则打开补光灯。…

【iOS】编译与链接

前言 计算机语言分为机器语言、汇编语言和高级语言。 可以将高级语言分为两种&#xff1a;编译语言和解释型语言&#xff08;直译式语言&#xff09;。 解释型语言&#xff08;逐步进行解释执行&#xff09; 解释语言编写的程序在每次运行时都需要通过解释器对程序进行动态…

【区块链+体育】“数智化”的杭州亚运会,中创助力区块链技术发展

“智能”&#xff0c;是杭州亚运会的办赛理念之一。除了数字藏品开亚运先河&#xff0c;杭州亚组委充分应用区块链、大数据、人工智能等前沿技术&#xff0c;为观众提供从购票、出行、观赛到住宿、美食和旅游等“一站式”服务。 本次亚运会将全程智能陆续落到了实处&#xff0…

CSS 实现 Turbo 官网 3D 网格线背景动画

转载请注明出处&#xff0c;点击此处 查看更多精彩内容 查看 Turbo 官网 时发现它的背景动画挺有意思&#xff0c;就自己动手实现了一下。下面对关键点进行解释说明&#xff0c;查看完整代码及预览效果请 点击这里。 简单说明原理&#xff1a;使用 mask-image 遮罩绘制网格&a…

Python测试框架Pytest的基础入门

Pytest简介 Pytest is a mature full-featured Python testing tool that helps you write better programs.The pytest framework makes it easy to write small tests, yet scales to support complex functional testing for applications and libraries. 通过官方网站介绍…

ios 通过xib自定义控件

通过xib自定义控件 xib和stroyboayd对比 共同点&#xff1a; 都是用来描述软件界面 都是用interface Builder工具来编辑 本质都是转换成代码去创建控件 不同点&#xff1a; xib是轻量级的&#xff0c;用来描述局部ui界面 创建模型文件 XMGCar 自定义控件 xib 图形设计 …