Redis集群

目录

前言

数据分片算法 

哈希求余:

优点:

缺点:

 一致性hash算法:

优点:

缺点:

哈希槽分区算法(Redis使用) 

拓展问题:


前言

redis哨兵能够提高系统的可用性,但是真正存储数据的还是master和slave节点,所有的数据都保存在单个master和slave节点中

如果数据量很大,接近超出了master/slave所在的机器的物理内存,就会出现严重问题!

 

众所周知,redis的数据是保存在内存上的 ,即便现在的大公司的内存已经能够达到TB级别,但是在现在的这种大数据环境下,显然是不够的

Redis集群应运而生,引入多组Master/Slave,每一组Master/Slave存储数据全集的一部分,从而构成一个更大的整体,称为Redis集群(Cluster)

  • 上图三个不同的redis的主从结构分别存储的数据集3TB的1/3  
  • 每一个红框都可以是一个分片(Sharding)

 

数据分片算法 

Redis cluster 的核心思路是用多组机器来存数据的每个部分,那么接下来的核心问题就是,给定一个数据(一个具体的key),将他分配到应该去到的分片上

哈希求余:

设有N个分片[0,N-1] 进行编号 

假设一共有三个分片,那么得到key后将他hash之后%3 得到分片编号~
 

优点:

简单高效、分配均匀

缺点:

一旦需要进行扩容,N发生了改变,那么原有的映射规则都被破坏了,需要将所有数据进行重新排列,以满足新的映射规则,此时需要搬运的数据量很大~~

 一致性hash算法:

 为了降低上述的搬运开销, 能够更⾼效扩容, 业界提出了 "⼀致性哈希算法"

 第一步:把[0,2^32-1] 这个数据空间,映射到一个圆环上,数据按照顺时针方向增长。

第二步:假设当前存在三个分片,就把分片放到圆环的某个位置上 

 

第三步:假设此时有一个key,那么hash得到的值为H,那么将这个key映射到哪一个分片呢?

即从H位置顺时针往下找,直到找到的第一个分片,就是该key所属的分片

 

 那么在这种一致性hash的情况下,如果扩容一个分片,如何处理呢?

原有分片不动,在环上安排一个新的分片位置即可

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

优点:

大大降低了扩容时数据搬运的规模,提高了扩容操作的效率

缺点:

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

哈希槽分区算法(Redis使用) 

为了解决上述问题,Redis cluster引入了哈希槽(hash slots)算法

hash_slot = crc16(key) % 16384

| crc16 也是一种hash算法

| 16384 其实是16 ^ 1024  = 2 ^ 14

相当于将所有key值映射到 16384 个槽位上,也就是[0,16383]

然后再把这些槽位均匀的分配给每个分片,每个分片的节点都需要记录自己持有哪些分片

假设当前有三个分片,一种可能的分配方式:

  • 0 号分⽚: [0,5461], 共 5462 个槽位
  • 1号分⽚:  [5462,10923],共5462个槽位
  • 2号分⽚:  [10924,16383],共5460个槽位

 TIPS:这里的分片规则是很灵活的,每个分片所持有的槽位也不一定连续

每个分片的节点使用位图来记录自己拥有哪些槽位,对于16384的槽位来说,需要2048个字节(2KB)大小的内存空间表示

此时扩容增加了一个3号分片,即可以针对原有的槽位进行重新分配。

即可以把原有分片所持有的槽位分给新的分片。

  • 0 号分⽚:[0,4095],共4096 个槽位
  • 1 号分⽚:[5462,9557],共 4096 个槽位
  • 2 号分⽚:[10924,15019],共 4096 个槽位
  • 3 号分⽚:[4096,5461]+ [9558, 10923] + [15019, 16383], 共 4096 个槽位?

TIPS:实际使用的时候,不需要手动指定哪些槽位分配给某个分片,只需要告诉某个分片应该持有多少槽位即可,Redis会做单完成分配和搬运~~ 

拓展问题:

Q1:Redis集群最多只有16384个分片吗?

A1:nonono,实际上redis作者建议集群分片不要超过1000. 更何况如果你是用16000以上的那么大个规模的集群,本身的可用性也是一大问题

Q2:为什么是16384个槽位?

A2:这里直接翻译Redis原作者的话,大致是如下。

  • 节点之间的通讯是通过心跳包机制的,而心跳包是频繁的发送,心跳包又包含了该节点的各种信息包括所持有的槽。当槽的个数是16384的时候,位图的大小为2kb,但如果槽的个数是65535的时候,此时的位图大小将来到恐怖的8kb,虽然这对于内存不算什么,但是在网络中,仍然是一个不晓得开销
  • 另一方面,Redis集群一般不会超过1000个分片,所以16k对于最大1000个分片的下的情景是足够使用的,同时对应的槽的体积也不会很大

 

  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Obto-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值