Redis进阶(五):集群

1.概念

集群,从广义来讲:只要是多个机器,构成了分布式系统,都可以称为一个集群

狭义的集群:redis提供的集群模式,这个集群模式之下,主要是要解决存储空间不足的问题(拓展存储空间)

哨兵模式提高了系统的可用性,哨兵模式中,本质上还是redis主从节点存储数据,其中就要求一个主节点/从节点,就得存储整个数据的"全集"

引入多台机器,每台机器分担一部分:存储一部分数据,每台存储数据的机器还需要搭配多个从节点

2.分片

上述红框标注的就是分片~ 三种主流的分片方式

2.1 hash求余

借助hash函数,把一个key映射到整数,再针对数组长度求余,就可以得到一个数组下标

比如有三个分片:0,1,2

此时可以针对要插入的数据的key(redis都是键值对结构的数据)计算hash值(比如md5:将string经过数据计算得到一个整数),再把这个hash值余上分片的个数,就得到了一个下标,此时就可以把这个数据放到该下标对应的分片中了。

hash(key) % length(分片的个数,上述就是3)


但如果分片添加了,也就是扩容发生的时候,分片结果就会发生变化(需要重新进行分配)。

2.2 一致性hash算法

上述方式,如果数据很大,且发生数据搬运,开销极大,只能在非生产环境下,通过替换的方式进行扩容,依赖机器更多了,成本也高,因此一致性hash算法解决上述问题

在hash求余这种操作,当前key属于哪个分片是交替的:例如102 -》0 ,103-》1,104-》2 ...0,1,2.....,在一致性hash下,把交替出现,改成连续出现。

具体分为几步:

把0->2^32-1这个数据空间,映射到⼀个圆环上.数据按照顺时针⽅向增⻓.

假设有三个分区,在圆环上进行划分

假定一个key,计算得到hash值,该key值划分就是顺时针往下找,找到的第一个分区就是key所属分片

这就相当于,N个分⽚的位置,把整个圆环分成了N个管辖区间.Key的hash值落在某个区间内,就对应区间管理.

扩容场景

此时,只需要把0号分⽚上的部分数据 ,搬运给3号分⽚即可 .1号分⽚和2号分⽚ 管理的区间都是不变 的.

优点:⼤⼤降低了扩容时数据搬运的规模,提⾼了扩容操作的效率.

缺点:数据分配不均匀(有的多有的少,数据倾斜).

2.3 hash槽分区算法(redis使用)

就比如说:

此处,每个分区都会使用位图的数据结构表示当前有多少槽位号,16384个bit位,用每一个0/1来区分自己这个分片当前是否持有该槽位号

总结一下:key值先通过hash算法计算一下得到一个hash值,hash值再取模16384得到槽位,根据槽位数再划分到不同的分片。

分片增加场景:

注意事项

Redis集群是最多有16384个分⽚吗?

key是先映射到槽位 ,再映射到分片的。

如果每个分片包含的槽位比较多,如果槽位个数相当,就可以认为是包含的key数量相当。

如果每个分片包含的槽位比较少,槽位个数并不能直观的反应到key的数目。

因此造成:有的槽位有key,有的槽位没有key

如果每个分片只有一个槽位:很难保证数据在各个分片的均衡性

为什么是16384

1.节点之间通过心跳包进行通信,心跳包包含每个节点持有什么slots (槽位),槽位使用位图这样的数据结构表示的,16384 (16k)是2kb字节的空间,redis留出2kb的空间来保存槽位,如果slots更多了,就需要更大的空间去保存槽位。因为是周期性通信*(非常频繁,占用带宽)

2.另⼀⽅⾯,Redis集群⼀般不建议超过1000个分⽚.所以16k对于最⼤1000个分⽚来说是⾜够⽤

的,同时也会使对应的槽位配置位图体积不⾄于很⼤.

3.集群搭建

需求:

3.1 实现

在sh文件添加:

实现批量创建redis配置文件

执行脚本:

bash 复制代码
sh xxx.sh

创建redis容器:

在yml文件中进行编辑:

其他redis节点配置:

启动容器:

bash 复制代码
docker -compose up -d

几个redis节点构建成集群:

3.2 使用集群

使用集群存储数据:

-c:选型添加之后,redis客户端就会根据当前key实际算出来的槽位号,自动找到匹配的分片主机

4.故障处理

如果某个节点挂了,处理分几个情况

从节点挂了,挂就挂了不管,但如果是主节点挂了 ?

如果主节点挂了,就会自动把该主节点旗下的某个从节点选拨为主节点

4.1具体流程

1、先判断故障:

1.节点A给节点B发送ping包,B节点返回pong包,二个包除了message type属性不同之外,其他部分是一样的。

2.每个节点每秒钟都会给一些随机的节点发送ping包

3.A节点向B节点发送ping,不能正常返回pong,A就会尝试重置和B的TCP连接,如果还是失败,A就会把B标记为PEAIL(主观下线)

4.A判定BPEAIL之后,A会通过内置的Gossip协议,和其他节点进行沟通。让其他节点确认B状态

5.A发现其他节点也是认为B节点PFAIL,超过一半,那么A标记B为FAIL(客观下线),并且将消息同步给其他节点。

2、故障迁移

如果挂了的B节点是从节点无所谓

如果是主节点:需要从B节点的从节点挑选一个作为主节点

1.从节点首先需要判定是否有资格,从节点与主节点之间太久没同步了,此时差异太大,(超过了一定的阈值),就会失去资格

2.具有资格的节点会先进行休眠:休眠时间的大小因素主要为排名大小(offset值越大,排名越小)

3.有资格从节点的休眠时间到了,该节点就会给其他主节点进行拉票操作

4.主节点收到拉票请求就会投给那个参加竞选的从节点,当票数超过主节点数目的一半,该晋升成功的从节点自己负责 slaveof no one,并且让同为从节点的另一个从节点归属自己

5.同时,该节点晋升为主节点的消息也要发送给其他节点,以供其他节点更新自己的集群结构

集群宕机

出现以下几种情况会发生集群宕机:

1.某个分片,所有的主节点和从节点全挂了 :分片存储了部分的数据,如果该分片全挂了,就会宕机

2.主节点挂了,但该主节点没有从节点:和上述一个情况

3.超过半数的主节点挂了

5.集群扩容

场景:101-109 9个主机,构成了3主6从结构的集群,当前110和111也想加入到集群中:以110为主节点,111为从节点 == 分片从三个到四个

1.新的主节点添加到集群中

左ip为被新增的节点,右ip为集群上任意的一个节点:表明节点增添到哪个集群中

2.重新分配slots

然后需要输入分配多少槽位(通常16384 / 分片数)

紧接着,会询问让哪个节点来接收,粘贴110主机id即可

3.把从节点添加到集群中

5.1 问题

如果搬运key/slots时,此时的客户端能否访问咱们redis集群吗?

搬运key,大部分的key不是用来搬运的,针对这些未搬运的key:此时是可以访问的,针对这些正在搬运中的key,是有可能出现不能访问的情况

相关推荐
辛一一2 小时前
neo4j图数据库基本概念和向量使用
数据库·neo4j
熊大如如3 小时前
Java 反射
java·开发语言
巨龙之路3 小时前
什么是时序数据库?
数据库·时序数据库
蔡蓝3 小时前
binlog日志以及MySQL的数据同步
数据库·mysql
猿来入此小猿3 小时前
基于SSM实现的健身房系统功能实现十六
java·毕业设计·ssm·毕业源码·免费学习·猿来入此·健身平台
goTsHgo4 小时前
Spring Boot 自动装配原理详解
java·spring boot
卑微的Coder4 小时前
JMeter同步定时器 模拟多用户并发访问场景
java·jmeter·压力测试
是店小二呀4 小时前
【金仓数据库征文】金融行业中的国产化数据库替代应用实践
数据库·金融·数据库平替用金仓·金仓数据库2025征文
pjx9874 小时前
微服务的“导航系统”:使用Spring Cloud Eureka实现服务注册与发现
java·spring cloud·微服务·eureka
炒空心菜菜4 小时前
SparkSQL 连接 MySQL 并添加新数据:实战指南
大数据·开发语言·数据库·后端·mysql·spark