分布式一致性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. python 网络编程

    一.网络知识的一些介绍 socket是网络连接端点.例如当你的Web浏览器请求www.pythontik.com上的主页时,你的Web浏览器创建一个socket并命令它去连接www.pythontik ...

  2. 使用Spring进行统一日志管理 + 统一异常管理

    http://blog.csdn.net/king87130/article/details/8011843原文地址 统一日志异常实现类: 1 package com.pilelot.web.util ...

  3. bandicam如何录制视频

    我们一般都很熟悉这类软件:屏幕录制专家和kk录制等,这些都是国内比较优秀的作品.不过exe的封装格式以及录制的清晰度让人很纠结.所以这里要为大家分享的是一款韩国人写录制软件Bandicam.Bandi ...

  4. Windows7微软官方原版镜像系统文件

    Windows7微软官方原版镜像系统 Windows 7 是由微软公司(Microsoft)开发的操作系统,核心版本号为Windows NT 6.1.Windows 7可供家庭及 商业工作环境.笔记本 ...

  5. 图解JVM的类加载机制(详细版)

    注:本文为作者整理和原创,如有转载,请注明出处. 上一篇博文,把JAVA中的Class文件格式用图形的方式画了一下,逻辑感觉清晰多了,同时,也为以后查阅的方便. Class文件只是一种静态格式的二进制 ...

  6. mod-mono

    http://go-mono.com/config-mod-mono/  配置文件生成器 Mono remote debugging from Visual Studio http://stackov ...

  7. C++程序设计——知识点总结

    C++程序设计课程的总结,方便以后快速查阅和复习 Week 2 从C走进C++ 函数指针 函数名是函数的入口地址,指向函数的指针称为"函数指针". 比如,qsort库函数: voi ...

  8. 适配iOS10以及Xcode8

    现在在苹果的官网上,我们已经可以下载到Xcode8的GM版本了,加上9.14日凌晨,苹果就要正式推出iOS10系统的推送了,在此之际,iOS10的适配已经迫在眉睫啦,不知道Xcode8 beat版本, ...

  9. bzoj1441 MIN

    Description 给出n个数(A1…An)现求一组整数序列(X1…Xn)使得S=A1*X1+…An*Xn>0,且S的值最小 Input 第一行给出数字N,代表有N个数 下面一行给出N个数 ...

  10. WSDL2java简单使用

    一.使用工具WSDL2java把接口转为本地可调用的.java文件 工具的目录结构: 设置WSDL2Java(URL).bat中的参数 set Axis_Lib=.\lib set Java_Cmd= ...