0%

哈希算法

哈希算法定义

散列=哈希
将任意长度的二进制值串映射为固定长度的二进制值串,这个映射的规则就是哈希算法,通过原始数据映射之后得到的二进制值串就是哈希值

  • 从哈希值不能反向推导出原始数据(哈希算法也叫单项哈希算法);
  • 对输入数据非常敏感,哪怕原始数据只修改了一个Bit,最后得到的哈希值也大不相同;
  • 散列冲突的概率要很小,对于不同的原始数据,哈希值相同的概率非常小;
  • 哈希算法的执行效率要尽量高效,针对较长的文本,也能快速的计算出哈希值。

哈希算法应用

安全加密(数字签名/信息摘要)

最常用于加密的哈希算法是MD5(MD5 Message-Digest Algorithm,MD5消息摘要算法)和SHA(Secure Hash Algorithm,安全散列算法)。

其他加密算法(非哈希)DES(Data Encryption Standard,数据加密标准)、AES(Advanced Encryption Standard,高级加密标准)。

第一很难根据哈希值反向推导出原始数据。
第二散列冲突的概率要很小。鸽巢原理(抽屉原理)

哈希算法产生的哈希值的长度是固定且有限的。基于鸽巢原理,必然会存在哈希值相同的情况。一般情况下,哈希值越长的哈希算法,散列冲突的概率越低。
没有绝对安全的加密,越复杂、越难破解的加密算法,需要的计算时间也越长。

针对字典攻击,可以引入一个盐salt,跟用户密码组合在一起,增加密码的复杂度。拿组合之后的字符串来做哈希算法加密,将它存储到数据库中,进一步增加破解的难度。

唯一标识

哈希算法可以对大数据做信息摘要,通过一个较短的二进制编码来表示很大的数据。
将每一个图片开头、中间、结尾分别取一部分字节,通过哈希算法,得到一个哈希字符串,用它作为图片的额唯一标识。通过这个唯一标识来判定图片是否在图库,可以减少很多工作量。

数据校验

校验数据的完整性和正确性。
BT协议,将一个大文件分成多块小文件,通过哈希算法,对小文件块分别取哈希值,并保存在种子文件中。当文件块下载完成之后,可以通过相同的哈希算算发,对下载好的文件块逐一求哈希值,然后跟种子文件中保存的哈希值比对。如果不同,说明这个文件块不完整或者被篡改了,需要再重新从其他宿主及其上下载这个文件块。

散列函数

散列函数是涉及一个散列表的关键。它直接决定了散列冲突的概率和散列表的性能。
散列函数对于散列算法冲突的要求低很多,即便出现个别散列冲突,只要不是过于严重,都可以通过开放寻址法或者链表法解决。
散列函数更加关注散列后的值是否能平均分布,使一组数据能均匀的散列在各个槽中。
散列函数用的散列算法一般都比较简单,比较追求效率,注重性能。

负载均衡

轮询、随机、加权轮询等都属于负载均衡算法。
在同一个客户端上,在一次绘画中的所有请求都路由到同一个服务器上。需要会话粘滞的负载均衡算法。

  • 维护一张映射关系表,表的内容是客户端IP地址或者会话ID与服务器编号的映射关系,客户端发出的每次请求,都要先在映射表中查找应该路由到的服务器编号,然后再请求编号对应的服务器。

    客户端很多,映射表很大,比较浪费内存空间;客户端下线、上线,服务器扩容、缩容都会导致映射失败,维护映射表的成本会很大。

  • 通过哈希算法,对客户端IP地址或者会话ID计算哈希值,将取得的哈希值与服务器列表的大小进行取模运算,最终得到的值就是应该被路由道德服务器编号。这样就可以把同一个Ip过来的所有请求都路由到同一个后端服务器上。

数据分片

  1. 统计搜索关键词出现的次数
    1T的日志文件,记录了用户的搜索关键词,要快速的统计出每个关键词被搜索的次数 。
    先对数据进行分片,然后采用多肽及其处理的方法,来提高处理速度。用n台机器进行处理。从搜索记录的日志文件中,依次读出每个搜索关键词,并且通过哈希函数计算哈希值,然后再跟n取模,最终得到的值,就是应该被分配到的机器编号。
    哈希值相同的搜索关键词就被分配到了同一个机器上。每个机器分别计算关键词出现的次数,最后合并起来就是最终的结果。

  2. 快速判断图片是否在图库中
    1亿张图片,在单台机器上构建散列表是行不通的。单台机器的内存有限。
    对数据进行分片,然后采用多机处理。准备n台及其,让每台机器只维护某一部分图片对应的散列表。每次从图库中读取一个图片,计算唯一标识,然后与机器个数n求余取模,得到的值就对应要分配的机器编号,然后将这个图片的唯一标识和图片路径发往对应的及其构架散列表。
    当要判断一个图片是否在图库中的时候,通过同样的哈希算法,计算这个图片的唯一标识,然后与机器个数n求余取模。假设得到的值是k,那就去编号k的机器构建的散列表中查找。

针对海量数据的处理问题,都可以采用多机分布式处理。借助分片的思路,突破单机内存、CPU等资源的限制。

分布式存储

为了提高互联网海量用户海量数据的读取、写入能力,采用分布式的方式来存储。
用数据分片的思想,采用哈希算法对数据取哈希值,然后对机器个数取模,最终值就是应该存储的缓存机器编号。
数据增多扩容时,所有的数据都要重新计算哈希值,然后重新搬移到正确的机器上。相当于缓存中的数据一下子都失效了,所有的数据请求都会穿透缓存,直接去请求数据库,这样可能发生雪崩效应,压垮数据库。

解决方法,一致性哈希算法。
假设有k个机器,数据的哈希值的范围是[0,MAX]。将整个分为划分成m个小区间(m远大于k),每个机器负责m/k个小区间。当有新机器加入的时候,就将某几个小区间的数据,从原来的机器中搬移到新的机器中。这样既不用全部重新哈希、搬移数据,也保持了各个机器上数据数量的均衡。

一致性哈希一般会借助一个虚拟的环和虚拟节点,更加优美的实现出来。

把服务器映射到hash环,将需要缓存的对象也映射到hash环上,从对象映射的位置开始,沿顺时针方向遇到的第一个服务器,就是要缓存到的服务器。服务器数量发生改变时,并不是所有的缓存都会失效,只有部分缓存会失效(当前服务器位置与其逆时针前一个位置的缓存失效)。
服务器映射到hash环上的时候,很有可能出现hash环偏斜的情况,缓存会极不平衡的分布在各个服务器上。虚拟节点解决分配不均问题。虚拟节点是实际节点在hash环上的复制品,均匀的分布在环上,一个实际节点可以对应多个虚拟节点。虚拟节点越多,hash环上的节点就越多,缓存被均匀分布的概率就越大。