Hadoop和dumbo的新手,如何正确地对这些操作进行排序?

时间:2010-01-29 09:02:04

标签: hadoop mapreduce

请考虑以下日志文​​件格式:

id        v1        v2        v3
1         15        30        25
2         10        10        20
3         50        30        30

我们将使用dumbo计算Hadoop集群上每个数据行的平均值频率(AVF)。具有m个属性的数据点的AVF定义为:

avf = (1/m)* sum (frequencies of attributes 1..m)

因此对于第一行,avf =(1/3)*(1 + 2 + 1)〜= 1.33。异常值由低AVF识别。

编程问题

我们有以下伪/ python代码:

H = {}  # stores attribute frequencies

map1(_, datapoint): # 
  for attr in datapoint.attrs:
    yield (attr, 1)

reduce1(attr, values):
  H[attr] = sum(values)

map2(_, datapoint):
  sum = 0
  m = len(datapoint.attrs)
  for attr in datapoint.attrs:
    sum += H[attr]        

  yield (1/m)*sum, datapoint

reduce2(avf, datapoints): # identity reducer, only sorts datapoints on avf
  yield avf, datapoints

问题是,我们如何将我们的数据点集插入map1map2,以及在map2中使用中间散列H。如上所述全局定义H似乎违背了MapReduce概念。

1 个答案:

答案 0 :(得分:0)

如果我理解,第一步是计算直方图:

[attr, value] => frequency

其中frequencyvalue列中attr出现的次数。

下一步是采用直方图表和原始数据,为每一行计算AVF,并对它们进行排序。

我将在两次传递中进行:一次map-reduce传递计算直方图,另一次m-r传球使用直方图查找AVF。我也会使用一个单一的常量哈希无罪,因为将直方图值和单元格值放到同一个地方将是一个混乱的野兽。 (例如,让map1以[attr val id]作为键发出[attr val];并让reduce1累积每个键的所有记录,计算它们并发出[id attr val count]。第二遍使用{{1} }作为重新组合然后平均每一行的关键。)


要计算直方图,有助于将中间步骤视为“组”而不是“排序”。方法如下:由于reduce输入按键排序,它会累积给定键的所有记录,并且只要看到不同的键,就会发出计数。悟空,相当于小飞象的红宝石,有一个id,我也认为傻瓜也是如此。 (见下面的工作代码)。

这将离开你

Accumulator

对于下一个传递,我将这些数据加载到哈希表中 - 如果它适合内存,则为简单attr1 val1a frequency attr1 val1b frequency attr2 val2a frequency ... attrN attrNz frequency Hash),如果不适合,则为快速键值存储 - 并像你一样计算每个记录的AVF。


这是使用ruby代码来计算avf;见http://github.com/mrflip/wukong/blob/master/examples/stats/avg_value_frequency.rb

第一次通过

dictionary

第二次通过

module AverageValueFrequency
  # Names for each column's attribute, in order
  ATTR_NAMES = %w[length width height]

  class HistogramMapper < Wukong::Streamer::RecordStreamer
    def process id, *values
      ATTR_NAMES.zip(values).each{|attr, val| yield [attr, val] }
    end
  end

  #
  # For an accumulator, you define a key that is used to group records
  #
  # The Accumulator calls #start! on the first record for that group,
  # then calls #accumulate on all records (including the first).
  # Finally, it calls #finalize to emit a result for the group.
  #
  class HistogramReducer < Wukong::Streamer::AccumulatingReducer
    attr_accessor :count

    # use the attr and val as the key
    def get_key attr, val, *_
      [attr, val]
    end

    # start the sum with 0 for each key
    def start! *_
      self.count = 0
    end
    # ... and count the number of records for this key
    def accumulate *_
      self.count += 1
    end
    # emit [attr, val, count]
    def finalize
      yield [key, count].flatten
    end
  end
end

Wukong::Script.new(AverageValueFrequency::HistogramMapper, AverageValueFrequency::HistogramReducer).run