一致性哈希(consistent hashing)算法

文章同步发表在博主的网站朗度云,传输门:http://www.wolfbe.com/detail/201608/341.html

1、背景

我们都知道memcached服务器是不提供分布式功能的,memcached的分布式完全是由客户端来实现的。在部署memcached服务器集群时,我们需要把缓存请求尽可能分散到不同的缓存服务器中,这样可以使得所有的缓存空间都得到利用,而且可以降低单独一台缓存服务器的压力。
     最简单的一种实现是,缓存请求时通过计算key的哈希值,取模后映射到不同的memcahed服务器。这种简单的实现在不考虑集群机器动态变化的情况下也是比较有效的一种方案,但是,在分布式集群系统中,简单取模的哈希算法存在很多的不足。在动态变化的缓存集群中,有四个判断哈希算法好坏的标准:

  • 平衡性(blance):指哈希的结果能够尽可能映射到所有的节点,这样所有节点的资源都能够得到利用。
  • 单调性(monotonicity):指如果有一些数据通过哈希分派到相应的节点中,又有新的节点加入系统中,那么哈希的结果应该能够保证已分配的内容可以被映射到原有的或者新的节点中,而不会被映射到旧系统(加入新的节点之前)的其它节点。
  • 分散性(spread):在分布式环境中,终端有可能看不到所有的节点,而是只能看到一部分。当终端通过哈希过程分派到节点上时,由于不同的终端所看到的节点范围有可能不一样,从而导致哈希的结果不一样,最终会出现相同的内容会被不同的终端哈希到不同的节点上存储。这种情况应该要避免,因为这样相同的内容会被存储不同的节点,浪费系统的资源。
  • 负载(load):负载问题实际上是从另一个角度看待分散性问题。既然不同的终端可能将相同的内容映射到不同的节点中,那么对于一个特定的节点而言,也可能被不同的终端映射为不同的内容。与分散性一样,这种情况也是应当避免的,因此好的哈希算法应能够尽量降低节点的负荷。

在分布式的集群系统中,机器的增加或移除或机器故障宕机的情况经常发生,如果使用简单取模的哈希算法,机器变化了计算的算法也要重新修改,存储的对象的位置也必须改变,外部服务访问就可能无法命中原来的内容,导致缓存后端服务压力过大而崩溃。所以,简单取模的这种哈希算法不能满足动态变化的缓存集群环境,因此需要其它的算法来避免这样的问题。

一致性哈希算法在1997年由麻省理工学院的Karger等人在解决分布式Cache中提出的,主要是为了解决因特网中的热点(Hot spot)问题。目前这一思想已经扩展到其它的领域,并且在实践中得到了很大的发展。目前很多应用都会一致性哈希算法应用在动态变化的缓存集群中,它能够满足上面提到的四个标准。

2、原理

哈希,也叫做散列,就是把任意长度的输入通过散列算法,变换成固定长度的输出,该输出就是散列值,或者叫哈希值 。一致性哈希将整个哈希值空间虚拟成一个闭合的Hash环,假设哈希值空间为2的32次方,即哈希值空间为0~ 2^32-1,如下图所示:

图1 Hash环

将对象映射到Hash环

假设有object1、object2、object3、object4四个对象,通过Hash算法计算出它们的Key值,然后映射到Hash环上,如下图所示:

Hash(object1) = key1;

Hash(object2) = key2;

Hash(object3) = key3;

Hash(object4) = key4;

图2 对象哈希

将节点映射到Hash环

假设有Cache A 、Cache B、Cache C三个缓存节点,通过Hash算法计算它们的哈希值,映射到Hash环上,如下图所示:

Hash(Cache A) = Key A;

Hash(Cache B) = Key B;

Hash(Cache C) = Key C;

图3 节点哈希

一般情况下,计算节点的哈希值可以使用节点的IP或者节点的别名作为输入值。需要注意的是计算节点使用的Hash算法跟计算对象使用的Hash算法是一样的,这样节点跟对象的哈希空间也是一样的,按照顺时针的方向,将对象存储在离自己最近的那个节点上。从图3可以看出,object1存储到Cache A节点,object2和object3存储到Cache C节点,object4存储到Cache B节点。

节点变动

使用简单取模的哈希算法最大的问题在于当节点数量变动时,节点的数据会失效,那么一致性哈希算法能够避免这些问题,是否能够满足上面的四个标准呢?

  • 增加节点

在集群中增加一个新的节点Cache D,假设在Hash环上,节点经过Hash计算后被映射到object2与object3之间,如下图所示:

图4 增加节点

按照顺时针方向存储的约定,object2会迁移存储到Cache D节点,其它对象保持原来位置不变。

  • 删除节点

假设节点Cache B故障挂掉了,按照顺时针方向存储的约定,object4会迁移存储到Cache C节点,其它对象保持原来位置不变,如下图所示:

图5 删除节点

经过增加节点和删除节点的分析得到,一致性哈希算法在保持单调性的同时,还让数据的迁移达到最小,避免因为数据迁移造成后端服务器因为压力大而崩溃。

平衡性设计

通过上面的分析得到,一致性哈希算法可以满足动态缓存集群系统的单调性、分散性、负载的标准,但还不能确定它的设计是否能够满足平衡性。下面将讲解一致性哈希算法是如何做到满足平衡性的。

在删除节点的例子中,系统中只有Cache A与Cache C这两个节点,object1存储到Cache A节点,object2、object3、object4存储到Cache C节点,分布很明显不平衡。

为了解决这个问题,一致性算法中引入了虚拟节点的概念,虚拟节点是实际节点在Hash环上的复制器,一个实际节点可以对应多个虚拟节点。

现在假设一个实际点对应2个虚拟节点,经过Hash计算后,映射到Hash环上,这样Hash环上就存在4个虚拟的节点, 如下图所示:

图6 虚拟节点

按顺时针方向存储的约定,object1存储到Cache A2节点,object2存储到Cache A1节点,object3存储到Cache C1节点,object4存储到Cache C2节点。这样的情况是一个比较理想的情况,因此object1、object2存储到Cache A节点,object3、object4存储到Cache C节点上,平衡性得到满足。

引入虚拟节点后,映射关系就从对象->节点变成了对象->虚拟节点,查找对象所在的实际节点时的映射关系图如下所示:

图7 查找节点

虚拟节点的哈希输入可以是实际节点的IP加数字后缀的方式,假设Cache A的IP是192.168.1.100,那么计算Cache A1和Cache A2的Hash值是:

Hash("192.168.1.100 #1") = key C1;

Hash("192.168.1.100 #2") = key C2;

至此我们可以确定,一致性哈希算法能够满足分布式集群的平衡性、单调性、分散性、负载四个标准,现在已经被广泛地应用到各个领域。

时间: 2024-08-01 10:46:50

一致性哈希(consistent hashing)算法的相关文章

Go语言实现一致性哈希(Consistent Hashing)算法

一致性哈希可用于解决服务器均衡问题. 用Golang简单实现了下,并加入了权重.可采用合适的权重配合算法使用. package main //一致性哈希(Consistent Hashing) //author: Xiong Chuan Liang //date: 2015-2-20 import ( "fmt" "hash/crc32" "sort" "strconv" "sync" ) const DE

深入一致性哈希(Consistent Hashing)算法原理,并附100行代码实现

本文为实现分布式任务调度系统中用到的一些关键技术点分享——Consistent Hashing算法原理和Java实现,以及效果测试. 背景介绍 一致性Hashing在分布式系统中经常会被用到, 用于尽可能地降低节点变动带来的数据迁移开销.Consistent Hashing算法在1997年就在论文Consistenthashing and random trees中被提出. 先来简单理解下Hash是解决什么问题.假设一个分布式任务调度系统,执行任务的节点有n台机器,现有m个job在这n台机器上运

一致性哈希(Consistent Hashing)

传统来讲,数据的存储位置是通过hash(object)%N来计算的,这样造成的问题是如果新的机器添加进来或是某台机器down掉了,通过这种算法计算出来的存储位置会和以前的不同,造成了大量数据的迁移,如果有新的机器添加进来也会造成同样的问题,所以容错性和扩展性都不好.一致性哈希算法的主要目的是尽量减少数据的迁移. 一致性哈希假设有一个闭合圆环空间,上面有2**31个位置,数据通过特定的hash算法被分布到哈希圆环上.机器也通过特定的hash算法(输入值为机器的IP或是机器唯一的别名)放到圆环上,然

用于KV集群的一致性哈希Consistent Hashing机制

KV集群的请求分发 假定N为后台服务节点数,当前台携带关键字key发起请求时,我们通常将key进行hash后采用模运算 hash(key)%N 来将请求分发到不同的节点上, 后台节点的增删会引起几乎所有key的重新映射, 这样会造成大量的数据迁移,如果数据量大的话会导致服务不可用. 一致性哈希机制 我倾向于称之为一致性哈希机制而不是算法, 因为这其实和算法没太大关系. 设计这种机制的目的是当节点增减时尽量减小重新映射的key的数量, 尽量将key还映射到原来的节点上. 而对于一致性哈希机制, 如

2016 -Nginx的负载均衡 - 一致性哈希 (Consistent Hash)

Nginx版本:1.9.1 算法介绍 当后端是缓存服务器时,经常使用一致性哈希算法来进行负载均衡. 使用一致性哈希的好处在于,增减集群的缓存服务器时,只有少量的缓存会失效,回源量较小. 在nginx+ats / haproxy+squid等CDN架构中,nginx/haproxy所使用的负载均衡算法便是一致性哈希. 我们举个例子来说明一致性哈希的好处. 假设后端集群包含三台缓存服务器,A.B.C. 请求r1.r2落在A上. 请求r3.r4落在B上. 请求r5.r6落在C上. 使用一致性哈希时,当

_00013 一致性哈希算法 Consistent Hashing 探讨以及相应的新问题出现解决

一.业务场景 假如我们现在有12台Redis服务器(其它的什么东西也行),有很多User(用户)的数据数据从前端过来,然后往12台redis服务器上存储,在存储中就会出现一个问题,12台服务器,有可能其中几台Redis服务器上(简称集群A)存了很多的数据,然后另外几台Redis服务器(简称集群B)上存的数据很少,这样的话那 A 上的读写压力就会很大(当然,这个要看你的数据量的大小了,如果你数据量很小的话,基本无压力了,但是数据量很大,那就 ...),对于这样的问题,我们通常的解决办法是什么呢 ?

_00013 一致性哈希算法 Consistent Hashing 新的讨论,并出现相应的解决

笔者博文:妳那伊抹微笑 博客地址:http://blog.csdn.net/u012185296 个性签名:世界上最遥远的距离不是天涯,也不是海角,而是我站在妳的面前.妳却感觉不到我的存在 技术方向:Flume+Kafka+Storm+Redis/Hbase+Hadoop+Hive+Mahout+Spark ... 云计算技术 转载声明:能够转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明,谢谢合作. qq交流群:214293307  idkey=bf80524ac3630cb09

一致性哈希算法原理设计

原文出处: 知致智之   欢迎分享原创到伯乐头条 一.前言 一致性哈希(Consistent Hashing),最早由MIT的Karger于1997年提出,主要用于解决易变的分布式Web系统中,由于宕机和扩容导致的服务震荡.现在这个算法思路被大量应用,并且在实践中得到了很大的发展. 二.算法设计 1.问题来源 一个由6台服务器组成的服务,每台Server负责存储1/6的数据,当Server1出现宕机之后,服务重新恢复可用时的场景. 如下表格可以很清楚的看到,当Server1宕机时,Hash1的服

一致性 hash 算法( consistent hashing )a

一致性 hash 算法( consistent hashing ) 张亮 consistent hashing 算法早在 1997 年就在论文 Consistent hashing and random trees 中被提出,目前在cache 系统中应用越来越广泛: 1 基本场景 比如你有 N 个 cache 服务器(后面简称 cache ),那么如何将一个对象 object 映射到 N 个 cache 上呢,你很可能会采用类似下面的通用方法计算 object 的 hash 值,然后均匀的映射到