什么场景下需要一致性Hash? 首先我们先来看一个场景,我们需要对海量的用户数据进行切片存储。这样我们就需要在后端挂接多个存储服务,每个存储服务存储一部分用户的数据。其中如何对用户进行分配?
最简单的做法就是对用户ID的Hash值按照存储服务的数量取余。根据余数可确定分配到哪个存储服务上(余数即为存储服务的索引值)。但这样有一个问题,如果我们要对存储服务进行节点扩容,比如增加一个节点会面临大部分数据甚至所有数据的搬迁工作。需要从某一台存储服务将用户的数据根据新的分配策略搬迁到其他存储服务上。这显然存在很大的性能问题,不是我们希望的方案。
解决这个问题,需要用到一致性Hash。 如下图(图片来自:https://www.cnblogs.com/lpfuture/p/5796398.html)
一致性Hash
顾名思义,就是在集群节点扩缩容的时候保持原有数据或者大部分数据的哈希散列分布保持一致,这样可以有效避免因为服务集群节点扩缩容导致的大部分数据的重新哈希分布计算和搬迁的性能问题。一致性Hash环将服务几点分不到从0至2^32-1之间的某个节点上,将要分配的节点根据hash值按照顺时针方向找到最近的节点。如上图所示,粉色节点会分配到红色虚线箭头指向的node节点上。在进行节点增加例如在原本只有四个节点(node1、node2、node3、node4)的情况下增加node5节点时,Hash的分布只会影响到node2和node5之间的项。
上面的一致性Hash环中node节点是实际的服务节点。由于Node节点本身的分布也相对来说是随机的,对于数据较少的node节点,由于相邻节点的距离不均匀会导致节点分配不均匀。为了解决这个问题,可以采用虚拟节点(一般采用150个左右)的一致性Hash环结构来进行优化。node节点映射到相同数量的虚拟节点,从而达到整体节点分布的均匀。