前言
哈希算法经常使用的场景是哈希表,也叫散列表。但是在很多 场景下,哈希算法都有广泛的应用
提示:以下是本篇文章正文内容
一、哈希算法是什么?
可以概括为:将任意长度的二进制串映射为固定长度的二进制串,这个映射规则就是哈希算法。
需要满足的要求:
- 散列冲突概率要很小。
- 算法的执行效率要高效,尤其针对长文本。
- 单向性,不能通过给定的密文信息,推出明文。满足加密需求。
- 对原数据的任意一点修改,所得哈希值都大不相同。
- 抗强碰撞性
二、应用一:安全加密
常用于加密的哈希算法包括:MD5-消息摘要算法、SHA-安全散列算法、DES、AES算法。 MD5是常见的哈希算法,哈希值是固定的 128 位二进制串,能表示的数据是有限的,最多能表示 2^128 个数据。 因为我们的明文信息有无数种可能,远超过2^128,所以总会存在哈希冲突。 但是因为哈希值的范围很大,冲突的概率极低,所以相对来说还是很难破解的。 MD5散列冲突的概率要小于 1/2^128。
项目工程的应用 单纯使用MD5对密码进行加密已经没有很好的安全性,因为很多常见的密码都已经被计算出哈希值,随便搜就有很多MD5破解的网站,要想继续使用MD5,还需要对明文信息加入其它信息。 加盐加密:可以对要加密的数据再加入盐值,这个盐值可以是时间戳、随机数,等任何东西,将盐值和密码以一定规则组合在一起,再进行MD5加密,可以有效的保密信息。盐值也需要保存在数据库,比如密码加密后,要想登陆该账号,还需要当时的盐值。但是由于盐值和明文的组合方式有成千上万种,所以有很好的安全性。
三、应用二:唯一标识
场景: 如果要在海量的图库中,搜索一张图是否存在,我们不能单纯地用图片的元信息(比如图片名称)来比对,因为有可能存在名称相同但图片内容不同,或者名称不同图片内容相同的情况。
解决:
如果还想继续提高效率,我们可以把每个图片的唯一标识,和相应的图片文件在图库中的路径信息,都存储在散列表中。当要查看某个图片是不是在图库中的时候,我们先通过哈希算法(比如MD5)对这个图片取唯一标识,然后在散列表中查找是否存在这个唯一标识。通过这个唯一标识来判定图片是否在图库中,这样就可以减少很多工作量。
如果不存在,那就说明这个图片不在图库中;如果存在,我们再通过散列表中存储的文件路径,获取到这个已经存在的图片,跟现在要插入的图片做全量的比对,看是否完全一样。如果一样,就说明已经存在;如果不一样,说明两张图片尽管唯一标识相同,但是并不是相同的图片。
四、应用三:散列函数
散列函数是设计一个散列表的关键。它直接决定了散列冲突的概率和散列表的性能。不过,相对哈希算法的其他应用,散列函数对于散列算法冲突的要求要低很多。即便出现个别散列冲突,只要不是过于严重,我们都可以通过开放寻址法或者链表法解决。
五、应用四:数据校验
比如在从服务器下载大文件时,一般将文件先分片,从多个机器上并行下载,最后再合在一起。下载的文件块有可能是被宿主机器恶意修改过的,又或者下载过程中出现了错误,所以下载的文件块可能不是完整的。就需要校验。可以将原始数据计算哈希值,再将下载来的文件计算哈希值,若相同,则下载文件是源文件。
六、应用五:负载均衡
负载均衡为例,常见的负载均衡方法有很多,但是它们的优缺点也都很明显:
- 随机访问策略。系统随机访问,缺点:可能造成服务器负载压力不均衡,俗话讲就是撑的撑死,饿的饿死。
- 轮询策略。请求均匀分配,如果服务器有性能差异,则无法实现性能好的服务器能够多承担一部分。
- 权重轮询策略。权值需要静态配置,无法自动调节,不适合对长连接和命中率有要求的场景。
- Hash取模策略。不稳定,如果列表中某台服务器宕机,则会导致路由算法产生变化,由此导致命中率的急剧下降。
- 一致性哈希策略。
除了一致性哈希策略外,哈希取模使用的较多。
哈希取模: 负载均衡时,假设现有4台服务器(编号分别为0、1、2, 3),使用哈希取模的计算方式则是:对访问者的IP,通过固定算式hash(IP) % N(N为服务器的个数),使得每个IP都可以定位到特定的服务器。
例如现有IP地址 10.58.34.31,对IP哈希取模策时,计算结果为2,即访问编号为2的服务器。
哈希取模的问题: 1.如果服务器宕机,或者新扩充了一台机器,那么这个服务器个数N将会变化,这个哈希算法将会变化,所有的缓存的负载信息都需要重新更新。 2.分库分表时,通常是根据用户的 ID 哈希取模得到的值然后路由到对应的存储位置,计算公式为:hash(userId) % N,其中N为分库或分表的个数。如果新增了一台机器,为了数据可用,需要做数据迁移,按照新的路由规则对所有用户重新分配存储地址。每次的库或表的数量改变你都需要做一次全部用户信息数据的迁移。这个工作量相当费时费力。
- 如果客户端很多,映射表可能会很大,比较浪费内存空间;
- 客户端下线、上线,服务器扩容、缩容都会导致映射失效,这样维护映射表的成本就会很大;
解决:一致性哈希算法。
一致性哈希: 一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数 H 的值空间为 0 ~ 2^32-1(即哈希值是一个32位无符号整形,这个数值是int的最大取值)。 整个空间圆按顺时针方向布局,圆环的正上方的点代表0,0点右侧的第一个点代表1。以此类推2、3、4、5、6……直到232-1。
那么,一致性哈希算法与上图中的圆环有什么关系呢?仍然以之前描述的场景为例,假设我们有4台服务器,服务器0、服务器1、服务器2,服务器3,那么,在生产环境中,这4台服务器肯定有自己的 IP 地址或主机名,我们使用它们各自的 IP 地址或主机名作为关键字进行哈希计算,使用哈希后的结果对2^32取模,多个服务器都通过这种方式进行计算,最后都会各自映射到圆环上的某个点,这样每台机器就能确定其在哈希环上的位。把原始数据得到的模值将它负载给该值下一个顺时针最近的服务器。
新增一个服务器,对应地再在环上根据哈希算法添加一个值即可。 删除同理。
但是会出现数据倾斜问题,可以将一个服务器加入其它信息计算多个哈希值,来讲服务器虚拟出更多的结点,从而每个服务器都有很多对应结点。避免了数据都集中分配给某个服务器的情况
总结
提示:这里对文章进行总结: 例如:以上就是今天要讲的内容,哈希算法还在数据分片、分布式存储中有应用,可以继续了解。
|