Clickhouse. Расширение кластера

Kate

Administrator
Команда форума
Всем привет! Я хотел бы поделиться своим опытом по расширению высоконагруженного кластера ClickHouse, немного о том как работает репликация и шардирование.

Репликация​

Репликация работает в рамках одного шарда на уровне таблиц, которые были созданы используя семейства движков ReplicatedMergeTree. На каждом шарде, репликация работает независимо от других шардов. Репликация в Clickhouse работает посредством Apache Zookeeper, где хранятся метаданные о репликах. Apache Zookeeper также отказоустойчив, и можно собрать ансамбль из 3 нод для отказоустойчивости.

У Zookeeper есть один недостаток в виде zxid. Zxid - это идентификатор транзакций который имеет тип данных Int32. Когда количество транзакций превышает 32-битное число, можно получить ошибку: "zxid lower 32 bits have rolled over, forcing re-election, and therefore new epoch start". В момент, когда происходит re-election, записи в кликхаус не отрабатываются.

Шардирование​

Шардирование - это стратегия горизонтального масштабирования кластера, которая позволяет хранить часть данных на разных шардах. Для того, чтобы распределить данные по шардам, нужно создать таблицу на движке Distributed, а также нужно указать в файле конфигурации, информацию о расположении шардов и реплик на каждой ноде. Можно шардировать данные не задействуя Zookeeper.

Отказоустойчивость​

Для нашей компании потеря данных недопустима, поэтому нужно обеспечить максимальную сохранность данных. Для отказоустойчивого кластера важно иметь нечетное количество узлов в рамках одного шарда. Считаю, что иметь в шарде 3 реплики достаточным, т.к. 3 реплики позволяет обеспечить "кворумную запись", также позволяет терпеть крах одного из реплик в шарде, не оказывая влияние на работу кластера.

Кворумная запись. Почему реплик в шарде 3 а не 2?​

Предположим, что одна из реплик шарда приняла запись, обычно остальные реплики должны между собой асинхронно синхронизировать запись. Но, что если после принятия записи сервер не успел среплецировать принятую запись на остальные реплики и потерпел крах без возможности восстановления. В таком случае, данные будут потеряны. В ClickHouse, есть возможность задать "кворумную запись" при которой запись будет считаться успешной, если при записи в каждом шарде, запись приняли минимум 2 узла из 3. Если в шарде будут недоступны 2 узла из 3, то в таком случае кластер записи принимать не будет, и данные будут копиться в менеджере очередей MQ. При такой стратегии записи, стоит позаботиться об объёме хранилища менеджера очередей MQ, для того, чтобы было время привести реплики в рабочее состояние, иначе банально может не хватить места на диске для записи.

Файл конфигурации config.xml​

У ClickHouse, есть файл конфигурации config.xml, в котором можно задать параметры для сервера ClickHouse. Для удобства из config.xml, я вывел отдельно параметры, которые задаются уникально для каждого отдельного узла. Параметры которые будут одинаковы на всех серверах, оставил их в config.xml. Ниже будут указаны примеры:
address.xml - конфигурационный файл, который задаёт IP адрес и порты:
<yandex>
<listen_host>192.168.56.100</listen_host>
<http_port>8123</http_port>
<tcp_port>9000</tcp_port>
<interserver_http_port>9009</interserver_http_port>
<prometheus>
<port>9363</port>
</prometheus>
</yandex>
storage.xml - конфигрурационный файл, который задает расположение файлов и директорий в ОС:
<yandex>
<logger>
<log>/home/clickhouse/log/clickhouse-server.log</log>
<errorlog>/home/clickhouse/log/clickhouse-server.err.log</errorlog>
</logger>
<path>/home/clickhouse/data/</path>
<tmp_path>/home/clickhouse/tmp/</tmp_path>
<user_files_path>/home/clickhouse/user_files/</user_files_path>
<access_control_path>/home/clickhouse/access/</access_control_path>
<format_schema_path>/home/clickhouse/format_schemas/</format_schema_path>
</yandex>
zoo.xml - конфигрурационный файл, в котором нужно указать путь к нодам Zookeeper и задать макросы:
<yandex>
<zookeeper>
<node>
<host>192.168.56.200</host>
<port>2182</port>
</node>
<node>
<host>192.168.56.201</host>
<port>2182</port>
</node>
<node>
<host>192.168.56.202</host>
<port>2182</port>
</node>
</zookeeper>
<macros incl="macros" optional="true" />
<macros>
<shard>17</shard>
<replica>server's_hostname</replica>
</macros>
</yandex>
cluster.xml - конфигрурационный файл, отвечающий за архитектуру кластера:
<yandex>
<remote_servers incl="clickhouse_remote_servers" >
<cluster_name>
<shard>
<internal_replication>true</internal_replication>
<weight>1</weight>
<replica>
<host>hostname-192-168-56-165</host>
<port>9000</port>
<priority>1</priority>
</replica>
<replica>
<host>hostname-192-168-56-166</host>
<port>9000</port>
<priority>1</priority>
</replica>
<replica>
<host>hostname-192-168-56-167</host>
<port>9000</port>
<priority>1</priority>
</replica>
</shard>
<shard>
<internal_replication>true</internal_replication>
<weight>1</weight>
<replica>
<host>hostname-192-168-56-168</host>
<port>9000</port>
<priority>1</priority>
</replica>
<replica>
<host>hostname-192-168-56-169</host>
<port>9000</port>
<priority>1</priority>
</replica>
<replica>
<host>hostname-192-168-56-170</host>
<port>9000</port>
<priority>1</priority>
</replica>
</shard>
</cluster_name>
</remote_servers>
</yandex>

Расширение кластера​

Настоятельно рекомендую использовать плейбуки при разворачивании новых нод, хорошо написанный плейбук, позволяет избегать ненужных ошибок и сэкономит ваше время.
После того как вы закончили разворачивание новых нод, нужно с рабочего кластера получить скрипт на создание таблиц c движками ReplicatedMerge и Distributed и при помощи этих скриптов создать таблицы на новых серверах.
Если вы выполните подобный команду:
clickhouse-client -h $HOSTNAME --query="show create table database1.table1;" > table1.sql
и попытаетесь применить его на сервере CickHouse, то вы получите подобную ошибку:
Code: 62. DB::Exception: Syntax error: failed at position 25 ('\'): \n(\n
Но если вы выполните команду таким образом:
s=$(clickhouse-client -h $HOSTNAME --query="show create table database1.table1;") && echo -e "$s" | tr -d '\' > table1.sql
у вас получится выполнить команду создания таблицы путем импорта скрипта:
clickhouse-client -h $HOSTNAME --query="CREATE DATABASE database1"
clickhouse-client -h $HOSTNAME < table1.sql
После создания таблиц, нужно создать пользователей и дать привилегии этим пользователям которые будут обращаться к таблицам.
К сожалению в ClickHouse нельзя выполнив "show create user" получить команду на создания пользователя, команду наделения привилегий для пользователя и также получить хеш пароль пользователя, как это устроено в MySQL. Т.е. если вы забыли или не знаете пароль пользователя, то у вас не получится его создать также как на рабочем кластере.
Можно выделить важные моменты при расширении кластера:
  • Версии новых нод, должны быть такими же как с расширяемым кластером.
  • Все настройки указанные в users.xml, должны быть идентичны между собой. Иначе это может привести к непредвиденному поведению кластера.
  • После завершения разворачивания новых нод, нужно на каждом новом узле создать таблицы, которые имеются в кластере.
  • Т.к. в ClickHouse нельзя перешардировать данные в кластере в рамках одной таблицы. Чтобы увеличить приоритет новых записей на новые шарды, нужно перераспределить "weight". Не давайте слишком большой "weight" на новые шарды, если вы неуверены, что новые шарды способны выдержать оказываемую нагрузку на запись.
  • Создание пользователей и наделение привилегии.
  • После внесения изменений в cluster.xml с добавлением новых шард и реплик, необходимо перезагрузить каждую ноду.
Я получил информацию с сообщества "Clickhouse не тормозит", что кластерные конфигурации можно менять на горячую, без перезагрузки. После внесения правок, изменения действительно отражаются в system.clusters в виде новых шард и реплик. Но на деле, после изменения конфиг файла записи отваливались с ошибками, что некоторые из новых шард отрабатывались медленно. Но после перезагрузки каждого узла, ситуация нормализовалась.

 
Сверху