哈希算法
- 将任意长度的二进制值串映射为固定长度的二进制值串,这个映射规则就叫做哈希算法
- 而映射得到的固定长度二进制值串就是哈希值。
- 哈希算法的要求
-
- 从哈希值不能反向推导出原始数据(哈希算法也叫单向哈希算法)
-
- 对原始值非常敏感,即使只有一个bit不同,也会得到不同的哈希值
-
- 散列冲突的概率很小
-
- 哈希算法执行效率高,针对较长文本,也能很快算出哈希值
哈希算法的应用
- 安全加密
- 唯一标识
- 数据校验
- 散列函数
- 负载均衡
- 分布式存储
安全加密
- 常用加密的哈希算法MD5(消息摘要算法)Message-Digest Algorithm 和 SHA Secure Hash Algorithm,安全散列算法)
- 其他加密算法,比如 DES(Data Encryption Standard,数据加密标准)、AES(Advanced Encryption Standard,高级加密标准)
- 加密哈希算法最重要是,不能反向推出原始值,散列冲突概率要很小
- 散列冲突小的原因:减少碰撞冲突的概率,但是无法做到完全不冲突
- 为什么哈希算法无法做到零冲突?
- 哈希算法产生的哈希值的长度是固定且有限的。比如前面举的 MD5 的例子,哈希值是固定的 128 位二进制串,能表示的数据是有限的,最多能表示 2^128 个数据,而我们要哈希的数据是无穷的。基于鸽巢原理,如果我们对 2^128+1 个数据求哈希值,就必然会存在哈希值相同的情况。这里你应该能想到,一般情况下,哈希值越长的哈希算法,散列冲突的概率越低。
- 没有绝对安全的加密。越复杂、越难破解的加密算法,需要的计算时间也越长。比如 SHA-256 比 SHA-1 要更复杂、更安全,相应的计算时间就会比较长。
- 字典攻击,如果用户信息被”脱库“,即使密码是密文,也可以维护一个常用密码字典表,字典中的密码通过哈希算法计算和”脱裤”密文比较,如果相同,基本确定
- 针对字典攻击可以引入一个盐(salt),和用户的密码组合在一起
唯一标识
- 如果要在海量的图库中,搜索一张图是否存在,我们不能单纯地用图片的元信息(比如图片名称)来比对
- 可以给每一个图片取一个唯一标识,或者说信息摘要。
- 可以从图片的二进制码串开头取 100 个字节,从中间取 100 个字节,从最后再取 100 个字节,然后将这 300 个字节放到一块,通过哈希算法(比如 MD5),得到一个哈希字符串,用它作为图片的唯一标识。通过这个唯一标识来判定图片是否在图库中,这样就可以减少很多工作量。
- 继续提高效率,我们可以把每个图片的唯一标识,和相应的图片文件在图库中的路径信息,都存储在散列表中。当要查看某个图片是不是在图库中的时候,我们先通过哈希算法对这个图片取唯一标识,然后在散列表中查找是否存在这个唯一标识。
数据校验
- BT下载,将文件切片,下载完再拼接起来,怎么保证下载文件块没有被修改过?
- 通过文件的哈希值来判定,哈希函数对数据非常敏感,有一丁点改动也会得到不同的哈希值
散列函数
- 散列函数是设计一个散列表的关键
- 相对于其他应用,散列函数对散列算法的冲突要求低很多,出现冲突可以通过开放寻址法和链表法解决
- 散列函数对于散列后值是否均匀分布要求更高,这决定散列表的性能
负载均衡
如何实现一个会话粘滞的负载均衡算法?就是需要在同一个客户端上,在一次会话中的所有请求都路由到同一个服务器上
最简单的就是维护一张表,客户端ip和服务器id,每次查询这个表,找到对应的服务器
- 如果客户端很多,表很大,浪费内存
- 客户端上线下线,服务器扩容缩容,都会导致映射失效,这样维护映射表成本就会很大
哈希算法可以完美解决
- 通过哈希算法,对客户机ip计算哈希值
- 将取得的哈希值与服务器列表大小进行取模运算,最终得到的值就是服务器的id
数据分片
- 假如有1T的日志文件,记录了用户的搜索关键词,想要统计出每个关键词的搜索次数
- 搜索文件很大,没法放在一台机器的内存中
- 只用一台机器,搜索时间很长
- 可以先对数据进行切片,然后采用多台机器处理的方法,来提高速度
- 先使用n台机器并行处理,依次读取搜索关键词
- 并对每个关键词求哈希值,哈希值对n取模,得到的值就是因该被分配到的机器编号
- 哈希值相同的搜索关键词就被分配到了同一个机器上。也就是说,同一个搜索关键词会被分配到同一个机器上
- 这里的处理过程也是 MapReduce 的基本设计思想。
分布式存储
- 分布式缓存
- 机器不够,添加一台机器,所有的数据都要重新计算哈希值,然后重新搬移到正确的机器上。这样就相当于,缓存中的数据一下子就都失效了。所有的数据请求都会穿透缓存,直接去请求数据库。这样就可能发生雪崩效应,压垮数据库
- 我们需要一种方法,使得在新加入一个机器后,并不需要做大量的数据搬移。这时候,一致性哈希算法就要登场了
- 假设我们有 k 个机器,数据的哈希值的范围是[0, MAX]。我们将整个范围划分成 m 个小区间(m 远大于 k),每个机器负责 m/k 个小区间。当有新机器加入的时候,我们就将某几个小区间的数据,从原来的机器中搬移到新的机器中。这样,既不用全部重新哈希、搬移数据,也保持了各个机器上数据数量的均衡。
- 际上,一致性哈希算法的应用非常广泛,在很多分布式存储系统中,都可以见到一致性哈希算法的影子。