分布式一致性hash算法简介

当你看到“分布式一致性hash算法”这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么。在分析分布式一致性hash算法原理之前,我们先来了解一下这几个概念。

分布式

分布式(distributed)是指在多台不同的服务器中部署不同的服务模块,通过远程调用协同工作,对外提供服务。

现有系统system,有modelA、modelB、modelC等服务模块。现在要以集中式(集群,cluster)和分布式的方式进行部署,下面我们来看看它们部署的示意图。

集中式示部署意图

图分布式部署示意图

从上面的集中式示部署意图和分布式部署示意图中我们可以看出,集中式将一个系统的所有服务模块部署到了不同的服务器上,构成一个集群,通过负载均衡设备对外提供服务。集中式部署就像茶水间同时有多个饮水机提供服务,服务冗余部署。分布式部署则将系统拆分成不同的服务模块,然后将不同的服务模块部署在不同的服务器上。

从上图我们也可以看出,分布式部署方案中,不仅仅是分布式服务,还有分布式数据存储、分布式静态资源,分布式计算等。此时,可能你已经回忆起上提到的,memcached不就是一套分布式的缓存系统吗。对,没错,memcached的分布式就体现在分布式数据存储,“分布式一致性hash算法”中的“分布式”就是指缓存数据的分布性。

一致性

了解了分布式之后,一致性就好理解了。有分布式数据存储数据,那就离不开分布式提取数据。一致性hash能保证在分布式环境中,对key进行哈希的结果或者说key与节点之间的映射关系不会受节点的增加和删除而产生重大的变化。参考wiki中一致性hash的定义:

Consistent hashing is a special kind of hashing such that when a hash table is resized, only K/n keys need to be remapped on average, where K is the number of keys, and n is the number of slots. In contrast, in most traditional hash tables, a change in the number of array slots causes nearly all keys to be remapped because the mapping between the keys and the slots is defined by a modular operation.

大概意思就是“一致性哈希是一种特殊的哈希算法,提供了这样的一个哈希表,当重新调整大小的时候,平均只有部分(k/n)key需要重新映射哈希槽,而不像传统哈希表那样几乎所有key需要需要重新映射哈希槽”。

哈希

hash,俗称“哈希”,也叫散列,是一种将任意长度的消息(数据)压缩到某一固定长度的消息摘要(数据)的算法。常见的hash算法有MD5,SHA等。hash算法具有几个重要的特性:不可逆性(即从hash值反推出原消息是不可能的)、抗冲突性(即给定消息M1,不存在另一个消息M2,使得Hash(M1)=Hash(M2))和分布均匀性(即hash的结果是均匀分布的)。memcached中,存取数据时都要进行哈希映射。正是这这几个特性,保证了memcached缓存中key值得唯一性。

三个词已经介绍完了,那memcached为什么要使用分布式一致性hash算法呢,继续看下文。

分布式一致性hash算法使用背景

我们已经知道,memcached的分布式主要在于客户端的分布式算法。memcached客户端就像一个网络中的路由,经过特定的算法将数据分散的存在到memcached服务端的机器上,又从分散的memcached服务端的机器上提取数据。实际中,常见的存储和提取数据的算法有取模算法和本文分析的一致性hash算法。

取模算法算法的原理是:

hash(key)%N

其中key 代表数据的键,代表memcached服务器的数量。取模的结果就是memcached客户端要定位的memcached服务器。取模算法很明显,结果很容易受N的影响,当服务器数量N增加或者减少的时候,原先的缓存数据定位几乎失效,缓存数据定位失效意味着要到数据库重新查询,这对于高并发的系统来说是致命的。于是,人们提出了一致性hash算法,最终目的是实现在移除、添加一个memcached服务器时对已经存在的缓存数据的定位影响尽可能的降到最小。

分布式一致性hash算法的简介和使用背景已经介绍完了,想必你对“分布式一致性hash算法”这个词已经不陌生了,下面将开启我们的”分布式一致性hash算法”原理的讲解。

环形hash空间

通常,一个缓存数据的key经过hash后会得到一个32位的值,也就是0~2^32 - 1数值范围。我们可以把这个数值范围抽象成一个首尾相连环形的空间,我们称这个空间为环形hash空间。如下图所示:

图 环形hash空间


映射key到环形hash空间

有了环形hash空间之后,缓存数据的key经过hash后得到的值就映射到了环形hash空间。假设有key1、key2、key3、key4,经过hash后,映射到环形hash空间如下图所示:

图 key映射到环形hash空间

映射server节点到hash空间

同理,我们可以把memcached服务器抽象成网络上的节点经过hash后映射到环形hash空间。假设有server1(可以是服务器的某些唯一标志信息,如ip等)、server2、server3,经过hash后,映射到环形hash空间如下图所示:

图 server节点映射到环形hash空间

映射key到server节点

现在缓存key和server节点都经过一致性hash算法映射到了环形hash空间,现在就可以将缓存key和server节点的关系进行映射了。顺时针沿着环形hash空间,从某个缓存key开始,直到遇到一个server节点,那么该缓存key就存储到这个server节点上。如图:

图 key映射到server节点

了解了key、server节点、hash空间之间的映射关系之后,现在我们已经清楚了缓存数据是怎样分布的存储到memcached服务器了。查找缓存数据的时候,也采用同样的映射方法来定位。

添加server节点

现在我们已经知道memcached存储和访问数据的策略了。那么当在server集群中增加一个server节点时,对数据访问的命中率又有什么影响呢。如下图,我在server1和server2节点之间增加一个节点server4。

图 增加server4节点

从上图可以看出,增加server4节点后,原有的缓存数据分布中,仅有server1~server4节点的数据进行了重新分布,这部分数据需要重新到数据库查找再次映射到新添加的server4节点上。尽管不能命中的缓存数据仍然存在,但相对于取模算法,已经是最大限度地抑制了hash键的重新分布。

删除server节点

同理,当在server集群中删除server2节点时,受影响的也仅是server1~server2之间的缓存数据,这部分数据需要重新到数据库查找再次映射到server3节点上。如下图所示:

图 删除server2节点

虚拟节点的引入

我们已经知道,添加和删除节点都会影响缓存数据的分布。尽管hash算法具有分布均匀的特性,但是当集群中server数量很少时,他们可能在环中的分布并不是特别均匀,进而导致缓存数据不能均匀分布到所有的server上。为解决这个问题,需要使用虚拟节点的思想:为每个物理节点(server)在环上分配100~200个点,这样环上的节点较多,就能抑制分布不均匀。当为cache定位目标server时,如果定位到虚拟节点上,就表示cache真正的存储位置是在该虚拟节点代表的实际物理server上。另外,如果每个实际server节点的负载能力不同,可以赋予不同的权重,根据权重分配不同数量的虚拟节点。

虚拟节点的hash计算可以采用对应节点的 IP 地址加数字后缀的方式。例如假设 serverA 的 IP 地址为 127.0.0.1 。引入虚拟节点前,计算serverA 的 hash 值:

hash(“127.0.0.1”);

引入虚拟节点后,计算虚拟节点serverA1 和 serverA12 的 hash 值:hash(“127.0.0.1#1”);

hash(“127.0.0.1#2”);

节点变化数据分流的问题

上面讨论的节点变化都会导致部分缓存数据的重新分布,hash算法还有一个重要的衡量指标:hash算法的结果能够保证需要重新分布的缓存数据能映射到新的server节点中。

一致性hash算法与取模算法的比较

取模算法的方法简单,数据的分散性也可以,但其主要缺点是当添加或移除server节点时,缓存重新映射的代价相当巨大。添加或移除server节点时,余数就会产生巨变,这样就无法定位与存储时相同的server节点,从而影响缓存的命中率。而一致性hash算法则最大限度的减少了server节点变化带来的影响,当节点变化时,只影响一个server节点的部分数据,且hash算法能够保证需要重新分布的缓存数据能映射到新的server节点中。

参考文档

http://blog.csdn.net/sparkliang/article/details/5279393

http://www.blogjava.net/hao446tian/archive/2013/01/29/394858.html

http://www.dexcoder.com/selfly/article/2388

http://www.cnblogs.com/lintong/p/4383427.html

http://blog.csdn.net/fdipzone/article/details/7170045

http://blog.jobbole.com/95588/

当你看到“分布式一致性hash算法”这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么。在分析分布式一致性hash算法原理之前,我们先来了解一下这几个概念。

分布式

分布式(distributed)是指在多台不同的服务器中部署不同的服务模块,通过远程调用协同工作,对外提供服务。

现有系统system,有modelA、modelB、modelC等服务模块。现在要以集中式(集群,cluster)和分布式的方式进行部署,下面我们来看看它们部署的示意图。

集中式示部署意图

图分布式部署示意图

从上面的集中式示部署意图和分布式部署示意图中我们可以看出,集中式将一个系统的所有服务模块部署到了不同的服务器上,构成一个集群,通过负载均衡设备对外提供服务。集中式部署就像茶水间同时有多个饮水机提供服务,服务冗余部署。分布式部署则将系统拆分成不同的服务模块,然后将不同的服务模块部署在不同的服务器上。

从上图我们也可以看出,分布式部署方案中,不仅仅是分布式服务,还有分布式数据存储、分布式静态资源,分布式计算等。此时,可能你已经回忆起上提到的,memcached不就是一套分布式的缓存系统吗。对,没错,memcached的分布式就体现在分布式数据存储,“分布式一致性hash算法”中的“分布式”就是指缓存数据的分布性。

一致性

了解了分布式之后,一致性就好理解了。有分布式数据存储数据,那就离不开分布式提取数据。一致性hash能保证在分布式环境中,对key进行哈希的结果或者说key与节点之间的映射关系不会受节点的增加和删除而产生重大的变化。参考wiki中一致性hash的定义:

分布式缓存技术memcached学习系列(四)—— 一致性hash算法原理的更多相关文章

  1. 分布式缓存技术memcached学习(四)—— 一致性hash算法原理

    分布式一致性hash算法简介 当你看到“分布式一致性hash算法”这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么.在分析分布式一致性hash算法原理之前,我们先来了解一下这几 ...

  2. 分布式缓存技术memcached学习系列(五)—— memcached java客户端的使用

    Memcached的客户端简介 我们已经知道,memcached是一套分布式的缓存系统,memcached的服务端只是缓存数据的地方,并不能实现分布式,而memcached的客户端才是实现分布式的地方 ...

  3. 分布式缓存技术memcached学习系列(二)——memcached基础命令

    上文<linux环境下编译memcahed>介绍了memcahed在linux环境下的安装以及登录,下面介绍memcahed的基本命令的使用. Add 功能:往内存增加一条新的缓存记录 语 ...

  4. 分布式缓存技术memcached学习系列(三)——memcached内存管理机制

    几个重要概念 Slab memcached通过slab机制进行内存的分配和回收,slab是一个内存块,它是memcached一次申请内存的最小单位,.在启动memcached的时候一般会使用参数-m指 ...

  5. 分布式缓存技术memcached学习系列(一)——linux环境下编译memcahed

    安装依赖工具 [root@localhost upload]# yum  install gcc  make  cmake  autoconf  libtool 下载并上传文件 memcached 依 ...

  6. 分布式缓存技术redis学习系列

    分布式缓存技术redis学习系列(一)--redis简介以及linux上的安装以及操作redis问题整理 分布式缓存技术redis学习系列(二)--详细讲解redis数据结构(内存模型)以及常用命令 ...

  7. 分布式缓存技术redis学习系列(一)——redis简介以及linux上的安装

    redis简介 redis是NoSQL(No Only SQL,非关系型数据库)的一种,NoSQL是以Key-Value的形式存储数据.当前主流的分布式缓存技术有redis,memcached,ssd ...

  8. 分布式缓存技术redis学习系列(四)——redis高级应用(集群搭建、集群分区原理、集群操作)

    本文是redis学习系列的第四篇,前面我们学习了redis的数据结构和一些高级特性,点击下面链接可回看 <详细讲解redis数据结构(内存模型)以及常用命令> <redis高级应用( ...

  9. 分布式缓存技术redis学习(四)——redis高级应用(集群搭建、集群分区原理、集群操作)

    本文是redis学习系列的第四篇,前面我们学习了redis的数据结构和一些高级特性,点击下面链接可回看 <详细讲解redis数据结构(内存模型)以及常用命令> <redis高级应用( ...

随机推荐

  1. jvm 配置,看看

    http://my.oschina.net/qiangzigege/blog/661757

  2. Scala中function的理解

    在函数式语言中,函数是和value一样地位的一等公民,他可以作为变量,或者作为参数传递给另一个函数 ##作为变量 val f=(x:Int)=>x+1 为啥可以这样写? 由于scala是OOP, ...

  3. Java将List/JavaBean转成Json

    import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.util.List; /**  *  ...

  4. November 11th 2016 Week 46th Friday

    Keep in mind that neither success nor failure is ever final. 无论成败,皆非定局. The final is not coming, but ...

  5. 1、Sencha cmd学习笔记(一) 使你的sencha cmd跑起来

    带着Ext JS 5来使用sencha cmd -------------------------------------------------------------------  这个指导通过处 ...

  6. 如何深入学习CSS

    学习CSS有了一定基础后,有的人会觉得好象没有什么学的.因为知道一些基本的理论性的东西.CSS说它容易是因为它的知识点有限.说它难学就在于各浏览器对CSS的支持程度不同.如何深入学习我给出以下几点见意 ...

  7. linux下源码编译安装mysql

    1.安装依赖的包: yum install -y gdb cmake ncurses-devel bison bison-devel 2.创建mysql安装目录和数据文件目录 mkdir -p /us ...

  8. 今天学习了下,如何破解wifi

    破解了隔壁的wif,得罪了,哥哥要蹭网一段时间. 主要思路:安装linux环境.这里我选择了虚拟机加cdlinux .运行里面的min抓得握手包,然后淘宝花10元跑下包,因为自己的电脑不行,跑费时间太 ...

  9. Firefox恢复书签

    Firefox虽然有网络同步功能,但是网络账户中没有保存历史书签.一旦电脑故障,书签可能会丢失,更要命的是自动同步後,网上书签也被覆盖的一干二净.怎么办呢? 大多数时候还是可以在本机找回书签 1:打开 ...

  10. UVa 10057 - A mid-summer night's dream

    题目大意:给n个数,找一个数A使得A与这n个数的差的绝对值最小.输出A最小的可能值,n个数中满足A的性质的数的个数以及满足A性质的不同的数的个数(不必从这n个数中挑选). 看见绝对值就想到了数轴上点之 ...