Java实现加密(四)哈希算法与一致性哈希算法

1.哈希算法

哈希算法: 也称散列算法、摘要算法。是把任意长度的输入通过散列算法变换成固定长度的输出,该输出就是散列值。

  • 哈希碰撞: 如果两个关键字通过Hash算法得到的值是一样的,就是哈希碰撞。
  • Hash表(散列表): 根据散列函数和冲突处理将一组关键字分配在连续的地址空间内,并以散列值记录在表中的存储位置,这种表称为散列表。

2.一致性哈希算法

一致性哈希算法: 也称割环法。在1997年由麻省理工学院提出,是一种特殊的哈希算法,目的是解决分布式缓存的问题。在移除或添加一个服务器时,能够尽可能小地改变已存在地服务请求与处理请求服务器之间的映射关系。一致性哈希解决了简单哈希算法在分布式哈希表中存在的动态伸缩等问题。

2.1 为什么要使用Hash算法

举个例子,我们在使用Redis的时候,为了保证Redis的高可用,提高Redis的读写性能,最简单的方式我们会做主从复制,或者搭建Redis集群,进行数据读写分离,当数据量很大的时候(标准可能不一样,要看Redis服务器容量)我们同样可以对Redis进行类似数据库的操作,就是分库分表,如图所示:

请添加图片描述

假如采用随机分配的方式,那么我们保存一条数据都有可能存储在任何一组Redis中,如果我们需要查询某一条数据,由于我们不清楚数据保存在哪一个Redis服务器中,所以需要遍历所有的Redis服务器,这显然不是我们想要的结果。

如果我们使用Hash的方式,每一张图片在进行分库的时候都可以定位到特定的服务器,示意图如下:

请添加图片描述

上图中,假设我们查找的是“a.png”,由于有4台服务器(排除从库),因此公式为 hash(a.png) % 4 = 2,可知定位到了第2号服务器,这样的话就不会遍历所有的服务器,大大提升了性能!

2.2 使用Hash算法带来的问题

上述的方式虽然提升了性能,我们不再需要对整个Redis服务器进行遍历,但是使用上述Hash算法进行缓存时会出现一些缺陷,主要体现在服务器数量变动的时候,所有缓存的位置都要发生改变。

试想一下,如果4台缓存服务器已经不能满足我们的缓存需求,那么我们应该怎么做呢?很简单,多增加几台缓存服务器不就行了。假设:我们增加了一台缓存服务器,那么缓存服务器的数量就由4台变成了5台。那么原本hash(a.png) % 4 = 2 的公式就变成了 hash(a.png) % 5 = ?,可想而知这个结果肯定不是2的,这种情况带来的结果就是当服务器数量变动时,所有缓存的位置都要发生改变。换句话说,当服务器数量发生改变时,所有缓存在一定时间内是失效的,当应用无法从缓存中获取数据时,则会向后端数据库请求数据。

同样的,假设4台缓存中突然有一台缓存服务器出现了故障,无法进行缓存,那么我们则需要将故障机器移除,但是如果移除了一台缓存服务器,那么缓存服务器数量从4台变为3台,也是会出现上述的问题。

所以,我们应该想办法不让这种情况发生,但是由于上述Hash算法本身的缘故,使用取模法进行缓存时,这种情况是无法避免的,为了解决这些问题,一致性Hash算法诞生了!

2.3 一致性Hash算法原理

一致性Hash算法也是使用取模的方法,只是,刚才描述的取模法是对服务器的数量进行取模,而一致性Hash算法是对2^32取模,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,将各个服务器使用Hash进行计算,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置,这里假设将上文中4台服务器使用IP地址哈希后在环控件的位置如下:

请添加图片描述

每次根据要缓存的key计算得到hash值,在hash环上顺时针查找距离最近的缓存服务器节点,

请添加图片描述

根据一致性Hash算法,数据A会被定位到Node A上,B被定位到Node B上,C被定位到Node C上,D被定位到Node D上。

2.4 一致性Hash算法的容错性和可扩展性

现假设Node C不幸宕机,可以看到此时对象A、B、D不会受到影响,只有C对象被重定位到Node D。一般的,在一致性Hash算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其空间中的前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其他不会受到影响,如下所示:

请添加图片描述

下面考虑另外一种情况,如果在系统中增加一台服务器 Node X,如下图所示:

请添加图片描述

此时对象Object A、B、D不受影响,只有对象C需要重定位到新的Node X。一般的,在一致性Hash算法中,如果增加一台服务器,则受影响的数据仅仅是新服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其他数据也不会受到影响。

综上所述,一致性Hash算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。

2.5 Hash环的数据倾斜问题

一致性Hash算法在服务节点太少时,容易因为节点分布不均匀而造成数据倾斜问题(被缓存的对象大部分集中存储在某一台服务器上),例如系统中只有两台服务器,其环分布如下:

请添加图片描述

此时,必然造成大量数据集中到Node A上,而只有极少量会定位到Node B上。为了解决这种数据倾斜问题,一致性Hash算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希,每个计算结果位置上都放置一个此服务节点,成为虚拟节点。具体做法可以在服务器IP或主机名的后面增加编号来实现。例如上面的情况,可以为每台服务器计算三个虚拟节点,于是可以分别计算“Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3” 的哈希值,于是形成六个虚拟节点:

请添加图片描述

同时数据定位算法不变,只是多了一步虚拟节点到实际节点的映射,例如定位到“Node A#1”、“Node A#2”、“Node A#3” 三个虚拟节点的数据均定位到NodeA上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布。

3.总结

在分布式系统中一致性hash算法起着不可忽略的地位,无论是分布式缓存,还是分布式RPC框架的负载均衡策略都有所使用。分布式系统每个节点都有可能失效,并且新的节点很可能动态的增加进来的情况,如何保证当系统的节点数发生变化的时候,我们的系统仍然能够对外提供良好的服务,这是值得考虑的。

一致性哈希算法能尽可能减少服务器数量变化所导致的缓存迁移。

consistent(一致性) hash算法能够在一定程度上改善缓存的雪崩问题,它能够在移除/增加一台缓存服务器时,尽可能小的改变已存在的key映射关系,避免大量key的重新映射。

先构造一个长度为2的32次方的整数环(这个环被成为一致性Hash环),根据节点名称的Hash值(其分布为[0, 2^32-1]),接着在Hash环上顺时针查找距离这个key值的hash值最近的服务器节点,完成key到服务器的映射查找。

这种算法解决了普通余数Hash算法伸缩性差的问题,可以保证在上线、下线服务器的情况下尽量有多的请求命中原来路由到的服务器。





参考地址:

1.一致性hash和普通hash区别?,https://blog.csdn.net/weixin_43217065/article/details/107659713

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不愿放下技术的小赵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值