一致性 Hash 算法

       一致性哈希算法在分布式缓存领域的 MemCached,负载均衡领域的 Nginx 以及各类 RPC 框架中都有广泛的应用。它主要是为了解决传统哈希函数添加哈希表槽位数后要将关键字重新映射的问题。普通的哈希表算法一般都是计算出哈希值后,通过取余操作将 key 值映射到不同的服务器上但是当服务器数量发生变化时,取余操作的除数发生变化,所有 key 所映射的服务器几乎都会改变,这对分布式缓存系统来说是不可以接收的。一致性哈希算法能尽可能减少了服务器数量变化所导致的缓存迁移。

哈希算法

      首先,一致性哈希算法依赖于普通的哈希算法。哈希算法有很多种实现,它们在不同方面都各有优劣,针对不同的场景可以使用不同的哈希算法实现。

  • MD5 算法:全称为 Message-Digest Algorithm 5,用于确保信息传输完整一致。是计算机广泛使用的杂凑算法之一,主流编程语言普遍已有 MD5 实现。MD5 的作用是把大容量信息压缩成一种保密的格式(就是把一个任意长度的字节串变换成定长的16进制数字串)。常见的文件完整性校验就是使用 MD5。
  • CRC 算法:全称为 Cyclic Redundancy Check,中文名称为循环冗余校验。它是一类重要的,编码和解码方法简单,检错和纠错能力强的哈希算法,在通信领域广泛地用于实现差错控制。
  • MurmurHash 算法:高运算性能,低碰撞率,由 Austin Appleby 创建于 2008 年,现已应用到 Hadoop、libstdc++、nginx、libmemcached 等开源系统。Java 界中 Redis,Memcached,Cassandra,HBase,Lucene和Guava 都在使用它。
  • FNV 算法:全称为 Fowler-Noll-Vo 算法,是以三位发明人 Glenn Fowler,Landon Curt Noll,Phong Vo 的名字来命名的,最早在 1991 年提出。 FNV 能快速 hash 大量数据并保持较小的冲突率,它的高度分散使它适用于 hash 一些非常相近的字符串,比如 URL,hostname,文件名,text 和 IP 地址等。
  • Ketama 算法:一致性哈希算法的实现之一,其他的哈希算法有通用的一致性哈希算法实现,只不过是替换了哈希映射函数而已,但 Ketama 是一整套的流程。

一致性哈希算法

.简单来说,一致性哈希将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数H的值空间为0 - 2^32-1(即哈希值是一个32位无符号整形)。整个哈希空间环如下:

                                                                        

      整个空间按顺时针方向组织。0和2^32-1在零点中方向重合。下一步将各个服务器使用H进行一个哈希,具体可以选择服务器的ip或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置。这里假设将上文中三台服务器使用ip地址哈希后在环空间的位置如下:

                                                                    

       接下来使用如下算法定位数据访问到相应服务器:将数据key使用相同的函数H计算出哈希值h,通根据h确定此数据在环上的位置,从此位置沿环顺时针“行走”,第一台遇到的服务器就是其应该定位到的服务器。例如我们有A、B、C、D四个数据对象,经过哈希计算后,在环空间上的位置如下:

                                                                    

      根据一致性哈希算法,数据A会被定为到Server 1上,D被定为到Server 3上,而B、C分别被定为到Server 2上。现假设Server 3宕机了:可以看到此时A、C、B不会受到影响,只有D节点被重定位到Server 2。一般的,在一致性哈希算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即顺着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。   

       如果我们在系统中增加一台服务器Memcached Server 4:此时A、D、C不受影响,只有B需要重定位到新的Server 4。一般的,在一致性哈希算法中,如果增加一台服务器,则受影响的数据仅仅是新服务器到其环空间中前一台服务器(即顺着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响。

                                                                     

       综上所述,一致性哈希算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。

虚拟节点

       一致性哈希算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜问题。例如我们的系统中有两台服务器,其环分布如下:此时必然造成大量数据集中到Server 1上,而只有极少量会定位到Server 2上。为了解决这种数据倾斜问题,一致性哈希算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希,每个计算结果位置都置一个此服务节点,称为虚拟节点。

                                                                      

      具体做法可以在服务器ip或主机名的后面增加编号来实现,例如上面的情况,我们决定为每台服务器计算三个虚拟节点。我们可以分别计算下面节点的哈希值:

  • “Memcached Server 1#1”
  • “Memcached Server 1#2”
  • “Memcached Server 1#3”
  • “Memcached Server 2#1”
  • “Memcached Server 2#2”
  • “Memcached Server 2#3”

于是形成六个虚拟节点:

                                                                   

同时数据定位算法不变,只是多了一步虚拟节点到实际节点的映射,例如定位到下面三个虚拟节点的数据均定位到Server 1上。

  • “Memcached Server 1#1”
  • “Memcached Server 1#2”
  • “Memcached Server 1#3”

       这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值