Hadoop

时间:2015-06-29 07:17:42

标签: hadoop

一堆驾驶汽车产生痕迹(有序位置序列)

car_id  order_id    position
car1    0       (x0,y0)
car1    1       (x1,y1)
car1    2       (x2,y2)
car2    0       (x0,y0)
car2    1       (x1,y1)
car2    2       (x2,y2)
car2    3       (x3,y3)
car2    4       (x4,y4)
car3    0       (x0,y0)

我想计算汽车驱动的距离(路径长度)。

核心是,我需要逐行处理所有记录。如果 前一行的car_id与我需要的当前行相同 计算到前一个位置的距离并将其添加到聚合位置 值。如果前一行的car_id与当前行不同 然后我需要输出前一个car_id的聚合,并初始化 当前car_id的总和为零。

hadoop程序的架构应该如何?是否有可能 以下是:

解决方案(1):

(a)每个映射器计算跟踪的聚合距离(每个物理 块)

(b)每个映射器在跟踪分裂的情况下进一步聚合距离 在多个块和节点之间

评论:此解决方案需要知道我是否在最后一条记录(行) 块。这些信息是否可用?

解决方案(2)

(a)映射器逐行读取数据(不进行计算)并发送 基于car_id的数据到reducer。

(b)Reducer根据order_id对各个car_id的数据进行排序, 计算距离,并汇总它们

评论:由于映射器的懒惰导致的高网络负载

解决方案(3)

(a)实现自定义阅读器以读取将逻辑记录定义为整体 一辆车的痕迹

(b)每个映射器计算距离和聚合

(c)并不真正需要reducer,因为映射器完成了所有操作

注释:由于需要将整个跟踪加载到main中,因此主内存成本较高 记忆(虽然一次只使用两行)。

1 个答案:

答案 0 :(得分:2)

我会选择Solution(2),因为它是最干净的实现和重用。

您当然希望根据car_id AND order_id进行排序,这样您就可以动态计算距离,而无需将它们全部加载到内存中。

您对高网络使用率的关注是有效的,但是,您可以在合并器中预先聚合距离。

看起来如何,让我们采取一些伪代码:

Mapper:

  foreach record:
    emit((car_id, order_id), (x,y))

Combiner:

if(prev_order_id + 1 == order_id): // subsequent measures
     // compute distance and emit that as the last possible order
     emit ((car_id, MAX_VALUE), distance(prev, cur)) 
else:
     // send to the reducer, since it is probably crossing block boundaries
     emit((car_id, order_id), (x,y)) 

减速机有两个主要部分:

  • 计算后续测量的总和,就像组合器
  • 一样
  • 对所有现有金额求和,用order_id = MAX_VALUE
  • 标记

您可以通过网络使用POV获得最佳功能。

从软件POV中,更好地使用Spark-你的逻辑将是五行,而不是三行类文件中的100行。

对于您的其他问题:

  

此解决方案需要知道我是否在最后一条记录(行)   块。这些信息是否可用?

Hadoop只保证在阅读时不会分割记录,很可能你的记录已经触及下面的两个不同的块。找到它的方法基本上是重写输入格式,使这些信息可供映射器使用,甚至更好 - 在分割块时考虑逻辑。