Дублируется при переходе по ссылкам с использованием Ripple

Я работаю над проектом, в котором использую Riak с Ripple, и столкнулся с проблемой. По какой-то причине я получаю дубликаты при переходе по структуре ссылок. Когда я связываю прогулку с помощью curl, я не получаю дубликатов, насколько я вижу.

Разница между моей прогулкой по ссылкам на основе завитков

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

и моя прогулка по ссылке на ruby ​​ripple/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 не содержал дубликатов, поскольку удаление дубликатов в конце кажется пустой тратой времени.

Я пробовал следующее:

  • Убедитесь, что в наборах ссылок моих объектов пульсации нет дубликатов.
  • Загрузка данных без сокращения карты, но ссылка содержит повторяющиеся ключи.

Любая помощь приветствуется.


person Morten    schedule 20.07.2012    source источник


Ответы (1)


Здесь вы сталкиваетесь с интересным побочным эффектом/проблемой запросов Map/Reduce.

Запросы M/R не имеют никакого понятия о значениях кворума чтения, и они обязательно должны обращаться к каждому объекту (конечно, в пределах ограничений входной фильтрации) на каждом узле. Это означает, что когда N > 1, запросы должны обращаться к каждой копии каждого объекта.

Например, скажем, N=3 по умолчанию. Это означает, что для каждого записанного объекта существует 3 копии, по одной на 3 разных узлах. Когда вы выполняете чтение для объекта (скажем, со значением кворума по умолчанию R = 2), координирующий узел (который получил запрос на чтение от вашего клиента) связывается со всеми 3 узлами (и потенциально получает 3 разных значения, 3 разные копии объекта). Затем он проверяет, чтобы по крайней мере 2 из этих копий имели одинаковые значения (чтобы удовлетворить требование R=2), возвращает это согласованное значение запрашивающему клиенту и отбрасывает остальные копии. Таким образом, в обычных операциях (чтение/запись, а также обход ссылок) координирующий узел отфильтровывает для вас дубликаты.

Запросы Map/Reduce не имеют такой роскоши. На самом деле с ними не связаны значения кворума — они созданы для перебора каждого (соответствующего) ключа и объекта на всех узлах. А поскольку код M/R выполняется на каждом отдельном узле (рядом с данными), а не только на координирующем узле, они не могут по сути отфильтровать любые дубликаты. Например, они предназначены для обновления (или удаления) всех копий объектов на всех узлах. Таким образом, каждая фаза карты (в вашем случае выше) выполняется на каждом узле, возвращает совпадающие «завершенные» значения для каждой копии и отправляет результаты обратно на координирующий узел для возврата клиенту. А поскольку весьма вероятно, что ваш N>1, в результирующем наборе будут дубликаты.

Теперь вы, вероятно, можете явно отфильтровать дубликаты, написав код на этапе сокращения, чтобы проверить, присутствует ли уже ключ, и отклонить дубликаты, если они есть, и т. д. Но, честно говоря, если бы я был в вашей ситуации, я бы просто отфильтровал дубликаты в ruby ​​​​на стороне клиента, а не возиться с кодом сокращения.

В любом случае, я надеюсь, что это проливает свет на эту тайну.

person Dmitri Zagidulin    schedule 21.10.2012