当前,Memcached、Redis这类分布式kv缓存已经非常普遍。从本篇开始,本系列将分析分布式缓存相关的原理、使用策略和最佳实践。

我们知道Memcached的分布式其实是一种“伪分布式”,也就是它的服务器结点之间其实是相互无关联的,之间没有网络拓扑关系,由客户端来决定一个key是存放到哪台机器。

具体来讲,假设我有多台memcached服务器,编号分别为m0,m1,m2,…。对于一个key,由客户端来决定存放到哪台机器,那最简单的hash公式就是 key % N,其中N是机器的总数。

但这有个问题,一旦机器数变少,或者增加机器,N发生变化,那之前存放的数据就全部无效了。因为你按照新的N值取模计算出的机器编号,和当时按旧的N值取模算出的机器编号肯定是不等的,也就意味着绝大部分缓存会失效。

这个问题的解决办法就是用1种特别的Hash函数,尽可能使得,增加机器/减少机器时,缓存失效的数目降到最低,这就是Hash环,或者叫一致性Hash。

Hash环
上面说的Hash函数,只经过了1次hash,即把key hash到对应的机器编号。
而Hash环有2次Hash:
(1)把所有机器编号hash到这个环上
(2)把key也hash到这个环上。然后在这个环上进行匹配,看这个key和哪台机器匹配。

具体来讲,如下:

假定有这样一个Hash函数,其值空间为(0到2的32次方-1) ,也就是说,其hash值是个32位无整型数字 ,这些数字组成一个环。

然后,先对机器进行hash(比如根据机器的ip),算出每台机器在这个环上的位置; 再对key进行hash,算出该key在环上的位置,然后从这个位置往前走,遇到的第一台机器就是该key对应的机器,就把该(key, value) 存储到该机器上。

如下图所示:

首先计算出每台Cache服务器在环上的位置(图中的大圆圈);然后每来一个(key, value),计算出在环上的位置(图中的小圆圈),然后顺时针走,遇到的第1个机器,就是其要存储的机器。

这里的关键点是:当你增加/减少机器时,其他机器在环上的位置并不会发生改变。这样只有增加的那台机器、或者减少的那台机器附近的数据会失效,其他机器上的数据都还是有效的。

数据倾斜问题
当你机器不多的时候,很可能出现几台机器在环上面贴的很近,不是在环上均匀分布。这将会导致大部分数据,都会集中在某1台机器上。

为了解决这个问题,可以引入“虚拟机器”的概念,也就是说:1台机器,我在环上面计算出多个位置。怎么弄呢? 假设用机器的ip来hash,我可以在ip后面加上几个编号, ip_1, ip_2, ip_3, … 把1台物理机器生个多个虚拟机器的编号。

数据首先映射到“虚拟机器上”,再从“虚拟机器”映射到物理机器上。因为虚拟机器可以很多,在环上面均匀分布,从而保证数据均匀分布到物理机器上面。

ZK的引入
上面我们提到了服务器的机器增加、减少,问题是客户端怎么知道呢?

一种笨办法就是手动的,当服务器机器增加、减少时候,重新配置客户端,重启客户端。

另外一种,就是引入ZK,服务器的节点列表注册到ZK上面,客户端监听ZK。发现结点数发生变化,自动更新自己的配置。

当然,不用ZK,用一个其他的中心结点,只要能实现这种更改的通知,也是可以的。

最新文章

  1. 深入理解Sqlserver文件存储之页和应用 (转)
  2. Zookeeper会话
  3. Web开发人员常犯的10个错误
  4. java 哪些情况下会使对象锁释放
  5. DNX概述
  6. Spring集成XFire开发WebService
  7. Android02-控件
  8. 排列熵算法简介及c#实现
  9. sts 创建springMVC项目---- maven和tomcat 错误处理
  10. CSS之CSS的三种基本的定位机制(普通流,定位,浮动)
  11. Angular7.1.4+Typescript3.1框架学习(三)
  12. IIS Express ArgumentOutOfRangeException
  13. Markup解析XML——文档,说明
  14. selenium学习一
  15. Android 对BaseAdapter做优化处理
  16. eclipse 关联 Maven本地仓库的配置
  17. Spring学习---Spring中利用组件实现从FTP服务器上传/下载文件
  18. Spring+SpringMVC+MyBatis整合(山东数漫江湖)
  19. POJ 2777 Count Color(线段树 + 染色问题)
  20. python16_day09【Select多路复用】

热门文章

  1. JVM手动分配内存(转载)
  2. oracle 错误代码表
  3. Linux内核日志开关
  4. 织梦dedecms页面中增加二维码功能的实现方法
  5. 如何反编译silverlight
  6. 调节音量的各个方法——AudioManager的使用
  7. js 购物车中,多件商品数量加减效果修改,实现总价随数量加减改变
  8. linux--memcache的安装和使用(转)
  9. 在Ubuntu下获取Android4.0源代码并编译(一)
  10. 洛谷P1247取火柴游戏