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,是有可能出现不能访问的情况

相关推荐
tatasix32 分钟前
MySQL UPDATE语句执行链路解析
数据库·mysql
秋意钟37 分钟前
缓存雪崩、缓存穿透【Redis】
redis
南城花随雪。1 小时前
硬盘(HDD)与固态硬盘(SSD)详细解读
数据库
儿时可乖了1 小时前
使用 Java 操作 SQLite 数据库
java·数据库·sqlite
ruleslol1 小时前
java基础概念37:正则表达式2-爬虫
java
懒是一种态度1 小时前
Golang 调用 mongodb 的函数
数据库·mongodb·golang
简 洁 冬冬1 小时前
046 购物车
redis·购物车
天海华兮1 小时前
mysql 去重 补全 取出重复 变量 函数 和存储过程
数据库·mysql