哈希的四种特征
- 输入可以无穷,输出是有穷尽的
- 输入相同的情况下,输出一定相同(不包含随机性)
- 不同的输入,有可能输出相同,此时的情况为哈希碰撞(概率极小)
- 均匀性和离散性能够得到保证
- 离散性或者均匀性越好,证明这个哈希函数越优秀。
- 哈希值%M:表示在0-M之间均匀分布。
哈希函数的题型
- 给40亿个数,然后给你1G内存,找出相同数值出现次数比较多的数。
- 40亿个数:约合为G为
- 16000000000 字节=14.9011612 G
- 按照传统的办法(暴力方法)用哈希表进行计算的话,最坏情况下40亿种不同的数据
- 远远超出题目所给的内存
- 解题思路:
- 利用哈希表进行分组
- 先对每个数进行哈希计算,得出一个哈希值:(x);再%100,14.9G往前推两位为0.149G,题目中说给的内存就够了。
- 相当于将数值进行了0-99的分组
- 对分组后的值再进行统计计算(此时用的是哈希表的累加),即使有哈希碰撞也进行累加。
传统的哈希表的实现套路
- 最关键的两部
- 构建哈希表
- 根据元素查找位置
- 构建哈希表相当于是一个计算hashcode值,然后是一个对号入座的关系,如果作为上有关系,用链表将其串起来,
- 当串联到一定程度就会进行扩容工作,保证哈希碰撞的减少
- 扩容类似于java的离线迁移,将数据一次性备份完毕后将旧的使用权迁移到新的,旧的使用权直接被垃圾回收。理论上也是一个O(1)的时间复杂度
- 当串联到一定程度就会进行扩容工作,保证哈希碰撞的减少
- 查找的过程是一个计算出hashcode,然后根据地址进行检索,检索完毕后直接查找,不管是否有链表都是一个O(1)的关系,
关于哈希表的题
-
创建一种数据结构,要求实现下列方法
-
insert:插入不能重复
-
find:根绝key查找
-
getRandom:返回一个随机的value
-
-
解题思路:
-
这里最难点是:如何将删除后数补上
-
概要一句话:
-
删除尾部,将尾部填充到被删除的那里。
-
-
-
布隆过滤器
- 应用的业务场景(解决是否存在的问题)
- 应在用redis的缓存穿透
- 应用在类似于黑名单的系统
- 在以前没有布隆过滤器的时候,如何做黑名单系统:hashMap/hashSet;但是如果黑名单有10亿个数据,放在内存就会有点不合适了,放在硬盘查询又会太慢。但是特点是:没有失误率~
- 布隆过滤器产生,他缩小空间的根本方法是使用是用的bit位的map,4个字节=32个bit,8个字节=64个bit。
- 布隆过滤器的构成三要素:
- 这个数据结构不可以删除
- 要确定样本量大小
- 要允许存在一定的四五率
- 根据这3个条件可以确定:
- hash函数的数量
- bit位map的大小
- 布隆过滤器的公式
- 计算布隆过滤器(有关布隆过滤器的题:1、又一定失误率。2、该数据结构可以进行修改。):
- bitmap计算公式:
- n为样本量,p为失误率
- 哈希函数个数计算公式: m为bitmap的大小,n为样本量
- 真实失误率 n:样本量,k:哈希函数个数,m:bitmap的大小
- n为样本量,p为失误率
- 总之bitmap太大,浪费空间,bitmap太小,失误率得不到保证。
- bitmap计算公式:
- 计算布隆过滤器(有关布隆过滤器的题:1、又一定失误率。2、该数据结构可以进行修改。):
一致性哈希
- 下面是来自百度百科:
- 服务分为逻辑服务和数据服务
- 逻辑服务的部署随便,因为逻辑相同,各个实例是等效的。
- 而数据层就不一样了
- 分布式的数据服务器存在底层如何维持的一个问题,
- 传统的数据分布式是如何存储:(用区别最大的键来左hash的key:例如:身份证号码,姓名,电话号码)。
- 将数据进行hashCode()方法后,然后%数据服务器的个数,将数据存储到对应的服务器中,因为hashCode的均匀性,会将数据均匀的存到各个数据库中
- 存在的问题:
- 如果服务器装载不下更多的数据的时候,此时需要对数据服务器进行扩容
- 扩容的代价比较大,需要对所有的数锯重新进行hashCode方法,然后再模与当前的数据库服务器,重新塞到数据服务器中。数据迁移的代价是全量的。
- 无法根据服务器的性能进行调节它所存储的
- 对于负载均衡问题无法进行处理。
- 负载问题是由该数据是否非常“红”来决定的
- 一致性哈希解决了经典的数据迁移的问题(代价降到最低)。
- 一致性hash里没有%这回事,但是依旧要进行hashCode的处理
- 做法:
- 用一个能将机器信息区分开的key来做hash,用机器的信息做hash值(此时用hash类的算法就行,我此处是MD5算法,因为值比较大,有更多的选择)
- 用信息做成环
- 步骤:
- 当此时要多加一个数据库服务器或者减少一个数据库服务器的时候:
- 步骤:
- 存在潜在的两个问题:
- 机器数量很少可能一上来不均分
- 增加一台机器或者减少一台机器,负载可能不均衡
- 解决上面的问题:用虚拟节点技术
- 每个机器随机均匀预设1000个虚拟节点,三个机器就是3000个虚拟节点
- 在环中,随机一块区域,每个节点的个数均匀,整个环中,节点个数均匀。
- 当增加机器的时候又多出1000个虚拟节点,总计4000个虚拟节点
- 新加的4号机器从123机器中各抽出等比例的节点,最终凑成自己的1/4。减少也是同理。
- 每个机器随机均匀预设1000个虚拟节点,三个机器就是3000个虚拟节点
- 一致性哈希和虚拟节点搭配还可以管理负载,能者虚拟节点多点,弱者,虚拟节点少点。