曂沅仴駦 发表于 2024-10-2 09:34:44

[Redis][集群][上]详细解说

0.前言



[*]说明:该章节相干操作不需要记忆,理解流程和原理即可,用的时间能自主查到即可
1.根本概念



[*]哨兵模式提高了体系的可用性,但是真正用来存储数据的还是master和slave节点,所有的数据都需要存储在单个master和slave节点中

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

[*]怎样获取更大的空间?

[*]加机器即可
[*]所谓”大数据”的核心,其实就是一台机器搞不定了,用多台机器来搞定

[*]Redis集群就是在上述的思路下,引入多组Master/Slave,每组Master/Slave存储数据全集的一部分,从而构成一个更大的整体,称为Redis集群(Cluster)
[*]假定整个数据全集是1TB,引入三组Master/Slave来存储,那么每一组机器只需要存储整个数据全集的                                        1                            /                            3                                  1/3                     1/3即可

[*]三组机器存储的数据都是差异的
[*]每个Slave都是对应Master的备份,当Master挂了,对应的Slave会补位成Master
[*]每个红框部分都可以称为是一个**分片**(Sharding)

[*]如果全量数据进一步增加,只要再增加更多的分片,即可解决

[*]示例:

[*]Master1和Slave11和Slave12保存的是同样的数据,占总数据的                                                            1                                        /                                        3                                                1/3                                 1/3
[*]Master2和Slave21和Slave22保存的是同样的数据,占总数据的                                                            1                                        /                                        3                                                1/3                                 1/3
[*]Master3和Slave31和Slave32保存的是同样的数据,占总数据的                                                            1                                        /                                        3                                                1/3                                 1/3
https://i-blog.csdnimg.cn/direct/ae34fdfafbd74e9c8d934b26a0a8466b.png


2.数据分片算法

0.前言



[*]Redis Cluster的**核⼼思路是⽤多组机器来存数据的每个部分**
[*]那么接下来的核⼼问题就是,给定⼀个数据(⼀个具体的key),那么这个数据应该存储在哪个分⽚上? 读取的时间⼜应该去哪个分片读取?
1.哈希求余



[*] 设有N个分片,利用进行编号

[*]针对某个给定的key,先计算hash值,再把得到的结果%N,得到的结果即为分片编号
[*]后续如果要取某个key的值,也是针对key进行hash,再对N求余,就可以找到对应的分片编号了
https://i-blog.csdnimg.cn/direct/12debd279b744b988faaaef6f3095bcf.png

[*] 优点:简单高效,数据分配匀称
[*] 缺点:一旦需要进行扩容,N改变了,原有的映射规则被破坏,就需要让节点之间的数据互相传输,重新排列,以满足新的映射规则,此时需要搬运的数据量是比力多的,开销较大
https://i-blog.csdnimg.cn/direct/cb5e727e42ed4dc4aab1523c6aac5cc4.png
2.一致性哈希算法



[*] 为了低落上述的搬运开销,能够更高效扩容,业界提出了”一致性哈希算法”
[*] 本质区别:

[*]在哈希求余中,当前key属于哪个分片,是瓜代的
[*]在一致性哈希下,把瓜代出现,改进成了连续出现,此时就低落了需要搬运数据的可能

[*] key映射到分片序号的过程不再是简单求余了,而是改成以下过程:

[*] 把                                                       0                                              0                              0 ->                                                                      2                                        32                                                −                                     1                                              2^{32} - 1                              232−1这个数据空间,映射到一个圆环上,数据按照顺时针方向增长
https://i-blog.csdnimg.cn/direct/fa3eb1cb24f2462ab36cecc38571ca05.png
[*] 假设当前存在三个分片,就把分片放到圆环的某个位置上
https://i-blog.csdnimg.cn/direct/993d1d9676744a00a6d94b27c7c9f2c8.png
[*] 假定有一个key,计算得到hash值H,那么这个key映射到哪个分片呢?

[*] 从H所在位置,顺时针往下找,找到的第一个分片,即为该key所从属的分片
https://i-blog.csdnimg.cn/direct/ec7741904cd14008ad86fa2608f4b8f6.png
[*] 这就相称于,N个分片的位置,把整个圆环分成了N个管辖区间,key的hash值落在某个区间内,就归对应区间管理
https://i-blog.csdnimg.cn/direct/26e0cd96ce724d09a62aaba989b0e4a6.png

[*] 如果扩容一个分片,怎样处理呢?

[*]原有分片在环上的位置不动,只要在环上新安排一个分片位置即可
[*]此时只需要把0号分片上的部分数据,搬运给3号分片即可,1号分片和2号分片管理的区间都是稳定的
https://i-blog.csdnimg.cn/direct/596a5e439a544bab81d2161f7010cc69.png


[*] 优点:大大低落了扩容时数据搬运的规模,提高了扩容操作的服从
[*] 缺点:数据分配不匀称 -> 有的多有的少,数据倾斜
3.哈希槽分区算法(Redis利用)



[*]为了解决上述问题(搬运成本高和数据分配不匀称),Redis Cluster引入了哈希槽(hash slots)算法
[*]本质:把哈希求余和一致性哈希的
[*]hash slots:

[*]说明:

[*]crc16也是一种hash算法
[*]                                                            16384                                                16384                                 16384是                                                            16                                        ∗                                        1024                                                16 * 1024                                 16∗1024,即16K,为                                                                           2                                           14                                                                2^{14}                                 214

[*]解释:

[*]相称于把整个哈希值,映射到                                                            16384                                                16384                                 16384个槽位上,也就是
[*]然后再把这些槽位比力匀称的分配给每个片,每个分片的节点都需要记录自己持有哪些分片

[*]这里的分片规则是很灵活的,每个分片持有的槽位也不肯定连续
[*]每个分片的节点利用位图来表现自己持有哪些槽位,对于                                                16384                                          16384                           16384个槽位而言,需要2048个字节(2KB)巨细的内存空间表现
[*]如果需要扩容,比如新增一个3号分片,就可以针对原有的槽位进行重新分配

[*]把之前每个分片持有的槽位,各拿出一点,分给新分片

hash_slot = crc16(key) % 16384

[*]示例:

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

[*]0号分片:,共5462个槽位
[*]1号分片:,共5462个槽位
[*]2号分片:,共5460个槽位

[*]此时扩容了一个分片,一种可能的分配方式:

[*]0号分片:,共4096个槽位
[*]1号分片:,共4096个槽位
[*]2号分片:,共4096个槽位
[*]3号分片: + + ,共4096个槽位


[*]在实际利用Redis集群分片的时间,不需要手动指定哪些槽位分配给某个分片,只需要告诉某个分片应该持有多少个槽位即可,Redis会自动完成后续的槽位分配,以及对应的key搬运的工作
[*]两个问题:

[*]Redis集群是最多有16384个分片吗?

[*]并非云云,如果一个分片一个槽位,这对于集群的数据匀称是难以保证的
[*]实际上,Redis作者建议集群分片数不应该超过1000
[*]而且,16000这么大规模的集群,自己的可用性也是一个大问题

[*]一个体系越复杂,出现故障的概率就越高


[*]为什么是16384个槽位?

[*]Redis作者的答案
[*]节点之间通过⼼跳包通信,⼼跳包中包罗了该节点持有哪些slots,这个是使⽤位图这样的数据结构表⽰的

[*]表⽰16384(16k)个slots,需要的位图⼤⼩是2KB,如果给定的slots数更多了,⽐如65536个了,此时就需要斲丧更多的空间,如8KB位图表⽰了
[*]8KB对于内存来说不算什么,但是在频繁的⽹络⼼跳包中,还是⼀个不⼩的开销的

[*]另⼀⽅⾯,Redis集群⼀般不建议超过1000 个分⽚,所以16k对于最⼤1000个分⽚来说是⾜够⽤的,同时也会使对应的槽位设置位图体积不⾄于很⼤



免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: [Redis][集群][上]详细解说