zoukankan      html  css  js  c++  java
  • 聊聊一致性hash算法的原理

    https://mp.weixin.qq.com/s/BnErT5xrPpq76A4qUEyQCw

    工程师经常使用服务器的集群来设计和实现数据缓存,他们常见的策略是:

    1:不管是添加,删除和查询数据,都是先将数据的id通过hash函数生成一个hash值,记为key。

    2:如果有N台机器,则会计算key%N的值,这个值就是所属机器的编号,无论是添加,删除和查询数据,都是在这台机器上操作。

    请分析上面的策略存在的问题,并提出解决的方案。

    2解答

    1:首先来想下在什么情况下会产生问题。一般情况下,在不增加机器的情况下,产生的hash值相同,那么就会在某一台机器上操作,不会产生什么问题,但是如果增加或者删除了机器,即N变化的时候,代价就会比较高,所有的数据都需要根据id重新计算一次hash值,并通过hash值对新的机器进行重新取模操作,然后对数据进行大规模的迁移。

    2:那么为了解决这些问题,我们就引入了一致性hash算法,这是一种很好的数据缓存解决方案。

    假设通过id生成的hash值是0到(2^32)-1 的范围,那么我们可以想象成一个闭合的圆,一个数据id计算出的hash值就是对应圆中的某一个位置,如图所示

    当采用一致性哈希算法,把分布式集群中新的机器加入。其原理是通过使用与对象存储一样的Hash算法将机器也映射到圈中(一般情况下对机器的hash计算是采用机器的IP或者唯一的别名作为输入值),当数据和机器同时属于这个圈的时候,一条数据如何确定归属到哪台机器呢?

    首先把该数据的id用hash算法计算出hash值之后,映射到圈中的相应位置上,然后以顺时针的方向查找,将对象存储到离自己最近的机器中,那台机器就是该数据的归属。

    假设现在有三台机器中,通过hash算法得到对应的KEY值,分别是KEY1,KEY2,KEY3,映射到环中,其示意图如下

    object1算出的hash值是key1,顺时针查找的第一台机器是大写的KEY1,key3顺时针查找的第一台机器是大写的KEY2,key2和key4顺时针查找的第一台机器是大写的KEY3。

    3:节点的添加

    假设有两台机器,大写的KEY1和大写的KEY3和四个数据key1,key2,key3,key4,如上图所示,此时key1属于KEY1的归属,key2,key3,key4属于KEY3的归属。

    如果此时插入机器(大写的KEY2),假如计算出机器的hash值在key3和key2的中间,当添加KEY2的时候,key3的旧数据就要迁移到KEY2上,只迁移了一个数据,由此可见,添加机器时调整的代价是比较小的,同理在删除机器的时候,只要把删除机器的数据全部复制到顺时针找到的下一台机器即可。

    4:根据上面的图解分析,一致性哈希算法满足了单调性和负载均衡的特性以及一般hash算法的分散性,但这还并不能当做其被广泛应用的原由,因为如果机器在整个圈上的分布不均匀,就会导致机器之间的负载不均衡。

    为了解决这种数据分布不均匀的问题,一致性hash算法引入了虚拟节点机制,即对每一台机器通过hash算法计算出多个hash值,比如object1,object2,通过hash(object1),hash(object1-1),hash(object2),hash(object2-1),对多个位置放置一个服务节点,叫做虚拟节点。

    具体的做法可以是在机器ip或主机名后面添加编号或端口号实现,如下图,若去掉KEY3-2和KEY1-2机器,那么此时key3,key2,key4是分配个机器KEY3-1的,key1是属于机器KEY1-1的,对象在机器上的分布很不均衡。

    现在我们添加2个副本(添加了KEY3-2和KEY1-2)为例,这样整个hash环就存在4个虚拟节点,根据hash函数的性质,节点多了,平衡性就会变好一些。

    5:总结

    我们一步步分析了什么是一致性Hash算法,主要是考虑到分布式系统每个节点都有可能失效,并且新的节点很可能动态的增加进来的情况,如何保证当系统的节点数目发生变化的时候,我们的系统仍然能够对外提供良好的服务,这是值得考虑的

  • 相关阅读:
    [HNOI2002]营业额统计
    HDU 1374
    HDU 3345
    HDU 2089
    Graham扫描法
    Codeforces 1144D Deduction Queries 并查集
    Codeforces 916E Jamie and Tree 线段树
    Codeforces 1167F Scalar Queries 树状数组
    Codeforces 1167E Range Deleting
    Codeforces 749E Inversions After Shuffle 树状数组 + 数学期望
  • 原文地址:https://www.cnblogs.com/eryun/p/12158038.html
Copyright © 2011-2022 走看看