Riak MapReduce - 地图工作,减少接收非常小的结果子集

时间:2014-05-15 15:50:33

标签: mapreduce riak

我在Ubuntu 12.10(最新版)上使用Riak 2.0.0b1。这是一个开发人员框,所以我只有一个Riak实例 - 没有集群等。

我已经将大约100k个JSON文档(每个大约300个字节)放入一个存储桶中,现在我正在尝试mapreduce。数据是随机的,我还在其中一个键上得到了2i索引,基本上将数据集划分为10个几乎偶数~10k文档的部分。

此查询按预期工作:

curl -XPOST -d'{
  "inputs": {"bucket": "bucket", "index": "idx_bin", "key": "10"},
  "query": [
    {
      "map": {
        "language": "javascript",
        "source": "Riak.mapValuesJson"
      }
    }
  ]
}' http://localhost:8080/mapred -H 'Content-Type: application/json' | python -m json.tool | egrep '^ {4}\{' | wc -l

9974

获得约10k的结果。现在,如果我想在reduce步骤中做一些事情,我会得到一个没有意义的答案:

curl -XPOST -d'{
  "inputs": {"bucket": "bucket", "index": "idx_bin", "key": "10"},
  "query": [
    {
      "map": {
        "language": "javascript",
        "source": "Riak.mapValuesJson"
      }
    },
    {
      "reduce": {
         "language": "javascript",
        "source": "function(o) { return [o.length] }"
      }
    }
  ]
}' http://localhost:8080/mapred -H 'Content-Type: application/json' | python -m json.tool

[
    15
]

我想在这里看到一个错误,如果我达到一些(未)记录的限制或完整的对象列表请,而不是15。(这个数字在运行之间有所不同;有时会有更多。)我去了到配置并完成这个:

javascript.map_pool_size = 64
javascript.reduce_pool_size = 64
javascript.maximum_stack_size = 32MB
javascript.maximum_heap_size = 64MB

根本没有帮助。

发生了什么以及如何让所有对象进入reduce阶段?

1 个答案:

答案 0 :(得分:1)

多次调用reduce函数。 map函数将在集群中大约1/3的vnode上运行(在具有ring_size 64的集群中为22次),每次从map函数获得结果时都会调用reduce函数,其第一个参数是一个列表,包含上一次reduce函数运行的结果和map函数的结果。在您的情况下,您计算从第一个vnode返回的值,然后将其作为第二个vnode结果中包含的值传递,并且仅计为单个值。

您需要做的是让reduce函数返回一个很容易与其他值区分开的值/对象,例如

function(o) {
  var prevCount = 0;
  var countObjects = 0;
  for each (e in o) {
    if (typeof e === 'object' && typeof e.reduce_running_total === 'number') {
       prevCount += e.reduce_running_total;
       countObjects += 1;
    }
  }
  return([{"reduce_running_total":o.length + prevCount - countObjects}]);
}

或者,您可以节省一些网络带宽,而不是使地图阶段返回所有对象,让map函数为找到的每个键返回文字[1],然后reduce函数简单地总结所有输入列表中的数字并返回它们。