哈希算法(上):如何防止数据库中的用户信息被脱库?
1.什么是哈希算法
1).任意长度的二进制值串映射为固定长度的二进制值串,这个映射的规则就是哈希算法,而通过原始数据映射之后得到的二进制值串就是哈希值。
2).设计哈希算法满足的几点要求:
- 从哈希值不能反向推导出原始数据(所以哈希算法也叫单向哈希算法);
- 对输入数据非常敏感,哪怕原始数据只修改了一个 Bit,最后得到的哈希值也大不相同;
- 散列冲突的概率要很小,对于不同的原始数据,哈希值相同的概率非常小;
- 哈希算法的执行效率要尽量高效,针对较长的文本,也能快速地计算出哈希值
哈希算法的四个应用。
应用1:安全加密
- 1).例如:MD5,SHA,DES,AES
- 2).不管是什么哈希算法,我们只能尽量减少碰撞冲突的概率,理论上是没办法做到完全不冲突的,鸽巢原理(也叫抽屉原理)。这个原理本身很简单,它是说,如果有 10 个鸽巢,有 11 只鸽子,那肯定有 1 个鸽巢中的鸽子数量多于 1 个,换句话说就是,肯定有 2 只鸽子在 1 个鸽巢内。
- 3.为什么哈希算法无法做到零冲突?
哈希算法长度固定有限的,MD5固定为128位二进制串,能表示最多2^128数据,
应用2:唯一标识 - .如果要搜索一张图片是否存在,我们可以从图片的二进制码串开头取 100 个字节,从中间取 100 个字节,从最后再取 100 个字节,然后将这 300 个字节放到一块,通过哈希算法(比如 MD5),通过哈希算法(比如 MD5),得到一个哈希字符串,用它作为图片的唯一标识。可以减少很多工作量。如果还想继续提高效率,把每个图片的唯一标识,和相应的图片文件在图库中的路径信息,都存储在散列表中。当要查看某个图片是不是在图库中的时候,我们先通过哈希算法对这个图片取唯一标识,然后在散列表中查找是否存在这个唯一标识。如果不存在,图片不在图库中;如果存在,再通过散列表中存储的文件路径,获取到这个已经存在的图片,跟现在要插入的图片做全量的比对,看是否完全一样。如果一样,就说明已经存在;如果不一样,说明两张图片尽管唯一标识相同,但是并不是相同的图片。
应用三:数据校验 - 电驴这样的 BT 下载的原理是基于 P2P 协议的。多个机器上并行下载一个 2GB 的电影,这个电影文件可能会被分割成很多文件块(比如可以分成 100 块,每块大约 20MB)。等所有的文件块都下载完成之后,再组装成一个完整的电影文件就行了。这样容易造成数据串改,可以通过哈希算法,对 100 个文件块分别取哈希值,然后对下载好的文件块逐一求哈希值,然后跟种子文件中保存的哈希值比对。
应用4:散列函数 - 散列函数是设计一个散列表的关键。它直接决定了散列冲突的概率和散列表的性能
哈希算法是如何解决这些分布式问题的。
应用五:负载均衡
- 1).负载均衡算法有很多,比如轮询、随机、加权轮询等。
- 2).如何才能实现一个会话粘滞(session sticky)的负载均衡算法呢?(也就是说,我们需要在同一个客户端上,在一次会话中的所有请求都路由到同一个服务器上。)
维护一张映射关系表,这张表的内容是客户端 IP 地址或者会话 ID 与服务器编号的映射关系。客户端发出的每次请求,都要先在映射表中查找应该路由到的服务器编号,然后再请求编号对应的服务器。这种方法简单直观,但也有几个弊端:- 如果客户端很多,映射表可能很大,比较浪费内存空间
- 客户端下线、上线、服务端扩容、缩容都会导致映射失效,这样维护成本大
如果借助哈希算法,这些问题都可以非常完美地解决。可以通过哈希算法,对客户端 IP 地址或者会话 ID 计算哈希值,将取得的哈希值与服务器列表的大小进行取模运算,最终得到的值就是应该被路由到的服务器编号。 这样,我们就可以把同一个 IP 过来的所有请求,都路由到同一个后端服务器上。
应用六:数据分片
- 1).如何统计“搜索关键词”出现次数
两个难点,第一个是搜索日志很大,没办法放到一台机器的内存中。第二个难点是,如果只用一台机器来处理这么巨大的数据,处理时间会很长。
可以先对数据进行分片,然后采用多台机器处理的方法,来提高处理速度。具体的思路:为了提高处理的速度,用 n 台机器并行处理。我们从搜索记录的日志文件中,依次读出每个搜索关键词,并且通过哈希函数计算哈希值,然后再跟 n 取模,最终得到的值,就是应该被分配到的机器编号。
这样,哈希值相同的搜索关键词就被分配到了同一个机器上。也就是说,同一个搜索关键词会被分配到同一个机器上。每个机器会分别计算关键词出现的次数,最后合并起来就是最终的结果。实际上,这里的处理过程也是 ==MapReduce ==的基本设计思想。 - 2).如何快速判断图片是否在图库中?
给每个图片取唯一标识(或者信息摘要),然后构建散列表。
假设有1亿张图片,单台机器构建散列表是行不通的。可以对数据进行分片,采用多机处理,准备n台机器,每台只维护一部分图片对应的散列表,每次读取一张图片,计算唯一标识然后和n取模,得到机器编号,然后将图片的唯一标识和图片路径发到机器构建的散列表。
给这 1 亿张图片构建散列表大约需要多少台机器。?
散列表中2个信息:哈希值和图片路径。假设通过MD5计算哈希值,长度128比特(16字节),文件路径长度的上限是256字节,可以设计平均长度为152字节,如果使用链表法来解决冲突,还需要存指针(8字节),所以散列表每个数据占用152字节(估算)。
假设每台机器内存2GB,散列表的装载因子0.75,那每台机器大约1000w(2GB*0.75/152)张图片构建散列表,所以一亿张图片构建索引,大约需要10几台机器。
应用七:分布式存储
可以通过哈希算法对数据去哈希值,然后对每个机器个数取模,这个值就是存储的缓冲机器的编号。
扩容:所有数据需要重新计算哈希值,然后搬移到正确的机器上,相当于,缓冲中的数据失效了,这样容易发生雪崩效应,压垮数据库。
- 解决:一致性哈希算法,假设有k个机器,数据范围[0,MAX],将整个范围划分为m个小区间,每个机器负责m/k个小区间,当有新机器加入时,就将某几个小区间数据搬移到新机器中,这样就不用全部重新哈希、搬移数据,也保持了均衡。