总结
分布式数据库首先要解决把整个数据集按照分区规则映射到多个节点的问题,即把数据集划分到多个节点上,每个节点负责整体数据的一个子集。
数据分布有三种方式:
- 逻辑拆分
- 哈希分区
- 固定取模分区
- 一致性哈希
- 虚拟槽分区
- 顺序分区
一、逻辑拆分
逻辑上能拆分,比如 Redis 中的 M1 节点 存储 A服务需要的业务数据,而 Redis 中的 M2 节点存储 B服务需要的业务数据。
二、哈希分区
当逻辑上不能拆分,那么只能按数据来拆分,需要保证客户端读和写数据一致。
因此需要一个高效快速的数据结构来路由对应的Master节点。
最容易想到的就是类比 Java 中的 HashMap, 采用 哈希算法分区,快速找到,快速设置。
2.1 固定取模分区
使用特定的数据(包括redis的键或用户ID),再根据节点数量N,使用公式:hash(key)%N计算出一个0~(N-1)值,用来决定数据映射到哪一个节点上。即哈希值对节点总数取余。余数x,表示这条数据存放在第(x+1)个节点上。
缺点:
- 当节点数量N变化时(扩容或者收缩),数据和节点之间的映射关系需要重新计算。这样的话,所有的数据几乎要全部洗牌,要按照新的规则映射:要么之前存储的数据找不到,要么之前数据被重新映射到新的节点(导致以前存储的数据,需要发生数据迁移,相当麻烦)
- 意味着Redis在此种用法下,只能当缓存,不能当存储数据库!
2.2 一致性哈希
详见:Redis - 一致性哈希(Consistent Hashing Algorithm)
一致性哈希算法介绍
- 将整个哈希值空间组织成一个虚拟的圆环,整个空间按顺时针方向组织。hash的值空间一般为0~232-1次方 -- 为什么一致性哈希值空间是2的32?
- 先将各个服务器使用Hash进行一个哈希(可以选择服务器的ip或主机名作为关键字进行哈希),这样每台机器就能确定其在哈希环上的位置
- 将数据key使用相同的函数Hash计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器。
一致性哈希优点
- (1)扩展性:当增加节点时,只会影响顺时针的真实节点(此部分数据比较难迁移),而不是影响全部的节点。
- (2)容错性:当节点宕机或删除节点时,只会影响逆时针的真实节点,而不是影响全部的节点。
- (3)平衡性:当哈希算法的节点过少时,会可能造成某些服务器的数据存储较多,而另外一些存储较少,造成数据倾斜,当节点足够多时,这种现象得以缓解。因此虚拟节点个数较大的时候,数据的平衡性得以保证。
一致性哈希缺点
- 因为当增删节点时,需要重新计算受影响部分的节点中的key全部找出来,才能迁移,这个很麻烦!!!
- Redis在此种用法下,也只能当缓存,不能当存储数据库!
2.3 哈希槽分区(PreSharding,预先分片)
三、顺序分区
顺序分布就是把一整块数据分散到很多机器中,如下图所示。
正常顺序分区是按照平均分配的规则,当然也可以根据不同机器分配,内存大一点的可以多分配一些。
3.1 顺序分区 vs 哈希分区
参考文献
自有永有 - https://blog.csdn.net/qq_36324113/article/details/90727355
Redis 集群演进探讨和总结 - https://segmentfault.com/a/1190000022718948