Cluster模式潜在问题学习笔记—一致性Hash算法回溯
1.Hash算法
⽐如说在安全加密领域MD5、SHA等加密算法,在数据存储和查找⽅⾯有Hash表等, 以上都应⽤到了Hash算法。
2.为什么需要使⽤Hash?
Hash算法较多的应⽤在数据存储和查找领域,最经典的就是Hash表,它的查询效率⾮常之⾼,其中的哈希算法如果设计的⽐较ok的话,那么Hash表的数据查询时间复杂度可以接近于O(1)
3.需求
提供⼀组数据 1,5,7,6,3,4,8,对这组数据进⾏存储,然后随便给定⼀个数n,请你判断n是否存在于刚才的数据集中?
- 先创建一个数组[1,5,7,6,3,4,8],然后进行循环遍历,按照顺序进行查找,如果相等就说明存在
(这种⽅法叫做顺序查找法 :这种⽅式我们是通过循环来完成,⽐较原始,效率也不⾼)
for(int element: list) { if(element == n) { 如果相等,说明n存在于数据集中 } }
- 二分查找:排序之后折半查找,相对于顺序查找法会提⾼⼀些效率,但是效率也并不是特别好
4.问题
:我能否不循环!不⼆分!⽽是通过⼀次查询就把数据n从数据集中查询出来?
定义⼀个数组
,数组⻓度⼤于等于数据集⻓度,此处⻓度为9,数据1就存储在下标为1的位置,3就存储在下标为3的元素位置 … … 依次类推。- 这个时候,我想看下5存在与否,只需要判断list.get(5) array[5] 是否为空,如果为空,代表5不存在于数据集,如果不为空代表5在数据集当中,通过⼀次查找就达到了⽬的,时间复杂度为O(1)。
- 这种⽅式叫做
“直接寻址法”
:直接把数据和数组的下标绑定到⼀起,查找的时候,直接array[n]就取出了数据 优点
:速度快,⼀次查找得到结果缺点
:浪费空间
,⽐如 1,5,7,6,3,4,8,12306 ,最⼤值12306 ,按照上述⽅式需要定义⼀个⽐如⻓度为12307的数组,但是只存储零星的⼏个数据,其他位置空间都浪费着数据如
:1,5,7,6,3,4,8,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2最⼤值12,⽐如开辟13个空间,存储不了这么多内容
- 现在,换⼀种设计,如果数据是
3,5,7,12306,⼀共4个数据
,我们开辟任意个空间,⽐如5个
,那么具体数据存储到哪个位置呢,我们可以对数据进⾏求模(对空间位置数5)
,根据求模余数确定存储位置的下标,⽐如3%5=3
,就可以把3这个数据放到下标为3的位置上
,12306%5=1
,就把12306这个数据存储到下标为1的位置上
3%5
- 上⾯对数据求模 (数据%空间位置数) 他就是⼀个hash算法,只不过这是⼀种⽐较普通⼜简单的hash算法,这种构造Hash算法的⽅式叫做除留余数法
- 如果数据是1,6,7,8,把这4个数据存储到上⾯的数组中,处理结果如下:
在此基础上采⽤开放寻址法(了解)
开放寻址法
:1放进去了,6再来的时候,向前或者向后找空闲位置存放,不好的地⽅,如果数组⻓度定义好了⽐如10,⻓度不能扩展,来了11个数据,不管Hash冲突不冲突,肯定存不下这么多数据拉链法
:数据⻓度定义好了,怎么存储更多内容呢,算好Hash值,在数组元素存储位置放了⼀个链表
注意
:
- 如果
Hash算法
设计的⽐较好的话,那么查询效率会更接近于O(1),如果Hash算法设计的⽐较low,那么查询效率就会很低了 - 所以,
Hash表的查询效率⾼不⾼取决于Hash算法
,hash算法能够让数据平均分布,既能够节省空间⼜能提⾼查询效率。Hash算法的研究是很深的⼀⻔学问,⽐较复杂,⻓久以来,Hash表内部的Hash算法也⼀直在更新,很多数学家也在研究。 hash算法
:- 除留余数法--------例子:3%5,这是3对5求模,对谁求模的数越大,越能避免
hash冲突
- 线性构造Hash算法
- 直接寻址法也是⼀种构造Hash的⽅式,只不过更简单,表达式:H(key)=key
- ⽐如H(key)=a*key + b(a,b是常量)
- 除留余数法--------例子:3%5,这是3对5求模,对谁求模的数越大,越能避免
hashcode
其实也是通过⼀个Hash算法得来的