- Хаосные реплицированные таблицы
- Создание хаосной реплицированной динтаблицы
- Работа с хаосной реплицированной динтаблицей
- Добавление новой реплики
- Необходимое число очередей репликации
- Хаос-целлы
- Прогресс репликации
- Карточка репликации
- Переключение режимов реплик
- Автоматическое переключение режимов реплик
- Атрибуты
Хаосные реплицированные таблицы
Хаосные реплицированные динтаблицы в YTsaurus функционально похожи на реплицированные, но основанны на новом протоколе хаосной репликации. Как и обычные реплицированные, они позволяют иметь несколько копий одной и той же таблицы на разных кластерах, обновляемых в реальном времени, причём копии строго консистентны друг с другом и вместе представляют постоянно доступную динамическую таблицу с полной поддержкой транзакций.
По сравнению с обычными реплицированными, хаосные динтаблицы всё время доступны и на чтение, и на запись - это достигается благодаря протоколу хаосной репликации. Основные отличия хаосной репликации такие:
- На каждом кластере должна быть реплика специального вида - очередь репликации.
- Репликация делается по pull-модели, при этом в качестве источника может быть использована любая доступная очередь, содержащая достаточно свежие данные.
- Данные о состоянии реплик хранятся на отдельных кластерах хаосных метаданных в виде карточки репликации
- Для совместимости с обычными реплицированными используется объект
chaos_replicated_table, который, в отличие отreplicated_table, не содержит никаих данных - это просто прокси-узел к хаосным метаданным и репликам. - Хаосные метаданные располагаются в специальном chaos cell bundle.
chaos_replicated_tableподвязывается к хаосному бандлу.
Хаосные реплицированные динтаблицы могут быть как сортированные, так и упорядоченные. Для упорядоченных динтаблиц каждая реплика используется и как реплика с данными и как очередь репликации для других реплик. Для сортированных динтаблиц реплики с даными и реплики с очередью репликации - принципиально разные, и имеют разные типы.
Создание хаосной реплицированной динтаблицы
В этой секции описывается последовательность шагов, как быстро создать хаосную реплицированную динтаблицу, и какие основные интерфейсные отличия от реплицированной. Для более глубокого понимания того, как работают хаосные динтаблицы, стоит прочитать следующие секции.
- Создание хаосной динтаблицы. Сперва нужно создать объект вида
chaos_replicated_table. Несмотря на то, что это просто прокси, это удобная точка входа, которая сильно упрощает работу с хаосными реплицированными таблицами. (К тому же,chaos_replicated_tableдля всех операций требует только read-доступа к кластеру, на котором располагается, и продолжет быть доступной во время обновления, если обновление проводится в режиме с доступом чтений.)
При создании нужно обязательно указать атрибут chaos_cell_bundle - к какому хаосному бандлу будет привязана таблица и в каком будут жить все необходимые метаданные. Также желательно указать атрибут schema - при его наличии можно будет указывать chaos_replicated_tableя прямо для селектов и лукапов.
yt create chaos_replicated_table //path/to/replicated_table --attr '{
chaos_cell_bundle=...;
schema=[...];
}'
- Создание реплики с данными. Это реплика, в которой хранятся сами данные в привычном формате (если отвязать реплику от репликации, это будет обычная динтаблица, со всеми данными). Для того чтобы таблица-реплика получилась привязанной к
chaos_replicated_table, сперва нужно создать объект видаchaos_table_replica- часть метаданных, опиысывающих связь. Он полностью аналогиченtable_replicaдля реплицированных динтаблиц. При созданииchaos_table_replicaважно указать к какойchaos_replicated_tableона относится, а также какую таблицу-реплику описывает. Обратите внимание на"content_type" = "data"- это указывает на то, что реплика содержит данные и не может быть использована в качестве источника репликации. Если вы хотите создать реплику упорядоченной динтаблицы нужно указать"content_type" = "queue"- тогда реплика будет работать и как реплика с данными, и как источник для репликации.
$ yt create chaos_table_replica --attr '
{
"table_path" = "//path/to/replicated_table";
"cluster_name" = replica_cluster;
"replica_path" = "//path/to/data";
"content_type" = "data";
"mode" = "sync";
"enabled" = %true;
}'
1-2-3-4
Операция создания chaos_table_replica вернёт идентификатор свежесозданной реплики. Его нужно использвать в качестве upstream_replica_id для таблицы-реплики. upstream_replica_id можно как указать при создании таблицы, так и поменять с помощью alter_table.
$ yt --proxy replica_cluster create table //path/to/data --attr '{dynamic=%true; schema=[...]; upstream_replica_id="1-2-3-4"}'
# Или
$ yt --proxy replica_cluster alter-table --upstream-replica-id 1-2-3-4 //path/to/data
- Создать реплику с очередью репликации (только для сортированных хаосных динтаблиц). Этот шаг аналогичен созданию реплики с данными, но требует указать
"content_type" = "queue"при созданииchaos_table_replica, а также использовать типreplicated_log_table.
При создании очереди можно указать pivot_keys - тогда очередь будет разбитой на таблеты. Шардировать можно только один раз при создании. Если в будущем потребуется больше шардов, это можно сделать только создав новую очередь репликации, и удалив старую (хаос позволяет это сделать на живой таблице).
$ yt create chaos_table_replica --attr '
{
"table_path" = "//path/to/replicated_table";
"cluster_name" = replica_cluster;
"replica_path" = "//path/to/replication_queue";
"content_type" = "queue";
"mode" = "sync";
"enabled" = %true;
}'
5-6-7-8
$ yt --proxy zeno create replication_log_table //path/to/replication_queue --attr '{dynamic=%true; schema=[...]; upstream_replica_id="5-6-7-8"}'
Работа с хаосной реплицированной динтаблицей
Проще всего всегда использовать chaos_replicated_table - и для записи, и для чтения. Так будут сразу обеспечены все транзакционные гарантии.
Тем не менее, хаос поддерживает и доступ ко всей хаосной реплицированной таблице через любую реплику:
- при записи как в
chaos_replicated_table, так и в любую реплику, запись будет применяться сразу ко всей хаосной реплицированной таблице в соответствии с её текущим состоянием (например, при формальной записи в асинхронную реплику данные в этой транзакции будут на самом деле записаны только в синхронные реплики). - чтение из реплики читает данные только из неё самой (осторожно, в будущем это поведение может поменяться).
- чтение из реплики, с указанием опции
replica_consistency=syncбудет читать из синхронной реплики (или достаточно свежей асинхронной, и не обязательно той, которая была указана в операции). - чтение из
chaos_replicated_tableделается всегда в режимеreplica_consistency=sync, т.е. только из достаточно свежей реплики.
Добавление новой реплики
При долгой работе с таблицей случается момент, когда нужно добавить новую реплику: например, переехать на новый кластер, или просто пересоздать старую реплику. Добавление новой реплики делается с помощью знакомой команды chaos_table_replica, но, если выполнить её на таблице, которая уже давно работает, то скорее всего это приведёт к проблеме: репликация в свежесозданную реплику не пойдёт, к тому же в очередях начнут накапливаться данные, что может привести к проблемам во всём бандле. Так происходит потому, что история репликации чистится, и изначальных данных уже давно нет.
Чтобы добавить новую реплику и не требовать репликации данных за всё время существования, есть несколько способов:
- Создать реплику с указанием
catchup=%false. В таком случае будет считаться что история реплике не нужна и данные польются начиная с некоторого таймстемпа уже после создания. В случае реплики с данными в ней будут только новые записи, и такая реплика будет отличаться от других по данным. Но для добавления новой очереди репликации режимcatchup=%falseвыглядит разумным вариантом по умолчанию, ведь обычно в очередях репликации хранится только малая часть свежих данных, ещё не доехавших до остальных реплик. - Указать при создании реплики
replication_progress. Тогда репликация в реплику продолжится с указанного прогресса. Этот способ позволяет явно проконтролировать момент, с которого польются реплицированные данные. Подробнее о прогрессе репликации будет ниже. - Указать прогресс на таблице-реплике. Аналогично предыдущему, репликация продолжится начиная с указанного прогресса. Это наиболее предпочтительный способ, поскольку прогресс явно хранится вместе с таблицей в виде атрибута. Важно: прогресс на таблице должен быть больше или равен тому, который указан в
chaos_table_replica. Если прогресс на таблице вдруг станет меньше, репликация остановится.
При добавлении новой реплики с явно указанным прогрессом нужно быть уверенным, что текущие очереди репликации содержат необходимые данные. Обычно такого можно достичь с помощью отмонтирования уже существующей реплики с данными - тогда невозможность реплицировать в неё будет заставлять данные накапливаться в очередях.
Копирование существующей реплики
Рассмотрим подробнее частый сценарий: копирование существующей реплики на новый кластер. Новая реплика должна быть полностью идеентична старой и в неё должна начаться репликация. Распишем последовательность шагов, которые нужно сделать:
- Отмонтировать реплику-донор (стоит предварительно перевести её в асинхронный режим). Это нужно для фиксации прогресса репликации.
- Прочитать прогресс из атрибута
@replication_progressи запомнить его. - Создать новую реплику командой
create chaos_table_replica. Это позволит сохранить данные в очередях репликации до того момента, когда реплика начнет работать. Получившийся идентификатор нужно запомнить для последующей подстановки вupstream_replica_id - Скопировать реплику-донор на новый кластер. Это потенциально долгий шаг, его можно оптимизировать: сперва скопировать реплику локально (командоый
yt copy) - это быстро создаст необходимый снапшот данных, после чего копировать его в фоне и сразу переходить к следующему шагу - Примонтировать реплику-донор. В неё пойдёт репликация, но данные в копии уже не поменяются.
- После окончания копирования установить на новой таблице правильный
replication_progressиupstream_replica_id. - Примонтировать новую реплику. Она должна обновить прогресс в карточке репликации на тот, который был ей выставлен, и запустить репликацию.
Необходимое число очередей репликации
Несмотря на то, что протокол хаосной репликации будет работать при любом числе очередей репликации, в сценарии, когда очередеди разнесены по разным датацентрам, предполагается что очередей как минимум три, и в любой момент времени обязательно должны быть две синхронные.
Если предположить сценарий, в котоорм, пусть на короткое время, запись идёт только в одну синхронную очередь, то репликация сломается при внезапной недоступности этой очереди. Такая конфигурация может быть допустимой, только если очередь будет находиться на кросс-датацентровом кластере.
Хаос-целлы
Отказоустойчивость и постоянная доступность хаоса достигается благодаря отдельному слою хаосных метаданных, которые располагаются на хаос-целлах. Хаос-целлы располагаюся на кросс-дц кластерах, к томуже информация может быть смигрирована между хаос-целлами при необходимости даунтайма части хаос-целлов (напрмер, при обновлениях).
Как и таблет-целлы, хаос-целлы объединяются в бандлы (chaos cell bundle). Бандлы нужны для изоляции и учёта ресурсов между разными потребителями. В отличие от tablet cell bundle, целлы хаосного бандла известны сразу всем кластерам. Можно прямо в UI посмотреть список всех хаос-целлов, в том числе и тех, которые физически располагаются на других кластерах.
Для того, чтобы воспользоваться хаосной репликацией, у вас должен быть chaos cell bundle, которым разрешено пользоваться.
Прогресс репликации
При репликации важно понимать какие именно данные были переданы, а какие нет. В транзакционной модели данных динтаблицах YTsaurus обновления однозначно идентифицируются парой (ключ, таймстапм), причём таймстампы строго возрастают. Получается, что:
- По каждому ключу обновления должны быть строго упорядочены по таймстампам.
- По разным ключам порядка может не быть.
Прогресс репликации представляет собой ступенчатый график в пространстве ключей и времени: для каждого диапазона ключей указывается timestamp, до которого этот диапазон дореплицировался (включительно). Это позволяет делать запросы на чтение данных отдельно по диапазонам, причём диапазоны не обязательно должны совпадать с ключами шардирования очередей репликации.
Прогресс представляется в виде последовательности сегментов (lower key, timestamp). Последний ключ задаётся отдельным полем upper_key. Прогресс на таблице можно посмотреть через атрибут @replication_progress - рекомендуется это делать только на отмонтированных таблицах, потому что на примонтированных реальный прогресс может оказаться сильно больше. Поменять прогресс можно с помощью команды alter-table. Последнее может быть полезно, если требуется подключить новую реплику с подготовленными данными к существующей таблице.
Важно понимать, что у примонтированной реплики достоверный прогресс знает только таблетная нода для тех таблетов, которые на ней. Ни на мастере, который отвечает на чтение атрибута @replication_progress, ни на хаос-целле, с которого можно достать карточку репликации (о ней - ниже) информация о прогресее недостоверна, и by design, отстающая.
Карточка репликации
Карточка репликации - основные метаданыне для протокола хаосной репликации. В обычных пользовательских сценариях она не используется в явном виде, но может быть полезным при расследовании проблем.
В карточке содержится информация о репликах: какие кластера и таблицы, какие режимы реплик, а также, возможно, отставший, прогресс.
В карточке репликации есть дополнительно поля history и era. Эра - счётчик эпох хаосной репликации. Каждое изменение совокупного состояния реплик - добавление или удаление, а также смена режима - приводит к переходу на новую эру, В поле history указаны эпохи, в которых менялось состояние этой конкретной реплики. Поле history периодически подчищается в фоне.
Для того чтобы узнать уникальный идентификатор карточки, нужно прочитать атрибут @replication_card_id у реплицированной динтаблицы или у реплики. Чтобы получить саму карточку, достаточно сделать get по идентификатору (не забудтье добавить #).
Переключение режимов реплик
Переключение режимов реплик делается командой alter-table-replica, точно также как и для обычных упорядоченных. Можно как выключить-включить реплику (с помощью флагов enable/disable), так и поменять режим с синхронного на асинхронный и обратно - с помощью опции mode.
При смене режима возникает короткий даунтайм - это нужно чтобы подождать когда завершатся транзакции, пишущие в старые синхронные реплики и начать новые, которые будут писать уже в новые синхронные, это нужно для того чтобы репликация знала какие данные точно сохранены на синхронных реплик. В реплицированных динтаблицах существует похожий барьер, и на практике, можно добиться того, чтобы даунтайм был в пределах единиц секунд (как для реплицированных, так и для хаосных таблиц).
Автоматическое переключение режимов реплик
Как и обычные реплицированные, хаосные реплицированные таблицы поддерживают автоматическое переключение реплик.
Настройка автоматического переключения требует задать ReplicatedTableOptions для карточки репликации, и указать на репликах, для каких режим может быть изменён автоматически.
При создании chaos_replicated_table можно указать атрибут replicated_table_options, в который передать ReplicatedTableOptions. Подробное описание ReplicatedTableOptions см в соответствующем разделе.
Если хаосная реплицированная динтаблица уже создана, то поменять опции можно с помощью команды alter_replication_card (ей нужно передать идентификатор карточки репликации, который указан в атрибуте @replication_card_id хаосной реплицированной таблицы и реплик):
yt.alter_replication_card(replication_card_id, replicated_table_options=replicated_table_options)
yt.alter_replication_card(replication_card_id, enable_replicated_table_tracker=True)
Для того, чтобы управлять автоматическим переключением отдельных реплик, на каждой реплике есть флаг enable_replicated_table_tracker, который можно либо указать при создании реплики, либо поменять для уже существующей реплики с помощью команды alter-table-replica:
$ yt alter-table-replica [--enable-replicated-table-tracker | --disable-replicated-table-tracker] replica_id
Атрибуты
Атрибуты chaos_table_replica
| Имя | Тип | Значение |
|---|---|---|
| table_path | string | путь к chaos_replicated_table |
| replication_card_id | TReplicationCardId | явное указание карточки репликации (можно не указывать, если указан table_path) |
| cluster_name | string | крастер с таблице-репликой |
| replica_path | string | путь до таблицы-реплики |
| content_type | ETableReplicaContentType | data или queue в зависимости от того это данные или очередь репликации. Для реплик упорядоченных динтаблиц нужно указывать queue |
| mode | ETableReplicaMode | sync или async - режим реплики при создании |
| enabled | bool | true или false - должна ли реплика быть включена |
| catchup | bool | true если реплика должна подтянуть данные, false если нужно начать с чистого листа |
| replication_progress | TReplicationProgress | Прогресс при создании реплики (можно опустить, если прогресс уже есть на таблице-реплике) |
| enable_replicated_table_tracker | bool | true если для реплики должно быть включено автоматическое переключение режима |