文章目录
- 1.Hash算法定义
- 2.应用
- 2.1 安全加密
- 2.2 唯一标识
- 2.3 数据校验
- 2.4 散列函数
- 2.5 负载均衡
- 2.6 数据分片
- 2.7 分布式存储
1.Hash算法定义
- 哈希算法:将任意长度的二进制值串映射为固定长度的二进制值串,这个映射的规则就是哈希算法,而通过原始数据映射之后得到的二进制值串就是哈希值。
- 设计一个优秀的哈希算法并不容易,需要满足的几点要求:
1· 从哈希值不能反向推导出原始数据(所以哈希算法也叫单向哈希算法);
2· 对输入数据非常敏感,哪怕原始数据只修改了一个Bit,最后得到的哈希值也大不相同;
3· 散列冲突的概率要很小,对于不同的原始数据,哈希值相同的概率非常小;
4· 哈希算法的执行效率要尽量高效,针对较长的文本,也能快速地计算出哈希值。
2.应用
2.1 安全加密
- 最常用于加密的哈希算法是MD5(MD5 Message-Digest Algorithm,MD5 消息摘要算法)和SHA(Secure Hash Algorithm,安全散列算法)。
- 还有很多其他加密算法,比如DES(Data Encryption Standard,数据加密标准)、AES(Advanced Encryption Standard,高级加密标准)。
- 加密的哈希算法有两点格外重要。第一点是很难根据哈希值反向推导出原始数据,第二点是散列冲突的概率要很小。
2.2 唯一标识
- 海量图片查找
- 给每一个图片取一个唯一标识。比如,从图片的二进制码串开头取100个字节,从中间取100个字节,从最后再取100个字节,然后将这300个字节放到一块,通过哈希算法(比如MD5),得到一个哈希字符串,用它作为图片的唯一标识。通过这个唯一标识来判定图片是否在图库中。
2.3 数据校验
- BT下载电影,从多个机器上分别下载,最后合并成一个。
- 对 n 个文件块分别取哈希值,并且保存在种子文件中。只要文件块的内容有一丁点儿的改变,最后计算出的哈希值就会完全不同。当文件块下载完成之后,我们可以通过相同的哈希算法,对下载好的文件块逐一求哈希值,然后跟种子文件中保存的哈希值比对。如果不同,说明这个文件块不完整或者被篡改了,需要再重新从其他宿主机器上下载这个文件块。
2.4 散列函数
- 散列函数对于散列算法冲突的要求要低很多。出现个别散列冲突,只要不是过于严重,我们都可以通过开放寻址法或者链表法解决。
- 是否能反向解密也并不关心。散列函数中用到的散列算法,更加关注散列后的值是否能平均分布,散列函数执行的快慢,也会影响散列表的性能,所以,散列函数用的散列算法一般都比较简单,比较追求效率。
思考:区块链
- 区块链是一块块区块组成的,每个区块分为两部分:区块头和区块体。
- 区块头保存着自己区块体和上一个区块头的哈希值。
- 因为这种链式关系和哈希值的唯一性,只要区块链上任意一个区块被修改过,后面所有区块保存的哈希值就不对了。
- 区块链使用的是SHA256哈希算法,计算哈希值非常耗时,如果要篡改一个区块,就必须重新计算该区块后面所有的区块的哈希值,短时间内几乎不可能做到。
分布式系统应用:
2.5 负载均衡
- 我们可以通过哈希算法,对客户端IP地址或者会话ID计算哈希值,将取得的哈希值与服务器列表的大小进行取模运算,最终得到的值就是应该被路由到的服务器编号。我们就可以把同一个IP过来的所有请求,都路由到同一个后端服务器上。
2.6 数据分片
- 假设有1亿张图片,很显然,在单台机器上构建散列表是行不通的。因为单台机器的内存有限,而1亿张图片构建散列表显然远远超过了单台机器的内存上限。
- 对数据进行分片,然后采用多机处理。我们准备n台机器,让每台机器只维护某一部分图片对应的散列表。
- 每次从图库中读取一个图片,计算唯一标识,然后与机器个数n求余取模,得到的值就对应要分配的机器编号,然后将这个图片的唯一标识和图片路径发往对应的机器构建散列表。
- 要判断一个图片是否在图库中的时候,我们通过同样的哈希算法,计算这个图片的唯一标识,然后与机器个数n求余取模。假设得到的值是k,那就去编号k的机器构建的散列表中查找。
2.7 分布式存储
- 海量数据缓存在n台机器上,哪天缓存不够了,加一台机器,之前数据是通过和n求模得到的,现在全失效了?
- 我们需要一种方法,使得在新加入一个机器后,并不需要做大量的数据搬移。这时候,一致性哈希算法就要登场了。
- 假设我们有k个机器,数据的哈希值的范围是[0,MAX]。我们将整个范围划分成m个小区间(m远大于k),每个机器负责m/k个小区间。当有新机器加入的时候,我们就将某几个小区间的数据,从原来的机器中搬移到新的机器中。这样,既不用全部重新哈希、搬移数据,也保持了各个机器上数据数量的均衡。