传统Hash,通常会将K个元素通过一个Hash函数映射到n各槽位,Hash函数通常是取模方式(K mod n),但如果n个槽位进行调整的情况下(比如删除和新增一个槽位),几乎所有的关键字都需要重新映射;
一致性Hash也是Hash一种,解决传统Hash的上述问题,在很多分布式缓存系统应用中,像Memcache、Redis集群都有应用到一致性Hash的应用
概述
Hash背景
一致的散列通常用于将请求分发到一组不断变化的服务器。例如,假设有一些缓存服务器cacheA,cacheB和cacheC。若你想要决定使用哪个缓存服务器来查找用户的信息。
我们通常可以使用典型的哈希表并将用户ID哈希到cacheA,cacheB或cacheC之一。
但是使用典型的哈希表,如果添加或删除服务器,几乎所有键都将被重新映射到不同的结果,这基本上可以在缓存重建时使您的服务暂停。
使用一致的哈希,添加或删除服务器会大大减少重新映射的键数。
一致性Hash解决的问题
使用n台缓存服务器,对资源o的请求使用hash(o)= o mod n
方式来映射到某一台缓存服务器,以便实现资源的负载均衡,当从n中增加缓存节点或者剔除缓存节点会导致资源o重新映射,使得缓存服务器大量集中地向原始内容服务器更新缓存
因此需要一致哈希算法来避免这样的问题:
- 新增一台缓存节点,尽可能的使同一资源被映射到同一个缓存节点
- 剔除一台缓存节点,将被剔除节点上的缓存资源重新hash,但应该尽可能少的操作
一致性Hash的实现
- 一致哈希将每个对象映射到圆环边上的一个点,系统再将可用的节点机器映射到圆环的不同位置;
- 基于资源对象o查找节点则使用一致哈希算法计算得到对象对应圆环边上位置,沿着圆环边上查找直到遇到某个节点机器,这台机器即为对象应该保存的位置;
- 若圆环上的节点剔除,则机器上的缓存所有对象都要移动到下一台机器;
- 若圆环上的节点增加,新增节点的下一台机器需要转移其上的资源对象移动到新机器上;
一致性哈希算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。