之前听说过一致性哈希这个概念,但是没理解应用场景。最近重新看分布式系统才发现,其实很早以前就思考过一个分布式缓存系统的问题:当有多个缓存服务器,如果用户请求的响应内容缓存在缓存服务器A,但是这次请求访问到了缓存服务器B,怎么办呢?要保证所有缓存服务器都能命中,岂不是所有数据都要冗余一份么。
当时的疑问卡在那儿,就没继续想。现在看到一致性哈希恍然大悟,一致性哈希正是可以解决分布式缓存的问题。
环形构想
1.设计一个环形结构,分隔成 2^32=16384 份(slots),来源任何一个key值(暂且简单叫key值,实际上是一个用户请求内容),把key哈希,然后把哈希值对16384取模,找到这个模值在环形上的位置(slot)。如下图
2.同样的方式,把缓存浏览器的ip地址(暂时简单叫 node)也都哈希,然后把哈希值对16384取模,也找到这个模值在环形上的位置(slot)。如下图
3.key命中node的方式是,延环形架构顺时针找到最近的node,即这个请求就访问到这个缓存服务器。
优势
这样做的好处显而易见,尤其是这种设计的单调性。当然还有一些其他特性
- 单调性(Monotonicity):增加缓存服务器或者删除缓存服务器(node)的时候,只会影响到下一个或上一个node(所有数据都会写入顺时针的最近缓存分区),而不会影响到其他缓存节点。这比起普通哈希的方式优化了很多。
- 平衡性(Balance):哈希算法的特性,能使keys尽可能平衡分部再各nodes
- 降低分散性(Spread):记得开篇的问题么,如果不用哈希,几乎做不到让相同的请求命中同一缓存节点,甚至需要各节点冗余缓存数据。而哈希可以使得数据集中存在特定缓存节点,而且请求可以相应命中
- 降低负载(Load):和上述分散性类似,既然可以做到不再冗余数据,相应的负载也就降低了
优化
大家看到这里已经会发现了,那如果缓存节点的ip哈希映射到环形结构的时候,分布恰好非常不均匀,从而导致大量数据都映射在了某几个节点上,怎么办呢?
解决办法是,我们可以根据每个真实的缓存节点ip,创造一些与之对应的虚拟ip,也加入环形,使得数据分配到各真实缓存节点ip的时候基本是均衡的。
参考文献:
https://blog.csdn.net/cywosp/article/details/23397179
https://www.jianshu.com/p/49e3fbf41b9b