|
1 | 1 | ## 场景
|
| 2 | + |
2 | 3 | 假设你现在要处理这样一个问题,你有一个网站并且拥有`很多`访客,每当有用户访问时,你想知道这个ip是不是第一次访问你的网站。
|
3 | 4 |
|
4 | 5 | ### hashtable 可以么
|
5 |
| -一个显而易见的答案是将所有的 IP 用hashtable存起来,每次访问都去 hashtable 中取,然后判断即可。但是题目说了网站有`很多`访客, |
6 |
| -假如有10亿个用户访问过,假设 IP 是 IPV4, 那么每个 IP 的长度是 4 byte,那么你一共需要4 * 1000000000 = 4000000000Bytes = 4G , 如果是判断URL黑名单,由于每个 UR L会更长,那么需要的空间可能会远远大于你的期望。 |
| 6 | + |
| 7 | +一个显而易见的答案是将所有的 IP 用 hashtable 存起来,每次访问都去 hashtable 中取,然后判断即可。但是题目说了网站有`很多`访客, |
| 8 | +假如有10亿个用户访问过,假设 IP 是 IPV4, 那么每个 IP 的长度是 4 byte,那么你一共需要4 * 1000000000 = 4000000000Bytes = 4G 。 |
| 9 | + |
| 10 | +如果是判断 URL 黑名单,由于每个 URL 会更长(可能远大于上面 IPV4 地址的 4 byte),那么需要的空间可能会远远大于你的期望。 |
7 | 11 |
|
8 | 12 | ### bit
|
9 |
| -另一个稍微难想到的解法是bit, 我们知道bit有0和1两种状态,那么用来表示存在,不存在再合适不过了。 |
10 | 13 |
|
11 |
| -加入有10亿个ip,我们就可以用10亿个bit来存储,那么你一共需要 1 * 1000000000 = (4000000000 / 8) Bytes = 128M, 变为原来的1/32, |
12 |
| -如果是存储URL这种更长的字符串,效率会更高。 |
| 14 | +另一个稍微难想到的解法是bit, 我们知道bit有 0 和 1 两种状态,那么用来表示**存在**与**不存在**再合适不过了。 |
| 15 | + |
| 16 | +假如有 10 亿个 IP,就可以用 10 亿个 bit 来存储,那么你一共需要 1 * 1000000000 = (4000000000 / 8) Bytes = 128M, 变为原来的1/32, 如果是存储URL这种更长的字符串,效率会更高。 问题是,我们怎么把 IPV4 和 bit 的位置关联上呢? |
13 | 17 |
|
14 |
| -基于这种想法,我们只需要两个操作,set(ip) 和 has(ip) |
| 18 | +比如`192.168.1.1` 应该是用第几位表示,`10.18.1.1` 应该是用第几位表示呢? 答案是使用哈希函数。 |
| 19 | + |
| 20 | +基于这种想法,我们只需要两个操作,set(ip) 和 has(ip),以及一个内置函数 hash(ip) 用于将 IP 映射到 bit 表。 |
15 | 21 |
|
16 | 22 | 这样做有两个非常致命的缺点:
|
17 | 23 |
|
18 | 24 | 1. 当样本分布极度不均匀的时候,会造成很大空间上的浪费
|
19 | 25 |
|
20 |
| -> 我们可以通过散列函数来解决 |
| 26 | +> 我们可以通过优化散列函数来解决 |
21 | 27 |
|
22 | 28 | 2. 当元素不是整型(比如URL)的时候,BitSet就不适用了
|
23 | 29 |
|
24 | 30 | > 我们还是可以使用散列函数来解决, 甚至可以多hash几次
|
25 | 31 |
|
26 | 32 | ### 布隆过滤器
|
27 | 33 |
|
28 |
| -布隆过滤器其实就是`bit + 多个散列函数`, 如果经过多次散列的值再bit上都为1,那么可能存在(可能有冲突)。 如果 |
29 |
| -有一个不为1,那么一定不存在(一个值经过散列函数得到的值一定是唯一的),这也是布隆过滤器的一个重要特点。 |
| 34 | +布隆过滤器其实就是`bit + 多个散列函数`。多次 hash(ip) 会生成多个索引。 如果经过多次散列的值在 bit 上都为 1,那么认为其**可能存在**(因为有冲突的可能)。 如果有一个不为1,那么**一定不存在**(一个值经过散列函数得到的值一定是唯一的),这也是布隆过滤器的一个重要特点。 |
30 | 35 |
|
31 | 36 | 
|
32 | 37 |
|
| 38 | +也就是说布隆过滤器回答了:**可能存在** 和 **一定不存在** 的问题。 |
| 39 | + |
| 40 | +由于没有 hashtable 的100% 可靠性,因此这本质上是一种**可靠性换取空间的做法**。 |
| 41 | + |
33 | 42 | ### 布隆过滤器的应用
|
34 | 43 |
|
35 | 44 | 1. 网络爬虫
|
| 45 | + |
36 | 46 | 判断某个URL是否已经被爬取过
|
37 | 47 |
|
38 | 48 | 2. K-V数据库 判断某个key是否存在
|
39 | 49 |
|
40 |
| -比如Hbase的每个Region中都包含一个BloomFilter,用于在查询时快速判断某个key在该region中是否存在。 |
| 50 | +比如 Hbase 的每个 Region 中都包含一个 BloomFilter,用于在查询时快速判断某个 key 在该 region 中是否存在。 |
41 | 51 |
|
42 | 52 | 3. 钓鱼网站识别
|
43 | 53 |
|
|
0 commit comments