一致性哈希原理
分布式系统将数据分布到不同的节点来存储,比如一个分布式KV(key-value)缓存系统,某个key应该到哪个节点上获得,最直观的方法是使用哈希算法(hash(key)%n),对key进行哈希后用模运算映射到某个确定的节点。
但是会存在一个很致命的问题:如果节点数量发生了变化,也就是在对系统做扩容或者缩容时,必须迁移改变了映射关系的数据,否则会出现查询不到数据的问题。最坏的情况是所有数据都需要迁移。
为了避免这个问题,引入了一致性哈希,来解决分布式系统在扩容或者缩容时发生过多的数据迁移的问题。与哈希算法不同的是,哈希算法是对节点的数量进行取模运算,而一致哈希算法是对 2^{32} 进行取模运算,是一个固定的值。可以把一致哈希算法是对 2^32 进行取模运算的结果值组织成一个圆环(哈希环)。一致性哈希会将存储节点(如其IP地址)和数据分别经过不同的哈希映射到哈希环上。在数据映射时根据结果值往顺时针方向找到的第一个节点,就是存储该数据的节点。
其优势在于,增加或者减少一个节点,只会影响该节点在哈希环上顺时针相邻的后继节点,其他数据都不会收到影响。举例来说:
- 如果B右侧增加节点D:将A-D范围内的数据从B迁移到D节点(可以参考写时拷贝的方式,如等到D节点查询该数据时,如果找不到,就去B节点找,找到后再迁移到D节点来,但这种方式仅适用于节点变动不大的情况,不然不断积累会严重影响查找效率。)
- 如果删除B节点:将B节点上的数据全都迁移到C节点。
一致性哈希存在的问题和解决方法
主要问题是无法保证节点在哈希环上均匀分布,可能出现大量请求集中在同一个节点上,导致该节点崩溃,其后继节点将独自承受该节点转交的工作量,容易引起雪崩式的连锁反应。
解决方案是引入虚拟节点,也就是不再将真实节点映射到哈希环上,而是将虚拟节点映射到哈希环上,并将虚拟节点映射到实际节点
- 第一方面通过增加节点数量提高哈希环上节点分布均衡性;
- 第二方面当节点变化时,会有不同的节点共同分担系统的变化,提高系统的稳定性;
- 第三方面可以为硬件配置更好的节点增加权重,如对权重更高的节点增加更多虚拟节点。