Как атомные партии гарантируют, что либо все заявления в одной партии будут выполнены, либо нет?
Как работают атомные партии в Кассандре?
Ответ 1
Чтобы понять, как работают партии под капотом, полезно ознакомиться с отдельными этапами пакетного исполнения.
Клиент
Баты поддерживаются с помощью CQL3 или современных клиентских API Cassandra. В каждом случае вы сможете указать список операторов, которые вы хотите выполнить как часть пакета, уровень согласованности, который будет использоваться для всех операторов и необязательную временную метку. Вы сможете выполнять команды INSERT, DELETE и UPDATE. Если вы не хотите указывать временную метку, текущее время автоматически используется и связано с пакетом.
Клиент должен будет обработать два исключения, если пакет не может быть успешно выполнен.
- UnavailableException - недостаточно узлов для выполнения каких-либо обновлений с указанным пакетом CL
- WriteTimeoutException - тайм-аут, либо записывая пакетный журнал, либо применяя какие-либо обновления в пакете. Это можно проверить, прочитав значение
writeType
исключения (либоBATCH_LOG
, либоBATCH
).
Сбой записи во время этапа batchlog будет повторен один раз автоматически с помощью DefaultRetryPolicy
в драйвере Java. Создание пакетного журнала имеет решающее значение для обеспечения того, чтобы пакет всегда выполнялся в случае, если координатор не выполнил промежуточную операцию. Читайте дальше, чтобы узнать, почему.
Координатор
Все партии, отправленные клиентом, будут выполняться координатором так же, как и при любой операции записи. Что отличает от обычных операций записи, так это то, что Cassandra также будет использовать выделенный журнал, который будет содержать все незавершенные партии, выполняемые в настоящее время (называемые batchlog). Этот журнал будет храниться в локальном системном ключевом пространстве и управляться каждым node индивидуально. Каждое исполнение партии начинается с создания записи журнала с полной партией предпочтительно на двух узлах, отличных от координатора. После того, как координатор смог создать пакетный журнал на других узлах, он начнет выполнять фактические операторы в пакете.
Каждый оператор в партии будет записан в реплики, используя CL и временную метку всей партии. Кроме того, в этой области нет ничего особенного в том, что происходит. Можно также называть Writes или бросать WriteTimeoutException, которое может обрабатываться клиентом (см. Выше).
После того, как пакет был выполнен, все созданные журналы могут быть удалены безопасно. Поэтому координатор отправит сообщение удаления пакетного журнала при успешном выполнении на узлы, которые ранее получали пакетный журнал. Это происходит в фоновом режиме и будет оставаться незамеченным в случае его отказа.
Позволяет завершить работу координатора во время пакетного выполнения:
- отправляет пакетный журнал на два других узла (предпочтительно в разных стойках)
- выполнить все инструкции в пакетном режиме
- удаляет пакетный журнал из узлов снова после успешного пакетного выполнения
Узлы реплики batchlog
Как описано выше, пакетный журнал будет реплицироваться через два других узла (если размер кластера позволяет это) перед выполнением партии. Идея заключается в том, что любой из этих узлов сможет собирать ожидающие партии в случае, если координатор опустится до завершения всех операторов в пакете.
Что заставляет думать немного сложнее тот факт, что эти узлы не заметят, что координатор больше не жив. Единственная точка, в которой узлы пакетного журнала будут обновляться с текущим статусом исполнения партии, - это когда координатор выдает сообщения об удалении, указывающие, что пакет был успешно выполнен. В случае, если такое сообщение не поступило, узлы пакетного журнала предполагают, что пакет не был выполнен по некоторым причинам и воспроизвести пакет из журнала.
Воспроизведение периодических записей происходит каждую минуту, т.е. то есть интервал a node будет проверять, есть ли какие-либо ожидающие партии в локальном пакетном журнале, которые не были удалены координатором -возможно убитым-координатором. Чтобы дать координатору некоторое время между созданием пакета и фактическим исполнением, используется фиксированный льготный период (write_request_timeout_in_ms * 2
, по умолчанию 4 секунды). В случае, если пакетный блок все еще существует через 4 секунды, он будет воспроизведен.
Как и при любой операции записи в Cassandra, могут возникать таймауты. В этом случае node вернется к написанию подсказок для тайм-аутов. Когда тайм-аут будет повторяться, записи могут возобновиться с подсказок. По-видимому, это поведение не влияет на то, включен ли hinted_handoff_enabled
или нет. Также имеется значение TTL, связанное с подсказкой, которая приведет к отбрасыванию подсказки после более длительного периода времени (наименьшее GCGraceSeconds
для любого задействованного CF).
Теперь вам может быть интересно, не является ли потенциально опасным повторять пакет на двух узлах одновременно, что может произойти, если мы реплицируем пакетный журнал на двух узлах. Важно помнить, что каждое исполнение партии будет идемпотентным из-за ограниченного вида поддерживаемых операций (обновлений и удалений) и фиксированной метки времени, связанной с пакетом. Конфликтов не будет, даже если оба узла и координатор будут повторять выполнение партии одновременно.
Атомность гарантирует
Давайте вернемся к аспектам атомарности "атомных партий" и рассмотрим, что именно означает атомный (источник):
"(обратите внимание, что в базе данных мы подразумеваем" атомный "смысл, что если какая-либо часть пакет успешен, все это будет. Никакие другие гарантии не подразумеваются; в частности, нет изоляции; другие клиенты смогут прочитайте первые обновленные строки из партии, в то время как другие находятся в прогресс".
Итак, в каком-то смысле мы получаем гарантии "все или ничего". В большинстве случаев координатор просто записывает все утверждения в пакетном виде в кластер. Однако в случае таймаута записи мы должны проверить, в какой момент время ожидания произошло, прочитав значение writeType
. Пакет должен быть записан в пакетный журнал, чтобы быть уверенным, что эти гарантии все еще применяются. Также на этом этапе другие клиенты могут также читать частично выполненные результаты из партии.
Возвращаясь к вопросу, как Кассандра может гарантировать, что все или вообще никакие заявления вообще не будут выполнены? Атомные партии в основном зависят от успешных репликации и идемпотентных утверждений. Это не 100% гарантированное решение, так как в теории могут быть сценарии, которые по-прежнему будут вызывать несоответствия. Но для многих случаев использования в Cassandra это очень полезный инструмент, если вы знаете, как это работает.
Ответ 2
Пакетная документация (doc):
В Cassandra 1.2 и более поздних версиях по умолчанию атомы. В контексте пакетной операции Cassandra атомный означает, что если какая-либо из пакетов будет успешной, все это будет. Чтобы добиться атомарности, Cassandra сначала записывает сериализованную партию в таблицу системных журналов, которая потребляет сериализованную партию в виде данных blob. Когда строки в партии были успешно записаны и сохранены (или намечены), данные в пакете удаляются. Для атомарности есть штраф за производительность. Если вы не хотите брать на себя этот штраф, не позволяйте Кассандре писать в систему пакетного журнала, используя опцию UNLOGGED: BEGIN UNLOGGED BATCH
Ответ 3
Пакеты Кассандры: -
http://docs.datastax.com/en/cql/3.1/cql/cql_reference/batch_r.html
Чтобы добавить к приведенным выше ответам: С Cassandra 2.0 вы можете писать пакетные операторы + LWT. Однако ограничение состоит в том, что все DML файлы должны находиться в одном разделе