Перейти к основному содержимому
Перейти к основному содержимому

Репликация данных

примечание

В 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 поддерживает схему ACL digest системы безопасности ZooKeeper.

Пример задания адресов кластера ClickHouse Keeper:

ClickHouse также поддерживает хранение метаинформации о репликах в вспомогательном кластере ZooKeeper. Это делается путем указания имени кластера ZooKeeper и пути в качестве аргументов движка. Другими словами, он поддерживает хранение метаданных различных таблиц в разных кластерах ZooKeeper.

Пример задания адресов вспомогательного кластера ZooKeeper:

Чтобы хранить метаданные таблицы во вспомогательном кластере ZooKeeper вместо кластера ZooKeeper по умолчанию, мы можем использовать SQL для создания таблицы с движком ReplicatedMergeTree следующим образом:

Вы можете указать любой существующий кластер 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, имеет общий показатель несколько сотен INSERTs в секунду. Пропускная способность при вставках данных (количество строк в секунду) также высока, как и для нереплицированных данных.

Для очень больших кластеров вы можете использовать разные кластеры ZooKeeper для разных шардов. Тем не менее, из нашего опыта это не оказалось необходимым на производственных кластерах с примерно 300 серверами.

Репликация является асинхронной и многомастеров. Запросы INSERT (а также ALTER) могут отправляться на любой доступный сервер. Данные вставляются на сервере, где выполняется запрос, а затем копируются на другие серверы. Поскольку это асинхронно, недавно вставленные данные появляются на других репликах с некоторой задержкой. Если часть реплик недоступны, данные записываются по мере их доступности. Если реплика доступна, задержка составляет время, необходимое для передачи блока сжатых данных по сети. Количество потоков, выполняющих фоновые задачи для реплицированных таблиц, можно установить с помощью настройки background_schedule_pool_size.

Движок ReplicatedMergeTree использует отдельный пул потоков для реплицированных выборок. Размер пула ограничен настройкой background_fetches_pool_size, которую можно настроить с помощью перезапуска сервера.

По умолчанию запрос INSERT ожидает подтверждения записи данных только от одной реплики. Если данные успешно записаны только в одну реплику, и сервер с этой репликой перестает существовать, хранимые данные будут потеряны. Чтобы получить подтверждение записи данных от нескольких реплик, используйте опцию insert_quorum.

Каждый блок данных записывается атомарно. Запрос INSERT делится на блоки по max_insert_block_size = 1048576 строк. Другими словами, если запрос INSERT содержит менее 1048576 строк, он выполняется атомарно.

Блоки данных дедуплицируются. При нескольких записях одного и того же блока данных (блоки данных одинакового размера, содержащие одни и те же строки в одном и том же порядке) блок записывается только один раз. Это сделано на случай сетевых сбоев, когда клиентское приложение не знает, были ли данные записаны в БД, поэтому запрос INSERT можно просто повторить. Не имеет значения, на какие реплики отправлялись одинаковые данные. INSERTs идемпотентны. Параметры дедупликации контролируются настройками сервера merge_tree.

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

Вы можете иметь любое количество реплик одних и тех же данных. Из нашего опыта, относительно надежным и удобным решением может быть применение двойной репликации в производственной среде, при этом каждый сервер использует RAID-5 или RAID-6 (и RAID-10 в некоторых случаях).

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

Создание реплицированных таблиц

примечание

В ClickHouse Cloud репликация управляется для вас. Пожалуйста, создавайте свои таблицы без добавления аргументов. Например, в приведенном ниже тексте вы замените:

на:

Префикс Replicated добавляется к имени движка таблицы. Например: ReplicatedMergeTree.

подсказка

Добавление Replicated является необязательным в ClickHouse Cloud, так как все таблицы реплицируются.

Параметры Replicated*MergeTree

zoo_path

zoo_path — Путь к таблице в ClickHouse Keeper.

replica_name

replica_name — Имя реплики в ClickHouse Keeper.

other_parameters

other_parameters — Параметры движка, используемого для создания реплицированной версии, например, версия в ReplacingMergeTree.

Пример:

Пример в устаревшем синтаксисе

Как показывает пример, эти параметры могут содержать подстановки в фигурных скобках. Подставленные значения берутся из секции macros конфигурационного файла.

Пример:

Путь к таблице в ClickHouse Keeper должен быть уникальным для каждой реплицированной таблицы. Таблицы на разныхShard должны иметь разные пути. В этом случае путь состоит из следующих частей:

/clickhouse/tables/ — общий префикс. Рекомендуется использовать именно его.

{shard} будет расширен до идентификатора шарда.

table_name — это имя узла для таблицы в ClickHouse Keeper. Хорошая идея — сделать его таким же, как и имя таблицы. Оно определено явно, потому что в отличие от имени таблицы, оно не меняется после запроса RENAME. Подсказка: вы также можете добавить имя базы данных перед table_name. Например, db_name.table_name

Две встроенные подстановки {database} и {table} могут использоваться, они преобразуются в имя таблицы и имя базы данных соответственно (если только эти макросы не определены в секции macros). Таким образом, путь к ZooKeeper можно указать как '/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. Запрос вызывает исключение о несовпадающей контрольной сумме или размере сжатого блока. В этом случае части данных добавляются в очередь проверок и копируются с реплик при необходимости.

Если локальный набор данных слишком сильно отличается от ожидаемого, срабатывает защитный механизм. Сервер сообщает об этом в журнал и отказывается от запуска. Причина в том, что этот случай может указывать на ошибку конфигурации, например, если реплика на шарде была случайно настроена как реплика на другом шарде. Тем не менее, пороги для этого механизма установлены довольно низкими, и эта ситуация может возникнуть в процессе нормального восстановления после сбоя. В этом случае данные восстанавливаются полууавтоматически - "нажатием кнопки".

Чтобы начать восстановление, создайте узел /path_to_table/replica_name/flags/force_restore_data в ClickHouse Keeper с любым содержимым или выполните команду для восстановления всех реплицированных таблиц:

Затем перезапустите сервер. При запуске сервер удаляет эти флаги и начинает восстановление.

Восстановление после полной потери данных

Если все данные и метаданные исчезли с одного из серверов, выполните следующие шаги для восстановления:

  1. Установите ClickHouse на сервере. Правильно определите подстановки в конфигурационном файле, который содержит идентификатор шара и реплики, если вы их используете.
  2. Если у вас были нереплицированные таблицы, которые необходимо вручную продублировать на серверах, скопируйте их данные с реплики (в директории /var/lib/clickhouse/data/db_name/table_name/).
  3. Скопируйте определения таблиц, расположенные в /var/lib/clickhouse/metadata/, с реплики. Если идентификатор шара или реплики указан явно в определениях таблиц, исправьте его так, чтобы он соответствовал этой реплике. (В качестве альтернативы можно запустить сервер и выполнить все запросы ATTACH TABLE, которые должны были быть в .sql файлах в /var/lib/clickhouse/metadata/.)
  4. Чтобы начать восстановление, создайте узел 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/ для атомарной базы данных). Создайте пустой файл 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 были потеряны или повреждены, вы можете сохранить данные, переместив их в нереплицированную таблицу, как описано выше.

См. также