我在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阶段?
答案 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函数简单地总结所有输入列表中的数字并返回它们。