一致性Hash算法
场景
如果有N个缓存服务器,将一个对象缓存到某个服务器上,也许可以这样计算对象的hash值,然后映射到某个cache上:
hash(object) % N
这样做存在这两个问题:
- 如果其中一台服务器发生故障或者被移除,则映射到该服务器上的所有对象都会失效,而且映射公式就变为:
hash(object) % (N-1) - 相反,如果缓存已经不满足需求,需要增加缓存服务器时,映射公式变为:
hash(object) % (N+1)
这就意味着几乎所有的cache都会失效,也有两种解决方案:
- 清空所有缓存服务器,重新建立缓存。本来缓存就是为了减小数据库压力而设计的,这样做对后端来说,如同一场灾难,严重的可能会到时数据库崩溃。所以,一般应该不会这样做。
- 夜深人静,流量最小的时候,使缓存服务器中的数据重新分布。
这两种做法的成本都非常大。
一致性hash算法
基本原理
简单来说,一致性hash算法主要做的就是在添加或者移除一个缓存服务器的时候,能够尽可能小的改变已存在的映射关系。一致性hash算法用的也是取模的方法,只不过是对2^32取模:
- 先构造一个0~2^32-1的整数环,也称一致性hash环,也可以把它看成一个首尾相接的圆环
- 根据节点服务器的名称计算hash值,对hash值进行取模,然后将服务器节点放置在hash环上
- 根据需要缓存数据的key值计算hash值,对hash值进行取模,接着在hash环上顺时针查找离这个值最近的服务器节点
- 完成映射查找
虚拟节点
同样一致性hash算法也有缺点,在实际映射中,有可能缓存服务器会被映射到环上的其中一段弧上,这就造成大部分对象可能会集中缓存到某一台服务器上,这就诞生了虚拟节点。
虚拟节点就是实际节点的一个影子,或者说是复制品,一个实际节点对应多个虚拟节点,同样将虚拟节点映射到hash环上,这样一来缓存的分布就均衡多了,减少hash环的偏斜所带来的影响。
hash环上的节点越多,缓存被均匀分布的概率也就越大
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ansore!





