Движки таблиц Replicated*
В ClickHouse Cloud репликацией управляет платформа. Пожалуйста, создавайте таблицы без дополнительных аргументов. Например, в тексте ниже вы бы заменили:
с помощью:
Репликация поддерживается только для таблиц семейства MergeTree:
- ReplicatedMergeTree
- ReplicatedSummingMergeTree
- ReplicatedReplacingMergeTree
- ReplicatedAggregatingMergeTree
- ReplicatedCollapsingMergeTree
- ReplicatedVersionedCollapsingMergeTree
- ReplicatedGraphiteMergeTree
Репликация работает на уровне отдельной таблицы, а не всего сервера. Один сервер может одновременно хранить как реплицируемые, так и нереплицируемые таблицы.
Репликация не зависит от разбиения на сегменты. Каждый сегмент имеет собственную независимую репликацию.
Сжатые данные для запросов INSERT и ALTER реплицируются (дополнительную информацию см. в документации по ALTER).
Запросы CREATE, DROP, ATTACH, DETACH и RENAME выполняются на одном сервере и не реплицируются:
- Запрос
CREATE TABLEсоздаёт новую реплицируемую таблицу на сервере, на котором выполняется запрос. Если такая таблица уже существует на других серверах, создаётся новая реплика. - Запрос
DROP TABLEудаляет реплику, расположенную на сервере, на котором выполняется запрос. - Запрос
RENAMEпереименовывает таблицу на одной из реплик. Другими словами, реплицируемые таблицы могут иметь разные имена на разных репликах.
ClickHouse использует ClickHouse Keeper для хранения метаинформации о репликах. Можно использовать ZooKeeper версии 3.4.5 или новее, но рекомендуется ClickHouse Keeper.
Чтобы использовать репликацию, задайте параметры в разделе конфигурации сервера zookeeper.
Не пренебрегайте настройками безопасности. ClickHouse поддерживает схему digest ACL подсистемы безопасности ZooKeeper.
Пример настройки адресов кластера ClickHouse Keeper:
ClickHouse также поддерживает хранение метаинформации о репликах во вспомогательном кластере ZooKeeper. Для этого укажите имя кластера ZooKeeper и путь в параметрах движка. Другими словами, поддерживается хранение метаданных разных таблиц в разных кластерах ZooKeeper.
Пример задания адресов вспомогательного кластера ZooKeeper:
Чтобы хранить метаданные таблицы в дополнительном кластере ZooKeeper вместо кластера ZooKeeper по умолчанию, можно создать таблицу с движком ReplicatedMergeTree с помощью следующего SQL-запроса:
Вы можете указать любой существующий кластер ZooKeeper, и система будет использовать на нём каталог для собственных данных (каталог задаётся при создании реплицируемой таблицы).
Если ZooKeeper не указан в конфигурационном файле, вы не сможете создавать реплицируемые таблицы, а любые существующие реплицируемые таблицы будут доступны только для чтения.
ZooKeeper не используется в запросах SELECT, потому что репликация не влияет на производительность SELECT, и запросы выполняются так же быстро, как и для нереплицируемых таблиц. При выполнении запросов к распределённым реплицируемым таблицам поведение ClickHouse управляется настройками max_replica_delay_for_distributed_queries и fallback_to_stale_replicas_for_distributed_queries.
Для каждого запроса INSERT в ZooKeeper добавляется примерно десять записей через несколько транзакций. (Более точно: для каждого вставленного блока данных; один запрос INSERT содержит один блок или один блок на max_insert_block_size = 1048576 строк.) Это приводит к немного большему времени ожидания для INSERT по сравнению с нереплицируемыми таблицами. Но если вы следуете рекомендациям и вставляете данные пакетами не чаще одного INSERT в секунду, это не создаёт никаких проблем. Весь кластер ClickHouse, используемый для координации одного кластера ZooKeeper, в сумме обрабатывает несколько сотен запросов INSERT в секунду. Пропускная способность по вставке данных (количество строк в секунду) столь же высока, как и для нереплицируемых данных.
Для очень больших кластеров вы можете использовать разные кластеры ZooKeeper для разных сегментов. Однако, по нашему опыту, в боевых кластерах примерно из 300 серверов в этом не было необходимости.
Репликация асинхронная и multi-master. Запросы INSERT (а также ALTER) могут быть отправлены на любой доступный сервер. Данные вставляются на сервере, где выполняется запрос, а затем копируются на другие серверы. Поскольку это происходит асинхронно, недавно вставленные данные появляются на других репликах с некоторой задержкой. Если часть реплик недоступна, данные будут записаны, когда они станут доступными. Если реплика доступна, задержка равна времени передачи блока сжатых данных по сети. Количество потоков, выполняющих фоновые задачи для реплицируемых таблиц, может быть задано настройкой background_schedule_pool_size.
Движок ReplicatedMergeTree использует отдельный пул потоков для реплицируемых загрузок данных (fetches). Размер пула ограничен настройкой background_fetches_pool_size, которую можно изменить с перезапуском сервера.
По умолчанию запрос INSERT ожидает подтверждения записи данных только от одной реплики. Если данные были успешно записаны только на одну реплику и сервер с этой репликой перестаёт существовать, сохранённые данные будут утеряны. Чтобы включить получение подтверждения о записи данных от нескольких реплик, используйте опцию insert_quorum.
Каждый блок данных записывается атомарно. Запрос INSERT разбивается на блоки до max_insert_block_size = 1048576 строк. Другими словами, если запрос INSERT содержит меньше 1048576 строк, он выполняется атомарно.
Блоки данных дедуплицируются. При многократной записи одного и того же блока данных (блоки данных одного размера, содержащие одни и те же строки в одном и том же порядке) блок записывается только один раз. Это сделано для случая сбоев сети, когда клиентское приложение не знает, были ли данные записаны в БД, поэтому запрос INSERT можно просто повторить. Неважно, на какие реплики отправлялись запросы INSERT с идентичными данными. Запросы INSERT являются идемпотентными. Параметры дедупликации управляются серверными настройками merge_tree.
Во время репликации по сети передаются только исходные данные для вставки. Дальнейшее преобразование данных (слияние) координируется и выполняется на всех репликах одинаковым образом. Это минимизирует сетевой трафик, что означает, что репликация хорошо работает, когда реплики находятся в разных дата-центрах. (Обратите внимание, что дублирование данных в разных дата-центрах является основной целью репликации.)
Вы можете иметь любое количество реплик одних и тех же данных. По нашему опыту, относительно надёжным и удобным решением может быть двойная репликация в продакшене, когда каждый сервер использует RAID-5 или RAID-6 (и RAID-10 в некоторых случаях).
Система отслеживает синхронность данных на репликах и способна восстанавливаться после сбоя. Переключение на резерв (failover) происходит автоматически (при небольших различиях в данных) или полуавтоматически (когда данные различаются слишком сильно, что может указывать на ошибку конфигурации).
Создание реплицируемых таблиц
В ClickHouse Cloud репликация осуществляется автоматически.
Создавайте таблицы, используя MergeTree без аргументов репликации. Система внутренне преобразует MergeTree в SharedMergeTree для репликации и распределения данных.
Не используйте ReplicatedMergeTree и не задавайте параметры репликации, так как репликацией управляет платформа.
Параметры Replicated*MergeTree
| Параметр | Описание |
|---|---|
zoo_path | Путь к таблице в ClickHouse Keeper. |
replica_name | Имя реплики в ClickHouse Keeper. |
other_parameters | Параметры движка, используемого для создания реплицированной версии, например version в ReplacingMergeTree. |
Пример:
Пример с устаревшим синтаксисом
Как видно из примера, эти параметры могут содержать подстановки в фигурных скобках. Значения для подстановки берутся из раздела macros файла конфигурации.
Пример:
Путь к таблице в ClickHouse Keeper должен быть уникальным для каждой реплицируемой таблицы. Таблицы на разных сегментах должны иметь разные пути. В данном случае путь состоит из следующих частей:
/clickhouse/tables/ — это общий префикс. Мы рекомендуем использовать именно его.
{shard} будет подставлен как идентификатор сегмента.
table_name — это имя узла для таблицы в ClickHouse Keeper. Хорошей идеей будет сделать его таким же, как имя таблицы. Оно задаётся явно, потому что, в отличие от имени таблицы, не изменяется после запроса RENAME.
ПОДСКАЗКА: вы также можете добавить имя базы данных перед table_name. Например, db_name.table_name
Можно использовать две встроенные подстановки {database} и {table}, которые подставляются как имя таблицы и имя базы данных соответственно (если только эти макросы не определены в секции macros). Таким образом, путь в ClickHouse Keeper можно задать как '/clickhouse/tables/{shard}/{database}/{table}'.
Будьте осторожны с переименованием таблиц при использовании этих встроенных подстановок. Путь в ClickHouse Keeper нельзя изменить, и когда таблица переименовывается, макросы будут подставляться в другой путь, таблица будет ссылаться на путь, который не существует в ClickHouse Keeper, и перейдёт в режим только для чтения.
Имя реплики идентифицирует разные реплики одной и той же таблицы. Для этого вы можете использовать имя сервера, как в примере. Имя должно быть уникальным только внутри каждого сегмента.
Вы можете задать параметры явно вместо использования подстановок. Это может быть удобно для тестирования и настройки небольших кластеров. Однако в этом случае вы не можете использовать распределённые DDL-запросы (ON CLUSTER).
При работе с большими кластерами мы рекомендуем использовать подстановки, так как они снижают вероятность ошибок.
Вы можете задать аргументы по умолчанию для движка таблиц Replicated в конфигурационном файле сервера. Например:
В этом случае при создании таблиц можно не указывать аргументы:
Это эквивалентно следующему:
Выполните запрос CREATE TABLE на каждой реплике. Этот запрос создает новую реплицируемую таблицу или добавляет новую реплику к уже существующей.
Если вы добавляете новую реплику после того, как таблица уже содержит какие‑то данные на других репликах, данные будут скопированы с других реплик на новую реплику после выполнения этого запроса. Другими словами, новая реплика синхронизируется с остальными.
Чтобы удалить реплику, выполните DROP TABLE. Однако удаляется только одна реплика — та, которая находится на сервере, где вы выполняете запрос.
Восстановление после сбоев
Если ClickHouse Keeper недоступен при запуске сервера, реплицируемые таблицы переключаются в режим только для чтения. Система периодически пытается подключиться к ClickHouse Keeper.
Если ClickHouse Keeper недоступен во время выполнения INSERT или при взаимодействии с ClickHouse Keeper возникает ошибка, выбрасывается исключение.
После подключения к ClickHouse Keeper система проверяет, соответствует ли набор данных в локальной файловой системе ожидаемому набору данных (ClickHouse Keeper хранит эту информацию). При незначительных несоответствиях система устраняет их, синхронизируя данные с репликами.
Если система обнаруживает поврежденные части данных (с неправильным размером файлов) или нераспознанные части (части, записанные в файловую систему, но не зарегистрированные в ClickHouse Keeper), она перемещает их в подкаталог detached (они не удаляются). Любые отсутствующие части копируются с реплик.
Обратите внимание, что ClickHouse не выполняет никаких разрушающих действий, таких как автоматическое удаление большого объема данных.
При запуске сервера (или установлении новой сессии с ClickHouse Keeper) он проверяет только количество и размеры всех файлов. Если размеры файлов совпадают, но байты были изменены где-то в середине файла, это обнаруживается не сразу, а только при попытке чтения данных для запроса SELECT. В этом случае запрос завершится исключением о несовпадающей контрольной сумме или размере сжатого блока. Части данных добавляются в очередь проверки и при необходимости копируются с реплик.
Если локальный набор данных существенно отличается от ожидаемого, срабатывает защитный механизм. Сервер записывает это в лог и отказывается запускаться. Причина в том, что такая ситуация может указывать на ошибку конфигурации, например, если реплика на одном сегменте была по ошибке настроена как реплика на другом сегменте. Однако пороговые значения для этого механизма установлены достаточно низко, и такая ситуация может возникнуть при обычном восстановлении после сбоя. В этом случае данные восстанавливаются полуавтоматически — «нажатием кнопки».
Чтобы начать восстановление, создайте в ClickHouse Keeper узел /path_to_table/replica_name/flags/force_restore_data с любым содержимым или выполните команду для восстановления всех реплицируемых таблиц:
Затем перезапустите сервер. При запуске сервер удаляет эти флаги и начинает восстановление.
Восстановление после полной потери данных
Если все данные и метаданные исчезли с одного из серверов, выполните следующие шаги для восстановления:
- Установите ClickHouse на сервер. Корректно задайте подстановки в конфигурационном файле, который содержит идентификатор сегмента и реплик, если вы их используете.
- Если у вас были нереплицированные таблицы, которые необходимо вручную продублировать на серверах, скопируйте их данные с реплики (из каталога
/var/lib/clickhouse/data/db_name/table_name/). - Скопируйте определения таблиц, расположенные в
/var/lib/clickhouse/metadata/, с реплики. Если в определениях таблиц явно задан идентификатор сегмента или реплики, скорректируйте его так, чтобы он соответствовал этой реплике. (Либо запустите сервер и выполните все запросыATTACH TABLE, которые должны были быть в .sql-файлах в/var/lib/clickhouse/metadata/.) - Чтобы запустить восстановление, создайте узел ClickHouse Keeper
/path_to_table/replica_name/flags/force_restore_dataс любым содержимым или выполните команду для восстановления всех реплицированных таблиц:sudo -u clickhouse touch /var/lib/clickhouse/flags/force_restore_data
Затем запустите сервер (или перезапустите, если он уже работает). Данные будут загружены с реплик.
Альтернативный вариант восстановления — удалить информацию о потерянной реплике из ClickHouse Keeper (/path_to_table/replica_name), затем создать реплику заново, как описано в разделе "Создание реплицированных таблиц".
Во время восстановления нет ограничений на пропускную способность сети. Учитывайте это, если вы восстанавливаете большое количество реплик одновременно.
Преобразование из MergeTree в ReplicatedMergeTree
Мы используем термин MergeTree для обозначения всех движков таблиц семейства MergeTree, аналогично и для ReplicatedMergeTree.
Если у вас была таблица MergeTree, которая реплицировалась вручную, вы можете преобразовать её в реплицируемую таблицу. Это может понадобиться, если вы уже накопили большой объём данных в таблице MergeTree и теперь хотите включить репликацию.
Команда ATTACH TABLE ... AS REPLICATED позволяет прикрепить отсоединённую таблицу MergeTree как таблицу ReplicatedMergeTree.
Таблица MergeTree может быть автоматически преобразована при перезапуске сервера, если флаг convert_to_replicated установлен в каталоге с данными таблицы (/store/xxx/xxxyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy/ для базы данных Atomic).
Создайте пустой файл convert_to_replicated, и при следующем перезапуске сервера таблица будет загружена как реплицируемая.
Этот запрос можно использовать, чтобы получить путь к данным таблицы. Если у таблицы несколько путей к данным, необходимо использовать первый.
Обратите внимание, что таблица ReplicatedMergeTree будет создана со значениями настроек default_replica_path и default_replica_name.
Чтобы создать преобразованную таблицу на других репликах, вам нужно явно указать ее путь в первом аргументе движка таблицы ReplicatedMergeTree. Для получения этого пути можно выполнить следующий запрос.
Есть и способ сделать это вручную.
Если данные различаются на разных репликах, сначала синхронизируйте их или удалите эти данные на всех репликах, кроме одной.
Переименуйте существующую таблицу MergeTree, затем создайте таблицу ReplicatedMergeTree со старым именем.
Переместите данные из старой таблицы в подкаталог detached внутри каталога с данными новой таблицы (/var/lib/clickhouse/data/db_name/table_name/).
Затем выполните ALTER TABLE ATTACH PARTITION на одной из реплик, чтобы добавить эти части в рабочий набор.
Преобразование из ReplicatedMergeTree в MergeTree
Используйте команду ATTACH TABLE ... AS NOT REPLICATED, чтобы подключить отсоединённую таблицу ReplicatedMergeTree как MergeTree на одном сервере.
Другой способ сделать это требует перезапуска сервера. Создайте таблицу MergeTree с другим именем. Переместите все данные из каталога с данными таблицы ReplicatedMergeTree в каталог данных новой таблицы. Затем удалите таблицу ReplicatedMergeTree и перезапустите сервер.
Если вы хотите избавиться от таблицы ReplicatedMergeTree, не запуская сервер:
- Удалите соответствующий файл
.sqlв каталоге метаданных (/var/lib/clickhouse/metadata/). - Удалите соответствующий путь в ClickHouse Keeper (
/path_to_table/replica_name).
После этого вы можете запустить сервер, создать таблицу MergeTree, переместить данные в её каталог, а затем перезапустить сервер.
Восстановление после потери или повреждения метаданных в кластере ClickHouse Keeper
Если данные в ClickHouse Keeper были утеряны или повреждены, вы можете сохранить их, переместив в нереплицируемую таблицу, как описано выше.
См. также