Memcached中一致性哈希(Consistent Hashing)的运用

在缓存应用中最常规的方式莫过于Hash取模的方式。比如集群中可用机器数N,那么key值为K的数据请求应该路由到Hash(K) mod N对应的机器。的确,这种结构是简单实用的。但是随着系统访问压力的增长,缓存系统不得不通过增加机器节点的方式提高集群的响应速度和数据承载量。增加机器意味着按照Hash取模的方式,大量的缓存命不中,缓存数据需要重新建立,瞬间会给DB带来极高的负载,甚至导致DB服务器宕机。本文介绍的一致性哈希技术可以很好的解决这个问题。

一致性哈希(Consistent Hashing)
一致性哈希的定义除了描述一个定义或者一种想法并没有给出任何实现方面的描述。但一般的实现思路如下:
1、假定哈希的均匀Key分布在一个环上,比如所有节点都通过SHA-1或MD5进行哈希映射
2、所有的节点也都分布在同一环上(比如Server的IP地址经过SHA-1)
3、每个节点只负责一部分Key,当节点加入、退出时只影响加入退出的节点和其邻居节点或者其他节点只有少量的Key受影响
4、假如有n个节点,m个key,当节点增加时大约有O(m/n)的节点需要移动

一般一致性哈希需要满足下面几个条件:
1、平衡性(Balance):哈希算法要均匀分布,不能有明显的映射规律,这对一般的哈希实现也是必须的
2、单调性(Monotonicity):有新节点加入时,已经存在的映射关系不能发生变化
3、分散性(Spread):避免不同的内容映射到相同的位置和相同的内容映射到不同的位置
其实一致性哈希(哈希)有个明显的优点就是负载均衡,只要哈希函数设计得当,每个点就是对等的可以均匀地分布系统负载。

Memcached中一致性哈希的运用
Memcached使用了一致性哈希,支持动态对其增减节点。 Memcached在其客户端实现哈希策略,因此不同的客户端实现也有区别,以Spymemcache、Xmemcache为例,都是使用了ketama作为其实现。

ketama实现方式如下:
- 将服务器列表(如 1.2.3.4:11211, 5.6.7.8:11211)的每项进行MD5哈希,结果为一个160bit的数字,取其前32位作为一个整数
- 通常服务器数量比较少,通过给每项增加序列号后缀,每项再虚拟出100~200新项,再MD5哈希
- 这些MD5哈希生成的整数将均匀分布在一个0~2^32数字环上
- 把缓存对象的Key也进行MD5哈希,同样得到一个整数。用该整数去匹配应该存在那个服务器上

详细步骤如下:
1、Hash机器节点
首先求出机器节点的Hash值,然后将其分布到0~2^32的一个圆环上(顺时针分布)。
 
A , B, C, D, E 5台机器通过Hash算法将其分布上图环上

2、查找机器节点,访问缓存
有一个写入缓存的请求,其Key为K,计算器Hash值Hash(K), Hash(K) 对应于上图环中的某一个点,如果该点对应没有映射到具体的某一个机器节点,那么顺时针查找,直到第一次找到有映射机器的节点,该节点就是确定的目标节点。如果超过了2^32仍然找不到节点,则命中第一个机器节点。比如 Hash(K) 的值介于A~B之间,那么命中的机器节点应该是B节点(如上图)。

3、新增机器节点
在原有集群的基础上欲增加一台机器F:计算机器节点的Hash值,将机器映射到环中的一个节点:
 
增加机器节点F之后,访问策略不改变,依然按照第2步方式访问,此时缓存命不中的情况依然不可避免,不能命中的数据是Hash(K)在增加节点以前落在C~F之间的数据。尽管依然存在节点增加带来的命中问题,但是比较传统的Hash取模的方式,一致性哈希已经将不命中的数据降到了最低,最大限度地抑制了Hash键的重新分布。

 4、虚拟节点(virtual nodes)
实际应用中,为了取得比较好的负载均衡效果,往往在第1步Hash机器节点时要引入虚拟节点(virtual nodes),原因是哈希虽然是随机的,但当服务器(节点)数较少的情况下 (例如只有3台),通过Hash(key)算出节点的哈希值在圆环上并不是均匀分布的(稀疏的),仍然会出现各节点负载不均衡的问题。
绝大多数Key会映射到Server1

虚拟节点就是为每个物理节点(服务器)在圆上多分配100~200个点。这样就能抑制分布不均匀,最大限度地减小服务器增减时的缓存重新分布。有虚节点后的环如下,新增的同名节点即为虚拟节点:

关于如何设置虚拟节点数目,见下图:
 
* x轴表示的是需要为每台物理服务器扩展的虚拟节点倍数(scale)
* y轴是实际物理服务器数

从上图可以看出,当物理服务器的数量很小时,需要更大的虚拟节点,反之则需要更少的虚拟节点。如图,当物理服务器有10台时,应该为每台服务器增加100~200个虚拟节点才能达到真正的负载均衡。

ketama项目地址: https://github.com/RJ/ketama

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值