1、哈希函数和哈希表
当通过put方法存入对象时,会调用key对象的hashCode()方法计算出hashcode,通过hashcode找到bucket位置保存entry对象。获取对象时,通过key计算出hashcode,找到bucket位置,HashMap采用链表解决碰撞,因此遇到冲突时,就访问bucket位置上链表的每个点,直到key对象的equals()相等。
jdk1.8后,当链表长度大于8,后面的数据存入红黑树
2、设计RandomPool结构
【题目】 设计一种结构,在该结构中有如下三个功能:
insert(key):将某个key加入到该结构,做到不重复加入。
delete(key):将原本在结构中的某个key移除。 getRandom():
等概率随机返回结构中的任何一个key。
【要求】 Insert、delete和getRandom方法的时间复杂度都是
O(1)
做法:
insert和getRandom:
map<key ,integer> map1 ,map<integer, key> map2 。当第一个插入o1,就在map1.add(o1,1),map2.add(1,o1)。 当希望进行get时,通过数字进行random,得到的就是等概率的。
delete:
删掉后存在洞,这些洞影响性能,无法保证o( 1 )。 做法:拿最好一个值和洞进行交换,size – 。
3、布隆过滤器
有失误率,宁可错杀三千不可放过一个。
现在有100亿个黑名单,设置k个哈希函数,对于每个黑名单上的url,分别对k个哈希函数进行计算,得到的hashcode % m (m就是布隆过滤器的大小),对这个位置置1,这样一个url会对k个位置进行置1。
当需要检验一个url在不在黑名单上时,分别对k个哈希函数进行计算,得到的每个位置假设全部位1,那么就认为它在黑名单上,否则,认为不在。
m = n * lnP / (ln2)^2; m是布隆过滤器的大小(开的bit数组),p是预期失误率
k = ln2 * m/n ; 哈希函数的个数。
4、一致性哈希(负载均衡)
转自:http://www.zsythink.net/archives/1182
需求: 有多台后端服务器,希望进行负载均衡。举个例子:现在有3台服务器,那么读取图片的请求会均衡的负载在三台服务器上。
错误做法:一种做法是对请求进行哈希计算,计算结果对服务器数量去模,例如3台服务器,取模结果为0,1,2。这种做法存在致命的缺点,当服务器数量进行变化,模的底数变了,那么哈希计算出来的值就发送了改变。那么在实际中的体现是这样的:用户A的读取个人资料请求一直交给01服务器处理,现在请求被提交到了02服务器,那么就读取到错误的信息。
矫正数据:收集原来的请求哈希值对应的服务器,转存到新的哈希值计算的服务器上。代价是非常大的。
一致性哈希解决:对每台服务器的IP地址(唯一标识)进行哈希算法,得到一个值。 根据这个值可以在环上进行划分区域,这样每台服务器掌管一段区间。 当请求发过来时,把请求通过哈希函数进行计算,得到环上的一个位置, 然后通过二分算法找到离他最近的一个服务器的位置(超过容器大小,就从0开始),这个请求就交给了某台服务器。
矫正数据:添加或减少服务器时,矫正的代价只有一个结点的数据搬运到另一个结点的数据而已。
不过服务器IP在环上的映射并不均衡。很容易映射成这种情况。
那么解决方案就是:通过虚拟节点进行哈希计算,使它们均匀的分布在环上。 请求和虚拟节点进行匹配。 虚拟节点和物理服务器之间是多对一的关系。虚拟节点再发请求发送到自己对应的服务器上即可。