海量数据处理问题
Contents
知识点回顾
布隆过滤器
- 流程
- 准备 k 个 hash 函数,每个函数可以把 key 散列成为一个整数
- 初始化一个尽可能长的比特数组,每个比特位初始化为0
- 某个key加入集合时,用k个 hash 函数算出 k 个散列值,并把比特数组中对应的比特位置为1
- 判断某个key是否在集合时,用 k 个hash 函数算出k 个散列值,并查询比特数组中所有的 k 个位置,如果都为 1,认为在集合中。
- 特点
- 如果 key 在集合中,那么一定可以判断出来在;但是如果元素不在集合中,有可能会误判这个元素在集合中。
- 无法删除!(因为并不能确定某个位置是因为删除的元素而被设为1的!)
bitmap
- 利用内存中连续的二进制位,来对大量整形数据做重和查询!
- 不仅方便,还可以去掉重复的整型数,而且做
并集
和交集
也很方便 - 可以解决
用户和标签
的问题,以标签为key,然后将用户存储在bitmap中 - bitmap无法做
非运算
,比如从标签90后
对应的bitmap中可以查询到哪些用户是90后
,但是无法查出哪些不是九零后;解决方法是添加一个全量bitmap,那些在全量位图,且不在90后
位图中的用户都是非90后。 - 可以用 int 类型的数组或者 long 类型的数组来实现 bitmap。
- java中的两个优化的比较好的位图包:
RoaringBitmap
和JavaEWAH
.
|
|
哈希分桶
- 通过哈希函数来对数据进行划分,将不同的划分安排给不同的机器或者分为不同的文件批次处理。
- 哈希分桶的优点在于可以将相同的数据分到同一文件中,也就是说不同的划分间不存在相同的元素!
- MapReduce的本质就是哈希分桶?
需要保持敏感的数据
- $1GB = 2^{10}MB = 2^{20}KB = 2^{30}B = 2^{33}bit$
- $100亿 \approx 2^{34} $, $10亿 \approx 2^{30}$
- 所以 1GB 用位图的话,至少可以存放10亿个数。
常见题目
出现次数最多的IP
给一个超过100G大小的log file,log中存着IP地址,设计算法找到出现次数最多的IP地址.
- 哈希分桶法
- 将100G文件分成1000份,将每个IP地址映射到相应文件中(%1000)
- 在每个文件中分别找出出现频率最高的IP,得到1000个IP
- 再从1000个IP中找出频率最高的IP
只出现一次的数
给定100亿个整数,设计算法找到只出现一次的整数
- 哈希分桶法
- 位图法
- 00 表示没出现过
- 01 表示出现一次
- 10 表示出现过一次以上
两个文件的交集
给两个我呢见,分别有100亿个整数(去重后不超过10亿)
,我们只有1G内存,如何找到两个文件的交集
- 位图法
- 每个数用两位表示,00表示在两个文件中均没出现过,01表示在文件1中出现,10 表示izai文件2中出现,11表示在两个文件中都出现过
- 先遍历文件1中所有整数作出标记,再遍历文件2中的整数。
- 所有被标为 11 的数都是在两个文件中都出现过的数
- 哈希分桶
- 将两个文件分别分为N个小文件,然后小文件之间分别求交集
- 将所有的N个交集合并即可
- 布隆过滤器(近似算法???)
给出若干个文件,统计这些文件中不重复数据的个数。
- 哈希分桶法
- 位图法
如何扩展布隆过滤器使得它支持删除/计数操作?
- 将BloomFilter中的每一位扩展为一个计数器,记录有多少个hash函数映射到这一位;删除的时候,只有当引用计数变为0时,才真正将该位置为0。
- 将BloomFilter中的每一位扩展为一个计数器,每个输入元素都要把对应位置加1,从而支持计数操作。计数个数为所有映射到的位置计数的最小值(???)
有一个词典,包含N个英文单词,现在任意给一个字符串,设计算法找出包含这个字符串的所有英文单词。
- 字典树?
有一百万个数,是在1到一亿当中随机取值,找出这一亿个数中没出现的数
- 位图
100亿个整数如何找到中位数?
- 内存够用:快速选择(快排变形)(时间复杂度是O(N)和构建堆的时间复杂度一样)
- 内存不够用且无重复数据:bitmap
- 内存不够,且有重复数据:哈希分桶?按照每个数的最高8位进行分桶(最多255个桶),这样的话桶之间就有了大小关系,方便找中位数。
Author 段新朋
LastMod 2020-08-05