Spec-Zone.ru › RethinkDB javascript

Гарантии согласованности

  • Настройки
  • Гарантии линеаризуемости и атомарности
  • Гарантии доступности
  • Балансировка безопасности и производительности
  • Примечания

Три настройки управляют согласованностью и долговечностью в RethinkDB: подтверждения записи и долговечность по таблице, а также режим чтения запроса.

Настройки

  • Подтверждения записи настраиваются по таблице с помощью настройки write_acks, используя команду config или запись в системную таблицу table_config системную таблицу. По умолчанию установлено значение majority, что означает, что записи будут подтверждаться, когда большинство (голосовых) реплик подтвердят свои записи. Другой возможный вариант — single, что означает, что записи будут подтверждаться, когда подтвердит их одна реплика.
  • Долговечность настраивается по таблице с помощью настройки durability, опять же, используя либо reconfigure, либо запись в системную таблицу table_config. В режиме долговечности hard, записи сохраняются на диск до отправки подтверждения; в режиме soft, записи подтверждаются немедленно после хранения в памяти. Режим soft быстрее, но немного менее устойчив к сбоям. По умолчанию установлено значение hard.
  • Режим чтения настраивается по запросу с помощью необязательного аргумента read_mode (или readMode), для table. Он имеет три возможных значения:
    • single возвращает значения, которые находятся в памяти (но необязательно записаны на диск) на первичной реплике. Это значение по умолчанию.
    • majority будет возвращать только значения, которые безопасно сохранены на диске на большинстве реплик. Это требует отправки сообщения каждой реплике при каждом чтении, поэтому это самый медленный, но наиболее согласованный режим.
    • outdated возвращает значения, которые находятся в памяти на произвольной реплике. Это самый быстрый, но наименее согласованный режим.

Обратите внимание, что changefeeds игнорирует флаг read_mode, и всегда ведет себя так, как будто он установлен в single.

Линеаризуемость и атомарность гарантий

При следующих настройках RethinkDB гарантирует линеаризуемость отдельных атомарных операций над отдельными документами:

  • write_acks: majority
  • durability: hard
  • read_mode: majority

Это означает, что каждое чтение увидит все предыдущие успешные записи, и ни одно чтение никогда не увидит окончательно проваленную запись. (См. примечание о окончательно проваленных и неопределенных записях ниже.)

Гарантия линеаризации относится к атомарным операциям, а не к запросам. Один запрос RethinkDB необязательно выполняется как одна атомарная операция. Возможно, что запрос:

r.table("foo").get("bar").eq(r.table("foo").get("bar")).run(conn, callback);

может вернуть false! Каждая отдельная операция get является атомарной, но запрос в целом — нет. Чтобы прочитать и изменить документ в одной атомарной операции, используйте команды update или replace.

r.table("foo").get(id).update({hits: r.row("hits") + 1}).run(conn, callback);

Это также можно использовать для реализации регистра check-and-set. Следующий запрос атомарно проверит, равно ли поле check значению old_value, и изменит его на new_value, если это так:

r.table("foo").get(register_id).update({
    check: r.branch(r.row("check").eq(old_value), new_value, r.row("check"))
}).run(conn, callback);

Операции RethinkDB никогда не бывают атомарными для нескольких ключей. По этой причине RethinkDB нельзя считать базой данных ACID.

В настоящее время операции filter, get_all и аналогичные операции выполняются как отдельные операции от операций изменения update и других операций мутации. Поэтому следующее не является правильной реализацией регистра check-and-set, так как операции filter и update не будут выполняться в одной атомарной операции:

r.table("foo").filter({
    id: register_id, foo: old_val
}).update({foo: new_val}).run(conn, callback);

table.filter({id: register_id, foo: old_val}).update({foo: new_val})

Это поведение может измениться в будущем. См. Github issue #3992 для отслеживания обсуждения.

Гарантии доступности

За исключением коротких периодов, таблица остаётся полностью доступной, пока более половины голосовых реплик для каждого фрагмента и для всей таблицы в целом остаются доступными. Если потеряно половина или более голосовых реплик для фрагмента, операции чтения или записи для этого фрагмента завершатся ошибкой.

Переконфигурация таблицы (изменение количества фрагментов, балансировка и т. д.) приводит к кратковременной потере доступности в различные моменты переконфигурации.

Если первичная реплика потеряна, но более половины голосовых реплик по-прежнему доступны, произвольная голосовая реплика будет избрана в качестве первичной. Новая первичная реплика появится в table_status, но поле primary_replica в table_config не изменится. Если старая первичная реплика когда-либо станет доступна снова, система вернётся к исходному состоянию. При изменении первичной реплики произойдёт кратковременная потеря доступности.

Если потеряна половина или более голосовых реплик фрагмента, единственный способ восстановить доступность — запустить reconfigure с параметром emergency_repair. Для получения дополнительной информации см. документацию по reconfigure.

Чтения, выполняемые в режиме single могут быть успешными, даже если таблица недоступна, но это не гарантируется. Чтения, выполняемые в режиме outdated будут успешными, если доступна хотя бы одна реплика для каждого из соответствующих фрагментов.

Голосовые и не голосовые? По умолчанию все реплики являются «голосовыми», что просто означает, что они учитываются в любой операции, требующей наличия большинства реплик. Однако скорость, с которой реплики «голосуют», зависит от задержки сети; если у вас есть удалённый дата-центр с большей задержкой, вы можете установить его реплики как «неголосовые» для повышения производительности, но при этом гарантированная доступность в этом дата-центре уменьшится. Вы можете установить реплику как «неголосовую», изменив её конфигурацию таблицы с помощью reconfigure.

Балансировка безопасности и производительности

По умолчанию RethinkDB prioritizes safety over performance, за исключением одного случая: read_mode по умолчанию single, а не majority. Режим чтения majority требует отправки запроса ко всем репликам и ожидания ответа большинства, что значительно снижает производительность.

В нормальной работе режим чтения single даёт такие же результаты, как режим чтения majority, но может возвращать устаревшие результаты в случае сбоя сети или сбоя. Также возможно, что чтение, выполненное в режиме single , может вернуть результаты незавершенной записи, которая позже будет отменена.

То же самое относится к режиму записи single и режиму долговечности soft. В нормальной работе эти режимы дают такие же результаты, как majority и hard, но в случае сбоя сети или сервера недавние операции записи, выполненные с помощью этих режимов, могут быть потеряны.

Обратите внимание, что write_acks и durability фактически не влияют на выполнение записи; они только влияют на то, когда подтверждение отправляется клиенту.

Чтения, выполненные в режиме "outdated" , вернут устаревшие данные даже при нормальной работе, но данные, как правило, будут устаревшими менее чем на секунду. В случае сбоя сети или сервера данные могут быть намного более устаревшими. Преимущество выполнения чтений в режиме "outdated" заключается в том, что задержка и пропускная способность часто лучше, чем в режиме "single", помимо различий в доступности, описанных в предыдущем разделе.

Примечания

Использование опции emergency_repair в таблице аннулирует все гарантии.

Существуют два способа, которыми операция записи может завершиться сбоем. Если запись завершается сбоем окончательно, ни одно чтение никогда не увидит её, даже в более слабых режимах чтения. Если запись завершается сбоем неопределённо, чтения, выполненные в режимах single или outdated , могут увидеть её, но когда проблема, вызвавшая сбой сети или сервера, будет решена, запись может или не может быть отменена. Как правило, записи завершаются неопределённо, если они выполнялись в тот момент, когда впервые произошла проблема с сетью или сервером. Оба эти сбоя приведут к ошибкам, и вы можете проверить сообщение об ошибке, чтобы узнать, был ли сбой окончательным или неопределённым.

Автоматический failover RethinkDB имеет ограничения в случаях сбоев с непереходной связностью, т. е. сервер A может связаться с B, а B может связаться с C, но A не может связаться с C. Для получения дополнительной информации см. документацию по Failover.

© RethinkDB contributors
Licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License.
https://rethinkdb.com/docs/consistency/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API