Понимание Quorum/Vnode (R против PR)

Я проводил некоторые эксперименты, чтобы понять Riak. Вот что интересного нашел:

У меня есть кластер из 2 узлов и тип корзины, в котором n_val из 2

[root@co-riak002 ~]# riak-admin ring-status
================================== Claimant ===================================
Claimant:  '[email protected]'
Status:     up
Ring Ready: true

============================== Ownership Handoff ==============================
No pending changes.

============================== Unreachable Nodes ==============================
All nodes are up and reachable

[root@co-riak002 ~]# riak-admin bucket-type create testBucket '{"props":{"n_val":2}}'
testBucket created
[root@co-riak002 ~]# riak-admin bucket-type activate testBucket                        
testBucket has been activated

И тогда я написал что-то в нем:

[root@co-riak002 ~]# curl -XPUT -d '{"bar":"foo"}' -H "Content-Type: application/json" http://localhost:8098/types/testBucket/buckets/stuff/keys/hello?w=2&returnbody=true
[1] 10890
[root@co-riak002 ~]# 
[1]+  Done                    curl -XPUT -d '{"bar":"foo"}' -H "Content-Type: application/json" http://localhost:8098/types/testBucket/buckets/stuff/keys/hello?w=2

Теперь я могу нормально читать как с r=2, так и с pr=2:

[root@co-riak002 ~]# curl http://localhost:8098/types/testBucket/buckets/stuff/keys/hello?r=2
{"bar":"foo"}
[root@co-riak002 ~]# curl http://localhost:8098/types/testBucket/buckets/stuff/keys/hello?pr=2
{"bar":"foo"}

После того, как я убил один из узлов, r=2 по-прежнему читается нормально, но не pr=2

[root@co-riak002 ~]# riak-admin ring-status
================================== Claimant ===================================
Claimant:  '[email protected]'
Status:     up
Ring Ready: true

============================== Ownership Handoff ==============================
No pending changes.

============================== Unreachable Nodes ==============================
The following nodes are unreachable: ['[email protected]']

С r=2:

[root@co-riak002 ~]# curl http://localhost:8098/types/testBucket/buckets/stuff/keys/hello?r=2
{"bar":"foo"}

С pr=2:

[root@co-riak002 ~]# curl http://localhost:8098/types/testBucket/buckets/stuff/keys/hello?pr=2
PR-value unsatisfied: 1/2

Я в замешательстве: не должно ли число кворума r, используемое в операции чтения, означать количество реплик/физических узлов, которые необходимо согласовать перед возвратом данных? Почему в данном случае не работает? И почему в данном случае работает pr, если оно должно означать количество vnodes?

Я довольно новичок в этом пространстве. Очень признателен за любые указатели.


person saladinxu    schedule 02.10.2015    source источник


Ответы (2)


Вы должны различать "небрежный кворум" и «строгий кворум».

Как вы, наверное, знаете, к каждому ключу применяется хеш-функция для вычисления того, где этот ключ должен находиться в кластере Riak. Все пространство хеш-значений называется «кольцом» и поровну делится между vnodes (виртуальными узлами), которые, в свою очередь, назначаются физическим узлам. Назначение выполняется таким образом, чтобы гарантировать, что соседние vnodes принадлежат отдельным физическим узлам для надежности, хотя это не всегда возможно. Если репликация включена (т. е. n_val > 1), ключ записывается не только на vnode назначения, но и на несколько узлов, которые следуют за vnode в кольце (в большинстве случаев разные физические узлы — см. выше). Теперь это первичные узлы для этого ключа. Однако в случае неаккуратного кворума (например, W = 2), если основной узел недоступен, реплики ключа будут записаны на любой виртуальный узел, потенциально даже на одном и том же физическом узле. Это нормально, потому что они будут переданы «правильным» внодам, как только проблема будет устранена и первичные ноды станут доступны. Если вы не хотите, чтобы реплики записывались на один и тот же физический узел даже временно, или хотите убедиться, что клиент получает самые последние значения, вы можете явно требует всех или хотя бы некоторых операций записи должен быть сделан только для первичных vnodes (PW = 2, "P" означает "основной"). Однако это происходит за счет высокой доступности. Та же логика работает и для чтения.

Надеюсь это поможет.

Я настоятельно рекомендую вам прочитать "Маленькую книгу о Riak". Кроме того, превосходна онлайн-документация.

person vempo    schedule 02.10.2015

не должно ли число кворума r, используемое в операции чтения, означать количество реплик/физических узлов, которые должны быть согласованы перед возвратом данных?

Не совсем. Кворум чтения — это количество виртуальных узлов, которые должны дать приемлемый ответ. Когда вы читаете с одним узлом, остальная часть кластера (в данном случае оставшийся узел) запускает резервные копии для любых отсутствующих vnodes по мере необходимости.

Когда приходит ваш запрос на чтение с r=2, так как один vnode в preflist недоступен, запускается резервный вариант. Естественно, этот запасной вариант пуст при первом запуске, поэтому процесс чтения получает notfound от резервного варианта, а сохраненный объект — от другого.

Хитрость здесь заключается в настройке notfound_ok в свойствах корзины или параметрах запроса. Если оставить значение по умолчанию notfound_ok=true, ответ notfound считается допустимым, поэтому операция соответствует кворуму, ответ с данными превосходит ненайденный, и клиент возвращает объект. Это также запускает восстановление чтения, которое заполнит резервную копию этим объектом, поэтому следующий запрос на получение получит 2 объекта и не найдет ответов.

Если notfound_ok имеет значение false, первый запрос на чтение увидит только 1 действительный ответ и завершится ошибкой, но восстановление чтения все равно произойдет, поэтому следующий запрос r=2 будет успешным, поскольку запасной вариант также содержит данные.

Допустимой тактикой является использование r=1, notfound_ok=false для чтения, чтобы получить высокую доступность и максимально быстрый ответ, сохраняя при этом разумные гарантии того, что вы не получите ложных ответов notfound при сбое узла.

person Joe    schedule 30.10.2015