代码之家  ›  专栏  ›  技术社区  ›  Theo

MapReduce中的高效集操作

  •  2
  • Theo  · 技术社区  · 14 年前

    我继承了一个MapReduce代码库,它主要计算不同广告在一段时间内看到的唯一用户ID的数量。对我来说,它看起来并不是很有效,我想知道是否有人对如何在MapReduce中尽可能有效地进行这种计算有任何建议或建议。

    我们使用Hadoop,但我将给出一个伪代码示例,没有所有的障碍:

    map(key, value):
      ad_id = .. // extract from value
      user_id = ... // extract from value
      collect(ad_id, user_id)
    
    reduce(ad_id, user_ids):
      uniqe_user_ids = new Set()
      foreach (user_id in user_ids):
        unique_user_ids.add(user_id)
      collect(ad_id, unique_user_ids.size)
    

    它不需要太多的代码,也不难理解,但效率不高。每天我们都会得到更多的数据,因此每天我们都需要从一开始就查看所有的广告印象来计算该广告的唯一用户ID的数量,因此每天它需要更长的时间,并且使用更多的内存。此外,在没有实际分析代码的情况下(不确定如何在Hadoop中这样做),我很确定几乎所有的工作都是在创建一组唯一的ID。它也会消耗大量的内存。

    我已经尝试过非MapReduce解决方案,并获得了更好的性能(但问题是如何以与Hadoop相同的方式扩展它),但感觉应该有一种更好的方法在MapReduce中实现它,就像我拥有的代码一样。这一定是别人解决的一个足够普遍的问题。

    如何使用MapReduce以有效的方式实现唯一ID的计数?

    2 回复  |  直到 14 年前
        1
  •  2
  •   Niels Basjes    14 年前

    问题是,您继承的代码是以“我自己决定唯一的集”的心态编写的,而不是“让我们利用框架为我做这件事”。

    我想改成这样(伪代码):

    map(key, value):
      ad_id = .. // extract from value
      user_id = ... // extract from value
      collect(ad_id & user_id , unused dummy value) 
    
    reduce(ad_id & user_id , unused dummy value):
      output (ad_id , 1); // one unique userid.
    
    map(ad_id , 1): --> identity mapper!
      collect(ad_id , 1 ) 
    
    reduce(ad_id , set of a lot of '1's):
      summarize ;
      output (ad_id , unique_user_ids); 
    
        2
  •  2
  •   piccolbo    14 年前

    Niels的解决方案很好,但是对于一个接近原始代码并且只使用一个map reduce阶段的近似替代方案,只需用一个bloom过滤器替换集合即可。Bloom过滤器中的成员查询有很小的错误概率,但大小估计非常准确。