一致性哈希算法(Consistent Hashing)在分布式系统的应用仍是十分普遍的,本文尽可能结合业务场景快速讲解一致性哈希算法的应用及与其相关的话题。算法
随着业务的扩展,流量的剧增,单体项目逐渐划分为分布式系统。对于常用的数据,咱们可使用Redis做为缓存机制,减小数据层的压力。所以,重构后的系统架构以下图所示:数据库
优化最简单的策略就是,把经常使用的数据保存到Redis中,为了实现高可用使用了3台Redis(没有设置集群,集群至少要6台)。每次Redis请求会随机发送到其中一台,可是这种策略会引起以下两个问题:缓存
要解决上述的问题,咱们须要稍稍改变一些key存入Redis的规则:使用hash算法
例如,有三台Redis,对于每次的访问均可以经过计算hash来求得hash值。
如公式 h=hash(key)%3,咱们把Redis编号设置成0,1,2来保存对应hash计算出来的值,h的值等于Redis对应的编号。
可是hash算法也会面临容错性和扩展性的问题。容错性是指当系统中的某个服务出现问题时,不能影响其余系统。扩展性是指当加入新的服务器后,整个系统能正确高效运行。服务器
现假设有一台Redis服务器宕机了,那么为了填补空缺,要将宕机的服务器从编号列表中移除,后面的服务器按顺序前移一位并将其编号值减一,此时每一个key就要按h = Hash(key) % 2从新计算。架构
一样,若是新增一台服务器,规则也一样须要从新计算,h = Hash(key) % 4。所以,系统中若是有服务器更变,会直接影响到Hash值,大量的key会重定向到其余服务器中,形成缓存命中率下降,而这种状况在分布式系统中是十分糟糕的。分布式
一个设计良好的分布式哈希方案应该具备良好的单调性,即服务节点的变动不会形成大量的哈希重定位。一致性哈希算法由此而生~函数
一致哈希 是一种特殊的哈希算法。在使用一致哈希算法后,哈希表槽位数(大小)的改变平均只须要对 K/n 个关键字从新映射,其中K是关键字的数量, n是槽位数量。然而在传统的哈希表中,添加或删除一个槽位的几乎须要对全部关键字进行从新映射。
简单的说,一致性哈希是将整个哈希值空间组织成一个虚拟的圆环,如假设哈希函数H的值空间为0-2^32-1(哈希值是32位无符号整形),整个哈希空间环以下:优化
整个空间按顺时针方向组织,0和2^32-1在零点中方向重合。spa
接下来,把服务器按照IP或主机名做为关键字进行哈希,这样就能肯定其在哈希环的位置。
而后,咱们就可使用哈希函数H计算值为key的数据在哈希环的具体位置h,根据h肯定在环中的具体位置,今后位置沿顺时针滚动,遇到的第一台服务器就是其应该定位到的服务器。设计
例如咱们有A、B、C、D四个数据对象,通过哈希计算后,在环空间上的位置以下:
根据一致性哈希算法,数据A会被定为到Server 1上,数据B被定为到Server 2上,而C、D被定为到Server 3上。
那么使用一致性哈希算法的容错性和扩展性如何呢?
假如RedisService2宕机了,那么会怎样呢?
那么,数据B对应的节点保存到RedisService3中。所以,其中一台宕机后,干扰的只有前面的数据(原数据被保存到顺时针的下一个服务器),而不会干扰到其余的数据。
下面考虑另外一种状况,假如增长一台服务器Redis4,具体位置以下图所示:
本来数据C是保存到Redis3中,但因为增长了Redis4,数据C被保存到Redis4中。干扰的也只有Redis3而已,其余数据不会受到影响。
所以,一致性哈希算法对于节点的增减都只需重定位换空间的一小部分便可,具备较好的容错性和可扩展性
前面部分都是讲述到Redis节点较多和节点分布较为均衡的状况,若是节点较少就会出现节点分布不均衡形成数据倾斜问题。
例如,咱们的的系统有两台Redis,分布的环位置以下图所示:
这会产生一种状况,Redis4的hash范围比Redis3的hash范围大,致使数据大部分都存储在Redis4中,数据存储不平衡。
为了解决这种数据存储不平衡的问题,一致性哈希算法引入了虚拟节点机制,即对每一个节点计算多个哈希值,每一个计算结果位置都放置在对应节点中,这些节点称为虚拟节点。
具体作法能够在服务器IP或主机名的后面增长编号来实现,例如上面的状况,能够为每一个服务节点增长三个虚拟节点,因而能够分为 RedisService1#一、 RedisService1#二、 RedisService1#三、 RedisService2#一、 RedisService2#二、 RedisService2#3,具体位置以下图所示:
对于数据定位的hash算法仍然不变,只是增长了虚拟节点到实际节点的映射。例如,数据C保存到虚拟节点Redis1#2,实际上数据保存到Redis1中。这样,就能解决服务节点少时数据不平均的问题。在实际应用中,一般将虚拟节点数设置为32甚至更大,所以即便不多的服务节点也能作到相对均匀的数据分布。
本文简要的介绍了一致性哈希算法,目前一致性哈希算法基本成为了分布式系统组件的标准配置,所以,咱们十分有必要了解该算法。
做者-fangqing
广州芦苇科技Java开发团队
芦苇科技-广州专业互联网软件服务公司
抓住每一处细节 ,创造每个美好
关注咱们的公众号,了解更多
想和咱们一块儿奋斗吗?lagou搜索“ 芦苇科技 ”或者投放简历到 server@talkmoney.cn 加入咱们吧
关注咱们,你的评论和点赞对咱们最大的支持