分布式一致性hash算法简介

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

分布式

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

以一个航班订票系统为例,这个航班订票系统有航班预定、网上值机、旅客信息管理、订单管理、运价计算等服务模块。现在要以集中式(集群,cluster分布式的方式进行部署,下面我们来看看它们部署的示意图。

集中式示部署意图

图 分布式部署示意图

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

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

一致性

了解了分布式之后,一致性就好理解了。有分布式数据存储数据,那就离不开分布式提取数据。一致性即存储数据到memcached和从memcached中提取数据的时候采用的算法要一致以保持数据一致性。即当以hash算法将数据存储到memcached时,提取该数据时,也要以hash算法进行提取。

Hash

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 代表数据的键,N代表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、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节点时,对数据访问的命中率又有什么影响呢。如下图,我在serverC和serverD节点之间增加一个节点serverF。

图 增加serverF节点

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

删除server节点

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

图 删除serverC节点

虚拟节点的引入

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

图 引入虚拟server节点

另外,如果每个实际server节点的负载能力不同,可以赋予不同的权重,根据权重分配不同数量的虚拟节点。

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

hash(“127.0.0.1”);

和 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/

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

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

    分布式一致性hash算法简介 当你看到"分布式一致性hash算法"这个词时,第一时间可能会问,什么是分布式,什么是一致性,hash又是什么.在分析分布式一致性hash算法原理之前, ...

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

随机推荐

  1. 12.3 Arithmetic-software-

    一.流程图: 二.软件功能: 分为混合模式和单则模式,混合模式生成指定题数的任意四则混合运算,数字是1-10之间随机:单则模式是生成指定题数的加减乘除中指定的某一则运算,数字是1-10之间随机. 用户 ...

  2. 一、Daily Scrum Meeting【Alpha】------Clover

    [Alpha]Daily Scrum Meeting 第一次 [Alpha]Daily Scrum Meeting 第二次 [Alpha]Daily Scrum Meeting 第三次 [Alpha] ...

  3. 树莓派系统介绍:DIetPi

    项目主页:http://fuzon.co.uk/phpbb/viewtopic.php?f=8&t=6 当前版本:V34(15年4月16日发布) DietPi是国外一个基于Raspbian的精 ...

  4. 10月25日下午PHP静态、抽象、接口

    多态(运行多态)概念:当父类引用指向子类实例,由于子类里面对父类的方法进行了重写,父类引用在调用该方法的时候表现出的不同状态.条件:1.必须发生在继承下2.必须重写父类方法3.父类引用调用该方法 如果 ...

  5. 转-ArcGIS Engine许可初始化

    关于初始化Engine许可的,其实原理都很简单,大家一般都没有问题,但又往往会因为不够细心加上Engine的“小脾气”,让不少程序员都要在这里犯错. 以Engine9.2为例,应用程序是强制初始化许可 ...

  6. Nginx 301重定向设置

    server { server_name www.***.com ***.com; if ($host != 'www.***.com' ) { rewrite ^/(.*)$ http://www. ...

  7. C# 异步

    private void GetHttpResponse() { var client = new Microsoft.HBase.Client.HBaseClient(new ClusterCred ...

  8. 深入理解javascript原型和闭包(9)——简述【执行上下文】下

    继续上一篇文章(http://www.cnblogs.com/wangfupeng1988/p/3986420.html)的内容. 上一篇我们讲到在全局环境下的代码段中,执行上下文环境中有如何数据: ...

  9. tail -f 和 -F 的用法

    tail -f 和 -F 的用法  Tai 2010-08-16 16:03:18 -f 是--follow[=HOW]的缩写, 可以一直读文件末尾的字符并打印出来."[=HOW]" ...

  10. PHP正则表达式模式修饰符详解

    PHP模式修饰符又叫模式修正符,是在正则表达式的定界符之外使用.主要用来调整正则表达式的解释,提扩展了正则表达式在匹配.替换等操作的某些功能,增强了正则的能力.但是有很多地方的解释都是错误的,也容易误 ...