在分布式存储系统中,数据会分布存放在各个数据节点上。那么数据来的时候,应该选择哪个节点存储数据,查询时又应该去哪个节点上找是一个很重要的问题。除此之外,增加新节点 或 老节点挂掉后,如何转移数据,也是需要关注的问题。一致性hash 和 哈希槽就是为了解决上述的两大问题。
一、一致性哈希
1.1 基本原理
一致性hash是一个2^32位的圆环,节点按照ip 哈希后,映射到环上。数据按照 key哈希后,也映射到环上。然后每个数据沿顺时针方向,在环上找最近的节点。
1.2 雪崩
当一个节点挂掉 或被删除时,此节点的数据全部交给下一个节点。如上图中 node1 挂掉后,node1的数据会全部转移给 node2。 如此以来,node2 的负载会骤增,很容易崩掉。如果 node2崩掉了,那么 原 node1 和 node2的数据都会转给 node4。node4的压力更大,更容易挂掉,以此类推。
1.3 数据倾斜
hash算法没法保证节点均匀的分布在环上,因此当节点个数很少时,可能出现下图的情况。这样大部分数据会放在node1上,只有少部分数据会放在node2上。
1.4 虚拟节点
每个节点对应 K 个虚拟节点,来解决上面的 “雪崩”和“数据倾斜”问题。比如下图,每个节点对应两个虚拟节点,将虚拟节点 hash映射到环上。由于节点变多了,节点的分布会变得均匀一些,解决了数据倾斜的问题。
当节点2 挂掉后,v201 和 v200这两个虚拟节点也会一起挂掉。v201上的数据会转移给 v100(即节点1);v200上的数据会转移给 v300(即节点3)。如此以来节点 2 和 节点 3 共同分担了节点1 的负载。
二、哈希槽(hash slot)
2.1 一致性哈希的问题
- 当节点很多时,查询效率较低
- 需要一个中心服务器,来计算数据应该放到哪个节点
2.2 哈希槽
redis 集群划分了 2^14(16384)个槽,每个节点对应固定范围的槽区。比如下图中,master1 负责0-2000的槽区,master2负责2000-8000的槽区....
ps:这里的master 和 slave 是集群的主备模式。数据仅在master节点内进行读写,当master挂了,slave中会选举出一个新的master节点。
初始时,槽区会被均匀的分给各master节点。
删除master节点时,先把其下面的slave节点摘掉,然后把槽区转给其他master节点,才能删除此节点。新增master节点也需要手动分配槽区,不然无法存储数据。
2.3 去中心化
redis相比于hbase等其他分布式存储有一大优势,就是利用哈希槽,实现了去中心化存储。
其他的比如hive存储的时候,其实还是需要有一台服务器来存储所有的元数据。那么这台中心服务器的大小就限制了集群中可以存储的数据总量。
而redis使用去中心化的哈希槽,每台机器上都存放一张“槽区-节点”对应表,并约定好使用的hash算法。如此一来,数据可以随机选择一个节点访问,在此节点上根据数据的key计算出应该存放的节点,并跳转。
reference :https://www.jianshu.cm/p/4163916a2a8a