Redis(二)-----数据分区 : https://cloud.tencent.com/developer/article/1744809
Redis(三)-----集群方案 : https://cloud.tencent.com/developer/article/1744811
Redis(四)-----持久化 : https://cloud.tencent.com/developer/article/1744791
Redis(五)-----应用场景 : https://cloud.tencent.com/developer/article/1744816
Redis(六)-----缓存穿透/缓存雪崩/缓存击穿 : https://cloud.tencent.com/developer/article/1744796
Redis(七)—淘汰删除策略 : https://cloud.tencent.com/developer/article/1744827
分布式数据库首先要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整体数据的一个子集。
数据分布通常有 哈希分区 和 顺序分区 两种方式, 如下:
使用特定的数据,如Redis的键或用户ID,再根据节点数量 N 使用公式:hash(key)% N 计算出 哈希值,用来决定数据 映射 到哪一个节点上。
优点:
这种方式的突出优点是简单性,常用于数据库的分库分表规则。一般采用预分区的方式,提前根据数据量规划好分区数,比如划分为 512 或 1024 张表,保证可支撑未来一段时间的数据容量,再根据负载情况将表迁移到其他数据库中。扩容时通常采用翻倍扩容,避免数据映射全部被打乱,导致全量迁移的情况。
缺点:
当节点数量变化时,如扩容 或 收缩 节点,数据节点映射关系 需要重新计算,会导致数据的重新迁移。
通过#3.1 节点求余分析了它的劣势,当节点数发生变动的时候,几乎所有的数据都会移动(不移动的应该是运气比较好吧前后取模都是同一个值),这个代价很大。此时的问题从水平如何拆分变成了,当增加或者删除节点时,对于大多数记录,保证原来分配到的某个节点,现在仍然应该分配到那个节点,将数据迁移量的降到最低,这就是一致性哈希要做的事情。
一致性 Hash 算法也是使用取模的思想,只是,刚才描述的取模法是对节点数量进行取模,而一致性Hash算法是对 2^32 取模,什么意思呢?简单来说,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0-2^32-1(即哈希值是一个32位无符号整形),整个哈希环如下,从 0 ~ 2^32-1 代表的分别是一个个的节点,这个环也叫哈希环
然后我们将我们的节点进行一次哈希,按照一定的规则,比如按照 key的哈希值,让节点落在哈希环上。比如此时我们可能得到了如下图的环:
然后就是需要通过数据 key 找到对应的服务器然后存储了,我们约定,通过数据 key 的哈希值落在哈希环上的节点,如果命中了机器节点就落在这个机器上,否则落在顺时针直到碰到第一个机器。如下图所示 : A 的哈希值落在了 D2 节点的前面,往下找落在了 D2 节点上,D的哈希值 在 D1 节点的前面,往下找到了 D1 节点,B的哈希值刚好落在了D1 节点上,依次~~~
一致性哈希主要就是解决当机器减少或增加的时候,大面积的数据重新哈希的问题,主要从下面 2 个方向去考虑的,当节点宕机时,数据记录会被定位到下一个节点上,当新增节点的时候 ,相关区间内的数据记录就需要重新哈希。
优点:
加入 和 删除 节点只影响 哈希环 中 顺时针方向 的 相邻的节点,对其他节点无影响。
缺点:
一致性Hash算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题。比如只有 2 台机器,这 2 台机器离的很近,那么顺时针第一个机器节点上将存在大量的数据,第二个机器节点上数据会很少。如下图所示,D0 机器承载了绝大多数的数据
。
虚拟槽分区巧妙地使用了哈希空间,使用分散度良好的哈希函数把所有数据映射到一个固定范围的整数集合中,整数定义为槽(slot)。这个范围一般远远大于节点数,比如 Redis Cluster 槽范围是 0 ~ 16383。Redis 集群包含了 16384 个哈希槽,每个 Key 经过计算后会落在一个具体的槽位上,而每个槽位落到哪个节点上,根据自己的节点配置,如图所示:
假设,当前集群有 5 个节点,每个节点平均大约负责 3276 个槽。由于采用高质量的哈希算法,每个槽所映射的数据通常比较均匀,将数据平均划分到 5 个节点进行数据分区。Redis Cluster 就是采用虚拟槽分区。
节点1: 包含 0 到 3276 号哈希槽。
节点2:包含 3277 到 6553 号哈希槽。
节点3:包含 6554 到 9830 号哈希槽。
节点4:包含 9831 到 13107 号哈希槽。
节点5:包含 13108 到 16383 号哈希槽。
注意一个思想,槽位是落在节点上的,且我们可以任意配置那些槽位落在哪个节点上
这种结构很容易添加或者删除节点。如果增加一个节点 6,就需要从节点 1 ~ 5 获得部分槽分配到节点 6 上。如果想移除节点 1,需要将节点 1 中的槽移到节点 2 ~ 5 上,然后将没有任何槽的节点 1 从集群中移除即可。
由于从一个节点将 哈希槽 移动到另一个节点并不会 停止服务,所以无论 添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态.
Redis Cluster 采用虚拟槽分区(Redis Cluster是Redis自带的集群),所有的键根据哈希函数映射到 0~16383 整数槽内,计算公式:slot = CRC16(key)& 16383。每个节点负责维护一部分槽以及槽所映射的键值数据,如图所示: