http://blog.redfox66.com/post/2010/09/24/mass-data-topic-1-start.aspx
第一部分、十五道海量数据处理面试题
1. 给定 a、b 两个文件,各存放 50 亿个 url,每个 url 各占 64 字节,内存限制是 4G,让你
找出 a、b 文件共同的 url?
方案 1:可以估计每个文件安的大小为 50G×64=320G,远远大于内存限制的 4G。所以不可
能将其完全加载到内存中处理。考虑采取分而治之的方法。
1. 遍历文件 a,对每个 url 求取 ,然后根据所取得的值将 url 分别存储
到 1000 个小文件(记为 )中。这样每个小文件的大约为 300M。
2. 遍历文件 b,采取和 a 相同的方式将 url 分别存储到 1000 小文件中(记为
)。这样处理后,所有可能相同的 url 都在对应的小文件(
)中,不对应的小文件不可能有相同的 url。然后我们
只要求出 1000 对小文件中相同的 url 即可。
3. 求每对小文件中相同的 url 时,可以把其中一个小文件的 url 存储到 hash_set 中。然
后遍历另一个小文件的每个 url,看其是否在刚才构建的 hash_set 中,如果是,那么
就是共同的 url,存到文件里面就可以了。
方案 2:如果允许有一定的错误率,可以使用 Bloom lter,4G 内存大概可以表示 340 亿
bit(4G=2^32 大概是 40 亿*8 大概是 340 亿)。将其中一个文件中的 url 使用 Bloom
lter 映射为这 m=340 亿 bit,n=50 亿,如果按出错率 0.01 算, m 应 该>=nlg(1/E)*lge
大概就是 nlg(1/E)1.44 倍(lg 表示以 2 为底的对数),需要的大概是 650 亿个 bit。 现在可用的
是 340 亿,相差并不多,这样可能会使出错率上升些。然后挨个读取另外一个文件的 url,检
查是否与 Bloom lter,如果是,那么该 url 应该是共同的 url(注意会有一定的错误率)。当
hash 函数个数 k=(ln2)*(m/n)时错误率最小
读者反馈@crowgns:
1. hash 后要判断每个文件大小,如果 hash 分的不均衡有文件较大,还应继续 hash 分
文件,换个 hash 算法第二次再分较大的文件,一直分到没有较大的文件为止。这样文
件标号可以用 A1-2 表示(第一次 hash 编号为 1,文件较大所以参加第二次 hash,
编号为 2)
2. 由于 1 存在,第一次 hash 如果有大文件,不能用直接 set 的方法。建议对每个文件都
先用字符串自然顺序排序,然后具有相同 hash 编号的(如都是 1-3,而不能 a 编号是
1,b 编号是 1-1 和 1-2),可以直接从头到尾比较一遍。对于层级不一致的,如
a1,b 有 1-1,1-2-1,1-2-2,层级浅的要和层级深的每个文件都比较一次,才能确
认每个相同的 uri。