1

我正在做一个将 Riak 与 Ripple 结合使用的项目,但我偶然发现了一个问题。出于某种原因,我在链接结构时会出现重复。当我使用 curl 链接 walk 时,我看不到重复项。

我的基于 curl 的链接步行之间的区别

curl -v http://127.0.0.1:8098/riak/users/2306403e5177b4716da9df93b67300824aa2fd0e/_,projects,0/_,tasks,1

和我的基于 ruby​​ipple/riak-client 的链接步行

      result =   Riak::MapReduce.new(self.robject.bucket.client).
            add(self.robject.bucket,self.key).
            link(Riak::WalkSpec.new({:key => 'projects'})).
            link(Riak::WalkSpec.new({:key => 'tasks', :bucket=>'tasks'})).
            map("function(v){ if(!JSON.parse(v.values[0].data).completed) {return [v];} else { return [];} }", {:keep => true}).run

据我所知,最后是地图。

然而,map/reduce 的结果包含多个重复项。我无法理解为什么。现在我已经决定根据密钥删除重复项,但我希望 riak 结果不包含重复项,因为最后删除重复项似乎是浪费。

我尝试了以下方法:

  • 确保我的波纹对象的链接集中没有重复项
  • 在没有 map reduce 的情况下加载数据,但 link walk 包含重复的键。

任何帮助表示赞赏。

4

1 回答 1

2

您在这里遇到的是 Map/Reduce 查询的一个有趣的副作用/挑战。

M/R 查询没有任何读取仲裁值的概念,它们必须命中每个节点上的每个对象(当然,在输入过滤的限制范围内)。这意味着,当 N > 1 时,查询必须命中每个对象的每个副本

例如,假设 N=3,默认情况下。这意味着,对于每个写入的对象,有 3 个副本,每个副本位于 3 个不同的节点上。当您为对象发出读取时(假设使用默认仲裁值 R=2),协调节点(从您的客户端接收读取请求)联系所有 3 个节点(并可能接收 3 个不同的值,3 个不同的副本对象)。然后,它检查以确保这些副本中至少有 2 个具有相同的值(以满足 R=2 的要求),将商定的值返回给请求的客户端,并丢弃其他副本。因此,在常规操作(读/写,还有链接步行)中,协调节点会为您过滤掉重复项。

Map/Reduce 查询没有那么奢侈。它们实际上并没有与之关联的仲裁值——它们被用来迭代所有节点上的每个(相关)键和对象。而且由于 M/R 代码在每个单独的节点(靠近数据)上运行,而不仅仅是在协调节点上,它们本质上并不能真正过滤掉任何重复项。例如,它们的设计目的之一是更新(或删除)所有节点上的所有对象副本。因此,每个 Map 阶段(在上述情况下)在每个节点上运行,为每个副本返回匹配的“完成”值,并将结果发送回协调节点以返回给客户端。而且由于您的 N>1 很可能,结果集中会有重复项。

现在,您可以通过在 Reduce 阶段编写代码来显式过滤掉重复项,以检查是否已经存在密钥并拒绝重复项,等等。但老实说,如果我处于您的情况,我会过滤掉在客户端的 ruby​​ 中重复,而不是弄乱 reduce 代码。

无论如何,我希望能对这个谜团有所了解。

于 2012-10-21T18:48:58.947 回答