文章出处:极客时间《数据结构和算法之美》-作者:王争。该系列文章是本人的学习笔记。
哈希算法的定义
文章来自极客时间。
参考网页
定义:将任意长度的二进制值串映射为固定长度的二进制值串。映射之后的二进制值串称为哈希值。
符合几点要求:
1 从哈希值不能推导出原文。
2 原文有一个bit的值发生变化,哈希值不相同。
3 散列冲突的概率要小,对于不同的原文产生相同哈希值的概率要小。
4 高效,对长文本生成哈希值也要非常快。
哈希算法的常见应用
1 安全加密
最常用于加密的算法有MD5,SHA、DES、AES。
鸽巢原理。哈希算法只能尽量减少碰撞冲突不能完全避免冲突的理论基础就是鸽巢原理。10个鸽巢,11只鸽子,肯定有2只鸽子在同一个鸽巢内。哈希值的长度是固定的,例如MD5算法哈希值是128位。128位能表示21282^{128}2128个数据。超出范围就会产生冲突。一般情况下,哈希值越长,产生冲突的概率就越低。
加密算法选择多长的哈希值主要由破解难度和计算时间两方面决定。
2 唯一标识
图片查询
唯一标识是指用哈希值表示一个长文件。例如图片、文件。如果我们想查找一个图片在我们的图片库中是否存在,我们希望通过比对文件查找。因为图片标题可能和图片内容不匹配。一个图片文件一般10几K,甚至几M,要想直接比较非常耗时。我们可以读取图片文件的开头100个字节,中间100个字节,末尾100个字节,放到一起计算哈希值。查询图片的时候,对于输入的图片也按照同样的方式计算哈希值,然后比较是否有相同哈希值的图片。
3 数据校验
BT下载
BT下载是基于P2P协议从多台机器上同时下载一个2G的电影。这个文件可能被分割为很多块。等所有块下载完成再组装成一个文件。但是网络传输是不安全的。我们需要在电影文件分割的时候,记录每个文件对应的哈希值,写在种子文件中。当下载完成后,计算下载文件的哈希值和种子文件中的哈希值比对。如果不一致,需要重新下载。
4 散列函数
要求散列函数计算的哈希值能够均匀分布在各个槽。
要求散列函数简单高效。
5 负载均衡
会话粘滞的负载均衡算法
我们可以维护一个映射表,将会话ID与对应的服务器IP做映射。这样简单,但是映射表会很大。客户端上下线、服务端上下线,都要维护,维护成本高。
我们借助哈希算法,对每个会话ID计算哈希值。将取得的哈希值与服务器列表大小取余,得到最终服务器编号。
6 数据分片
统计日志文件中搜索词次数
如果日志文件很多很大,单台计算内存可能不够,而且计算也很慢。可以考虑分布式计算。我们对搜索词取哈希值,然后跟服务器个数取余,最终得到的值就是服务器编号。这样同样的关键词就被分配到同一台服务器,进而计算出现次数。
7 分布式存储
一致性哈希
我们可以通过哈希算法把数据分别存储到某台服务器上。如果需要增加一台服务器,则所有缓存的数据都失效,需要再次计算哈希值取余,放到新的服务器上。但是此时对数据库压力很大,容易形成雪崩。
解决的方法是采用一致性哈希。我们把哈希值想象为一个闭环。
整个空间按顺时针方向存储。当插入数据A、B、C、D的时候,如下图所示。A存储咋server1,B、C存储在server2,D存储在server3。假设server3发生意外宕机,只需要把数据D迁移到seerver2。
假设我们有k个服务器,哈希值的取值范围是[0,MAX]。我们将哈希值分为m个区间(m远大于k),每个机器负责m/k个小区间。当有新机器加入的时候,我们就将某几个小区间的数据,从原来的机器上搬移到新的机器中。这样既不会重新哈希全部的数据,也保持了各个机器上的数据量的均衡。