海量数据处理

海量数据处理

首先熟悉一下进制转换

计算机最小单位 bit, 也就是 0 和 1
8 个 bit 为一个字节 byte
1024 个 byte 为 1 KB
1024 K 为 1 MB
1024 M 为 1 GB

一. 给定一个大小超过 100G 的文件, 其中存在 IP 地址, 找到其中出现次数最多的 IP 地址(hash文件切分).

解决方案:

(1) 采用Hash函数将 100G 的文件分为若干个小文件

例如: Hash(IP)%1024, 将其分为 1024 个小文件.其中Hash(IP)为每个小文件的编号.

(2) 逐个读取小文件, 对每个小文件建立一个 key 为 IP, value为出现次数的哈希表.将 IP 逐个放入哈希表中, 如果 IP 不存在, 就直接放进去, value 为 1, 如果 IP 已经存在了, 那么 value + 1, 这样统计出每个小文件中的 IP出现的次数.

(3) 到这里就已经知道了每个小文件中出现次数最多的 IP, 然后再用排序算法得到总的出现次数最多的 IP .

到这里, 还有几个问题需要思考.

第一, 切分是否均匀?

  • 小文件的大小是否均匀取决于哈希函数的选择, 在这里 Hash(IP)%1024。设计良好的Hash函数可以减少冲突,使数据均匀的分割到1024个小文件中。但是尽管数据映射到了另外一些不同的位置,但数据还是原来的数据,只是代替和表示这些数据的形式发生了变化而已。

第二, 采用哈希表进行 IP 频率统计时的内存消耗问题.

  • 32位的IP最多可以有2^32种组合方式,也就是说所有IP最多占4G存储空间。我们已经根据IP的hash值将大文件分割为了1024个小文件,也就是说这4G的IP已经被分散到了1024个文件中。那么在Hash函数设计合理的情况下, 每个小文件的哈希表占的内存大小最多为4G/1024 + 存储IP对应的次数所占的空间,所以内存是肯定够用的.

另外, 还需要注意, Hash取模是一种等价映射,换句话说通过映射分割之后相同的元素只会分到同一个小文件中去。相同的IP通过Hash函数映射后只会被分到这1024个小文件中的同一个文件中.

二. 给定100亿个整数, 找到其中只出现一次的整数(位图变形, 用两位来表示次数).

解决方案:

100亿个整数有10G, 超出了我们的内存, 于是想到肯定还是要用到我们的哈希表, 位图等. 一般而言, 位图用一个bit位表示一个数字是否存在, 但是现在, 要表示一个整数出现的次数. 我们可以用两个bit位.

00 代表没出现
01 代表出现一次
10 11 代表出现一次以上

将这100亿个整数对应到这样的位图中, 找到所有01对应的整数, 即为只出现一次的整数.
就算用200亿个bit位, 也只占两个多G的内存.

三. 有两个文件, 分别有100亿个query(查询词, 字符串), 只有1G内存, 找到两个文件的交集(hash文件切分 + 布隆过滤器).

解决方案:

首先还是一样, 100亿太大, 需要先切分, 将两个大文件且分为若干小文件, 然后对每个小文件进行处理, 将每个小文件中的字符串利用布隆过滤器保存, 然后再处理第二个大文件切分成的小文件, 处理时如果发现已经字符串已经存在, 那么就将此字符串放入交集文件中, 最后处理完毕即可得到两个文件的交集.

四. 给上千个文件, 每个文件大小为1K - 100M, 设计算法找到某个词存在在哪些文件中(倒排索引).

解决方案:

首先看两个概念:
正排索引: 由文件的 ID 找到对应的文件内容
倒排索引: 相反, 由文件内容找到对应的文件 ID

1, 首先, 我们对每个文件建立一个布隆过滤器, 将文件中的词对应到布隆过滤器中, 此时我们就得到了上千个布隆过滤器, 每个文件对应一个布隆过滤器.

2, 将要查找的词在一个个布隆过滤器中查找, 如果发现某个布隆过滤器中存在这个单词, 那么就知道了哪个文件存在这个词.

总结

对于海量数据问题, 首先应该想到先切分, 大事化小小事化了.
然后利用哈希表, 位图, 布隆过滤器等, 如果需要还可以借助排序算法等.
核心思想就是分而治之.

你可能感兴趣的:(数据结构与算法)