什么是哈希算法
1.定义:将任意长度的二进制值串映射为固定长度的二进制值串,这个映射的规则就是哈希算法,原始数据通过映射之后得到的值即为二进制串的哈希值。
2.一个优秀的哈希算法应满足什么样的条件?
1.不能反向推到出元数据(即单向哈希算法)。
2.对输入数据敏感,即使修改一个bit位,得到的结果也大不同。
3.散列冲突概率要小,对不同的原始数据,哈希值相同的概率非常小。
4.执行效率要尽量高,针对较长的串,也能快速计算出哈希值。
3.例如
MD5("今天我来讲哈希算法") = bb4767201ad42c74e650c1b6c03d78fa MD5("jiajia") = cd611a31ea969b908932d44d126d195b
MD5("我今天讲哈希算法!") = 425f0d5a917188d2c3c3dc85b5e4f2cb MD5("我今天讲哈希算法") = a1fb91ac128e6aa37fe42c663971ac3d
哈希算法的应用
1.安全加密
如MD5、SHA、DES、AES
无法做到零冲突,但概率极低。
开发时,权衡破解难度和计算时间来选择合适的算法。
2.唯一标识
搜索相同的文件或者图片时,转换成二进制直接对比的话是比较耗时的。
我们可以通过构造一个唯一标识或信息摘要,进行对比以提高效率。
若要提高效率及准确率,我们可以将图片的唯一标识和路径保存到散列表,当查找时,可以通过哈希算法获取图片的唯一标识,判断其是否在散列表中,若不在,则证明图片不存在;若存在该标识,则获取对应路径的图片进行全量对比。
3.数据校验
比如,迅雷、电驴等下载软件
对下载的数据块分别取哈希值,与种子文件中的值进行比对。
4.散列函数
相对哈希算法,散列函数对冲突的要求低,且不关心是否能反向解密,其只关心数据是否能均分的分布,另外,散列函数一般比较简单,比较追求效率。
5.负载均衡
通过哈希算法对客户端ip或会话id计算哈希值,将取得的哈希值与服务器列表的大小进行取模运算,最终得到的值就是应该被路由到的服务器编号。(即实现了一个会话粘滞[session sticky]的负载均衡算法)
其实,最直接的会话粘滞负载均衡的实现方法是,维护一张映射关系表,记录客户端ip或会话id与服务器编号的关系,但其弊端也很明显,1,客户端很多时,比较浪费空间;2.客户端上下线、服务器扩容缩容时需要重新维护,成本高。
负载均衡的算法有很多,比如还可以通过轮询、随机、加权轮询等来实现。
6.数据分片
例1:如何统计“搜索关键词”的出现次数(1T日志文件,记录了用户搜索关键词,如何快速统计词频)
先对数据进行分片,然后采用多台机器进行处理来提高速度。
从日志文件中,依次读取每个搜索关键词,并且通过哈希算法计算哈希值,与机器数量n求模即该分配到的机器编号,最终,同一个词都会被分配到同一个机器上,最终,把所有机器的结果合并即可。
这个过程也是MapReduce的基本设计思想。
例2:如何快速判断图片是否在图库中?
和唯一标识时不同的是,若这里的图片库数量很大,单机是不可能完成的。
我们同样可以对数据进行分片,采用多机处理,准备n台机器,让每台机器维护某一部分图片的散列表,当判断时,通过同样的哈希算法,计算图片的唯一标识,与机器个数n取模得到k,则去编号为k的机器上的散列表中查找。
在工程中,可以通过估算,来对事先需要投入的资源、资金有个大概的了解,以更好的评估方案可行性。
实际上,针对海量数据的处理问题,我们可以采用多机分布式处理,借助这种分配的思路,可以突破单机内存、CPU等资源的限制。
7.分布式存储
一致性哈希算法(在加入新机器后,并不需要做大量的数据搬移,否则会发生雪崩效应)
如何防止数据库信息被脱库
通过哈希算法,对密码进行加密后保存。
但简单的加密并不能解决问题,因为还有字典攻击的问题,针对字典攻击,我们可以引入一个盐(salt)跟用户的密码组合在一起,增加密码的复杂度,我们可以拿组合后的字符串来做哈希算法并存储到数据库。