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

ClickHouse Keeper (clickhouse-keeper)

Not supported in ClickHouse Cloud
Примечание

This page is not applicable to ClickHouse Cloud. The procedure documented here is automated in ClickHouse Cloud services.

ClickHouse Keeper предоставляет систему координации для репликации данных и выполнения запросов распределённого DDL. ClickHouse Keeper совместим с ZooKeeper.

Детали реализации

ZooKeeper — одна из первых хорошо известных систем координации с открытым исходным кодом. Она реализована на Java и имеет довольно простую и мощную модель данных. Алгоритм координации ZooKeeper, ZooKeeper Atomic Broadcast (ZAB), не предоставляет гарантий линеаризуемости чтения, так как каждый узел ZooKeeper обрабатывает операции чтения локально. В отличие от ZooKeeper, ClickHouse Keeper написан на C++ и использует алгоритм RAFT в реализации. Этот алгоритм обеспечивает линеаризуемость для операций чтения и записи и имеет несколько реализаций с открытым исходным кодом на разных языках.

По умолчанию ClickHouse Keeper предоставляет те же гарантии, что и ZooKeeper: линеаризуемые записи и нелинеаризуемые чтения. Он использует совместимый клиент-серверный протокол, поэтому любой стандартный клиент ZooKeeper можно использовать для взаимодействия с ClickHouse Keeper. Снимки и журналы имеют формат, несовместимый с ZooKeeper, но инструмент clickhouse-keeper-converter позволяет преобразовать данные ZooKeeper в снимки ClickHouse Keeper. Межсерверный протокол в ClickHouse Keeper также несовместим с ZooKeeper, поэтому смешанный кластер ZooKeeper / ClickHouse Keeper невозможен.

ClickHouse Keeper поддерживает списки контроля доступа (ACL) так же, как и ZooKeeper. ClickHouse Keeper поддерживает тот же набор прав и имеет идентичные встроенные схемы: world, auth и digest. Схема аутентификации digest использует пару username:password, при этом пароль кодируется в Base64.

Примечание

Внешние интеграции не поддерживаются.

Конфигурация

ClickHouse Keeper может использоваться как самостоятельная замена ZooKeeper или как внутренняя часть сервера ClickHouse. В обоих случаях конфигурация задаётся практически одинаковым .xml-файлом.

Параметры конфигурации Keeper

Основной конфигурационный тег ClickHouse Keeper — <keeper_server> и имеет следующие параметры:

ParameterDescriptionDefault
tcp_portПорт для подключения клиента.2181
tcp_port_secureЗащищённый порт для SSL-подключения между клиентом и keeper-server.-
server_idУникальный идентификатор сервера, каждый участник кластера ClickHouse Keeper должен иметь уникальный номер (1, 2, 3 и так далее).-
log_storage_pathПуть к журналам координации; как и в ZooKeeper, журналы лучше хранить на незагруженных узлах.-
snapshot_storage_pathПуть к снимкам состояния координации.-
enable_reconfigurationВключить динамическую переконфигурацию кластера с помощью reconfig.False
max_memory_usage_soft_limitМягкое ограничение в байтах на максимальное потребление памяти Keeper.max_memory_usage_soft_limit_ratio * physical_memory_amount
max_memory_usage_soft_limit_ratioЕсли max_memory_usage_soft_limit не задан или установлен в ноль, используется это значение для определения значения мягкого ограничения по умолчанию.0.9
cgroups_memory_observer_wait_timeЕсли max_memory_usage_soft_limit не задан или установлен в 0, используется этот интервал для наблюдения за объёмом физической памяти. Как только объём памяти изменится, мягкое ограничение памяти Keeper будет пересчитано по max_memory_usage_soft_limit_ratio.15
http_controlКонфигурация интерфейса HTTP control.-
digest_enabledВключить проверку согласованности данных в режиме реального времени.True
create_snapshot_on_exitСоздавать снимок состояния при завершении работы.-
hostname_checks_enabledВключить базовые проверки имён хостов для конфигурации кластера (например, если localhost используется с удалёнными конечными точками).True
four_letter_word_white_listБелый список команд 4lw.conf, cons, crst, envi, ruok, srst, srvr, stat, wchs, dirs, mntr, isro, rcvr, apiv, csnp, lgif, rqld, ydld
enable_ipv6Включить поддержку IPv6True

Другие общие параметры наследуются из конфигурации сервера ClickHouse (listen_host, logger и так далее).

Internal coordination settings

Внутренние настройки координации находятся в секции <keeper_server>.<coordination_settings> и включают следующие параметры:

ПараметрОписаниеЗначение по умолчанию
operation_timeout_msТаймаут для одной клиентской операции (мс)10000
min_session_timeout_msМинимальный таймаут для клиентской сессии (мс)10000
session_timeout_msМаксимальный таймаут для клиентской сессии (мс)100000
dead_session_check_period_msКак часто ClickHouse Keeper проверяет «мертвые» сессии и удаляет их (мс)500
heart_beat_interval_msКак часто лидер ClickHouse Keeper отправляет heartbeat-сообщения последователям (мс)500
election_timeout_lower_bound_msЕсли в течение этого интервала последователь не получает heartbeat от лидера, он может инициировать выборы лидера. Значение должно быть меньше или равно election_timeout_upper_bound_ms. В идеале они не должны быть равны.1000
election_timeout_upper_bound_msЕсли в течение этого интервала последователь не получает heartbeat от лидера, он обязан инициировать выборы лидера.2000
rotate_log_storage_intervalСколько записей лога хранить в одном файле.100000
reserved_log_itemsСколько записей журнала координации хранить до выполнения компакции.100000
snapshot_distanceКак часто ClickHouse Keeper будет создавать новые снапшоты (в количестве записей в логах).100000
snapshots_to_keepСколько снапшотов хранить.3
stale_log_gapПорог, при котором лидер считает последователя устаревшим и отправляет ему снапшот вместо логов.10000
fresh_log_gapУсловие, при котором узел считается «свежим».200
max_requests_batch_sizeМаксимальный размер батча по количеству запросов перед отправкой в RAFT.100
force_syncВызывать fsync при каждой записи в журнал координации.true
quorum_readsВыполнять запросы на чтение как операции записи, проходящие через весь консенсус RAFT, с сопоставимой скоростью.false
raft_logs_levelУровень текстового логирования о координации (trace, debug и т. д.).system default
auto_forwardingРазрешить перенаправление запросов на запись от последователей к лидеру.true
shutdown_timeoutОжидание завершения внутренних соединений и остановки (мс).5000
startup_timeoutЕсли сервер не подключается к другим участникам кворума в заданный таймаут, он завершает работу (мс).30000
async_replicationВключить асинхронную репликацию. Все гарантии записи и чтения сохраняются при повышенной производительности. Настройка отключена по умолчанию, чтобы не нарушать обратную совместимость.false
latest_logs_cache_size_thresholdМаксимальный общий размер кэша в памяти для последних записей лога1GiB
commit_logs_cache_size_thresholdМаксимальный общий размер кэша в памяти для записей лога, необходимых для следующего подтверждения500MiB
disk_move_retries_wait_msВремя ожидания между повторами после сбоя, произошедшего при перемещении файла между дисками1000
disk_move_retries_during_initКоличество повторных попыток после сбоя, произошедшего при перемещении файла между дисками во время инициализации100
experimental_use_rocksdbИспользовать RocksDB как бэкенд-хранилище0

Конфигурация кворума находится в секции <keeper_server>.<raft_configuration> и содержит описание серверов.

Единственный параметр для всего кворума — secure, который включает зашифрованное соединение для взаимодействия между участниками кворума. Параметр может быть установлен в true, если для внутреннего обмена между узлами требуется SSL-соединение, или оставлен не заданным в противном случае.

Основные параметры для каждого <server>:

  • id — Идентификатор сервера в кворуме.
  • hostname — Имя хоста, на котором размещён этот сервер.
  • port — Порт, на котором этот сервер принимает подключения.
  • can_become_leader — Установите в false, чтобы настроить сервер как learner. Если параметр не указан, по умолчанию используется значение true.
Примечание

В случае изменения топологии вашего кластера ClickHouse Keeper (например, при замене сервера) обязательно сохраняйте соответствие между server_id и hostname и избегайте перестановок или повторного использования уже существующего server_id для других серверов (например, это может произойти, если вы полагаетесь на скрипты автоматизации для развертывания ClickHouse Keeper).

Если хост экземпляра Keeper может меняться, мы рекомендуем использовать hostname вместо «сырых» IP-адресов. Изменение hostname эквивалентно удалению сервера и повторному добавлению его в кластер, что в некоторых случаях может быть невозможно (например, недостаточно экземпляров Keeper для кворума).

Примечание

async_replication по умолчанию отключена, чтобы не нарушать обратную совместимость. Если все ваши экземпляры Keeper в кластере работают на версии, которая поддерживает async_replication (v23.9+), мы рекомендуем включить её, так как это может улучшить производительность без каких-либо недостатков.

Примеры конфигураций кворума с тремя узлами можно найти в интеграционных тестах с префиксом test_keeper_. Пример конфигурации для сервера № 1:

<keeper_server>
    <tcp_port>2181</tcp_port>
    <server_id>1</server_id>
    <log_storage_path>/var/lib/clickhouse/coordination/log</log_storage_path>
    <snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path>

    <coordination_settings>
        <operation_timeout_ms>10000</operation_timeout_ms>
        <session_timeout_ms>30000</session_timeout_ms>
        <raft_logs_level>trace</raft_logs_level>
    </coordination_settings>

    <raft_configuration>
        <server>
            <id>1</id>
            <hostname>zoo1</hostname>
            <port>9234</port>
        </server>
        <server>
            <id>2</id>
            <hostname>zoo2</hostname>
            <port>9234</port>
        </server>
        <server>
            <id>3</id>
            <hostname>zoo3</hostname>
            <port>9234</port>
        </server>
    </raft_configuration>
</keeper_server>

Как запустить

ClickHouse Keeper входит в пакет сервера ClickHouse: просто добавьте конфигурацию <keeper_server> в /etc/your_path_to_config/clickhouse-server/config.xml и запустите сервер ClickHouse как обычно. Если вы хотите запустить ClickHouse Keeper как отдельный компонент, вы можете запустить его аналогичным образом:

clickhouse-keeper --config /etc/your_path_to_config/config.xml

Если у вас нет символической ссылки (clickhouse-keeper), вы можете создать её или указать keeper в качестве аргумента для clickhouse:

clickhouse keeper --config /etc/путь_к_вашему_конфигу/config.xml

Команды из четырёх букв

ClickHouse Keeper также предоставляет команды 4lw, которые почти идентичны командам в ZooKeeper. Каждая команда состоит из четырёх букв, таких как mntr, stat и т. д. Есть несколько более интересных команд: stat предоставляет общую информацию о сервере и подключённых клиентах, тогда как srvr и cons выдают расширенные сведения о сервере и соединениях соответственно.

Для 4lw-команд существует конфигурационный параметр белого списка four_letter_word_white_list, который по умолчанию имеет значение conf,cons,crst,envi,ruok,srst,srvr,stat,wchs,dirs,mntr,isro,rcvr,apiv,csnp,lgif,rqld,ydld.

Вы можете отправлять команды ClickHouse Keeper через telnet или nc, подключаясь к клиентскому порту.

echo mntr | nc localhost 9181

Ниже подробно описаны команды 4lw:

  • ruok: Проверяет, работает ли сервер без ошибок. Сервер ответит imok, если он запущен. В противном случае он не ответит вовсе. Ответ imok не обязательно означает, что сервер вошёл в кворум, а лишь то, что серверный процесс активен и привязан к указанному клиентскому порту. Для получения подробной информации о состоянии в контексте кворума и сведений о клиентских подключениях используйте команду «stat».
imok
  • mntr: Выводит список переменных, которые можно использовать для мониторинга работоспособности кластера.
zk_version      v21.11.1.1-prestable-7a4a0b0edef0ad6e0aa662cd3b90c3f4acf796e7
zk_avg_latency  0
zk_max_latency  0
zk_min_latency  0
zk_packets_received     68
zk_packets_sent 68
zk_num_alive_connections        1
zk_outstanding_requests 0
zk_server_state leader
zk_znode_count  4
zk_watch_count  1
zk_ephemerals_count     0
zk_approximate_data_size        723
zk_open_file_descriptor_count   310
zk_max_file_descriptor_count    10240
zk_followers    0
zk_synced_followers     0
  • srvr: Отображает полную информацию о сервере.
Версия ClickHouse Keeper: v21.11.1.1-prestable-7a4a0b0edef0ad6e0aa662cd3b90c3f4acf796e7
Задержка мин/сред/макс: 0/0/0
Получено: 2
Отправлено: 2
Подключений: 1
Необработанных: 0
Zxid: 34
Режим: leader
Количество узлов: 4
  • stat: Выводит краткую информацию о сервере и подключенных клиентах.
Версия ClickHouse Keeper: v21.11.1.1-prestable-7a4a0b0edef0ad6e0aa662cd3b90c3f4acf796e7
Клиенты:
 192.168.1.1:52852(recved=0,sent=0)
 192.168.1.1:52042(recved=24,sent=48)
Задержка мин/сред/макс: 0/0/0
Получено: 4
Отправлено: 4
Подключений: 1
Необработанных: 0
Zxid: 36
Режим: leader
Количество узлов: 4
  • srst: Сбрасывает статистику сервера. Команда повлияет на результаты srvr, mntr и stat.
Статистика сервера сброшена.
  • conf: Вывести подробные сведения о конфигурации сервиса.
server_id=1
tcp_port=2181
four_letter_word_white_list=*
log_storage_path=./coordination/logs
snapshot_storage_path=./coordination/snapshots
max_requests_batch_size=100
session_timeout_ms=30000
operation_timeout_ms=10000
dead_session_check_period_ms=500
heart_beat_interval_ms=500
election_timeout_lower_bound_ms=1000
election_timeout_upper_bound_ms=2000
reserved_log_items=1000000000000000
snapshot_distance=10000
auto_forwarding=true
shutdown_timeout=5000
startup_timeout=240000
raft_logs_level=information
snapshots_to_keep=3
rotate_log_storage_interval=100000
stale_log_gap=10000
fresh_log_gap=200
max_requests_batch_size=100
quorum_reads=false
force_sync=false
compress_logs=true
compress_snapshots_with_zstd_format=true
configuration_change_tries_count=20
  • cons: Выводит полные сведения о соединениях/сеансах для всех клиентов, подключённых к этому серверу. Включает информацию о количестве полученных/отправленных пакетов, идентификаторе сеанса, задержках выполнения операций, последней выполненной операции и т. д.
 192.168.1.1:52163(recved=0,sent=0,sid=0xffffffffffffffff,lop=NA,est=1636454787393,to=30000,lzxid=0xffffffffffffffff,lresp=0,llat=0,minlat=0,avglat=0,maxlat=0)
 192.168.1.1:52042(recved=9,sent=18,sid=0x0000000000000001,lop=List,est=1636454739887,to=30000,lcxid=0x0000000000000005,lzxid=0x0000000000000005,lresp=1636454739892,llat=0,minlat=0,avglat=0,maxlat=0)
  • crst: Сбросить статистику соединений/сеансов для всех подключений.
Статистика подключений сброшена.
  • envi: Вывести сведения о рабочем окружении сервиса
Environment:
clickhouse.keeper.version=v21.11.1.1-prestable-7a4a0b0edef0ad6e0aa662cd3b90c3f4acf796e7
host.name=ZBMAC-C02D4054M.local
os.name=Darwin
os.arch=x86_64
os.version=19.6.0
cpu.count=12
user.name=root
user.home=/Users/JackyWoo/
user.dir=/Users/JackyWoo/project/jd/clickhouse/cmake-build-debug/programs/
user.tmp=/var/folders/b4/smbq5mfj7578f2jzwn602tt40000gn/T/
  • dirs: Показывает общий размер файлов снапшотов и логов в байтах
snapshot_dir_size: 0
log_dir_size: 3875
  • isro: Проверяет, работает ли сервер в режиме только для чтения. Сервер ответит ro, если он в режиме только для чтения, или rw, если режим только для чтения не включён.
rw
  • wchs: Выводит краткую сводную информацию о наблюдениях на сервере.
1 соединение отслеживает 1 путь
Всего отслеживаемых объектов: 1
  • wchc: Выводит подробную информацию о наблюдениях (watches) на сервере, сгруппированную по сессиям. Возвращает список сессий (подключений) с соответствующими наблюдениями (путями). Обратите внимание: в зависимости от количества наблюдений эта операция может быть ресурсоёмкой (влиять на производительность сервера), поэтому используйте её с осторожностью.
0x0000000000000001
    /clickhouse/task_queue/ddl
  • wchp: Выводит подробную информацию о наблюдениях (watches) для сервера по путям. Результатом является список путей (znode-узлов) с соответствующими сессиями. Обратите внимание: в зависимости от количества наблюдений эта операция может быть ресурсоёмкой (то есть влиять на производительность сервера), используйте её с осторожностью.
/clickhouse/task_queue/ddl
    0x0000000000000001
  • dump: Выводит список незавершённых сессий и эфемерных узлов. Работает только на лидере.
Дамп сессий (2):
0x0000000000000001
0x0000000000000002
Сессии с эфемерными узлами (1):
0x0000000000000001
 /clickhouse/task_queue/ddl
  • csnp: Планирует задачу создания снапшота. Возвращает индекс последнего зафиксированного журнала запланированного снапшота в случае успеха или Failed to schedule snapshot creation task. в случае ошибки. Обратите внимание, что команда lgif может помочь определить, завершено ли создание снапшота.
100
  • lgif: Информация о логе Keeper. first_log_idx : мой первый индекс лога в хранилище логов; first_log_term : мой первый терм лога; last_log_idx : мой последний индекс лога в хранилище логов; last_log_term : мой последний терм лога; last_committed_log_idx : мой последний зафиксированный индекс лога в машине состояний; leader_committed_log_idx : зафиксированный индекс лога лидера в моём представлении; target_committed_log_idx : целевой индекс лога, который должен быть зафиксирован; last_snapshot_idx : максимальный зафиксированный индекс лога в последнем снапшоте.
first_log_idx   1
first_log_term  1
last_log_idx    101
last_log_term   1
last_committed_log_idx  100
leader_committed_log_idx    101
target_committed_log_idx    101
last_snapshot_idx   50
  • rqld: Запрос на избрание новым лидером. Возвращает Sent leadership request to leader. если запрос отправлен, или Failed to send leadership request to leader. если запрос не отправлен. Обратите внимание, что если узел уже является лидером, результат будет таким же, как и при успешной отправке запроса.
Запрос на лидерство отправлен лидеру.
  • ftfl: Отображает список всех feature-флагов и показывает, включены ли они для экземпляра Keeper.
filtered_list   1
multi_read  1
check_not_exists    0
  • ydld: Запрос на передачу лидерства и переход в состояние последователя. Если сервер, получающий запрос, является лидером, он сначала приостановит операции записи, затем дождётся, пока преемник (текущий лидер никогда не может быть преемником) не завершит догон по последним записям журнала, и после этого откажется от лидерства. Преемник будет выбран автоматически. Будет возвращено Sent yield leadership request to leader. если запрос отправлен, или Failed to send yield leadership request to leader. если запрос не был отправлен. Обратите внимание, что если узел уже является последователем, результат будет таким же, как если бы запрос был отправлен.
Отправлен запрос на передачу лидерства лидеру.
  • pfev: Возвращает значения для всех собранных событий. Для каждого события возвращает его имя, значение и описание.
FileOpen        62      Количество открытых файлов.
Seek    4       Количество вызовов функции 'lseek'.
ReadBufferFromFileDescriptorRead        126     Количество операций чтения (read/pread) из файлового дескриптора. Не включает сокеты.
ReadBufferFromFileDescriptorReadFailed  0       Количество неудачных попыток чтения (read/pread) из файлового дескриптора.
ReadBufferFromFileDescriptorReadBytes   178846  Количество байтов, прочитанных из файловых дескрипторов. Если файл сжат, отображается размер сжатых данных.
WriteBufferFromFileDescriptorWrite      7       Количество операций записи (write/pwrite) в файловый дескриптор. Не включает сокеты.
WriteBufferFromFileDescriptorWriteFailed        0       Количество неудачных попыток записи (write/pwrite) в файловый дескриптор.
WriteBufferFromFileDescriptorWriteBytes 153     Количество байтов, записанных в файловые дескрипторы. Если файл сжат, отображается размер сжатых данных.
FileSync        2       Количество вызовов функции F_FULLFSYNC/fsync/fdatasync для файлов.
DirectorySync   0       Количество вызовов функции F_FULLFSYNC/fsync/fdatasync для каталогов.
FileSyncElapsedMicroseconds     12756   Общее время ожидания системного вызова F_FULLFSYNC/fsync/fdatasync для файлов.
DirectorySyncElapsedMicroseconds        0       Общее время ожидания системного вызова F_FULLFSYNC/fsync/fdatasync для каталогов.
ReadCompressedBytes     0       Количество байтов (до декомпрессии), прочитанных из сжатых источников (файлы, сеть).
CompressedReadBufferBlocks      0       Количество сжатых блоков (блоков данных, сжатых независимо друг от друга), прочитанных из сжатых источников (файлы, сеть).
CompressedReadBufferBytes       0       Количество несжатых байтов (после декомпрессии), прочитанных из сжатых источников (файлы, сеть).
AIOWrite        0       Количество операций записи через интерфейс AIO в Linux или FreeBSD
AIOWriteBytes   0       Количество байтов, записанных через интерфейс AIO в Linux или FreeBSD
...

HTTP-контроль

ClickHouse Keeper предоставляет HTTP-интерфейс для проверки готовности реплики к приему трафика. Он может использоваться в облачных средах, таких как Kubernetes.

Пример конфигурации, которая включает конечную точку /ready:

<clickhouse>
    <keeper_server>
        <http_control>
            <port>9182</port>
            <readiness>
                <endpoint>/ready</endpoint>
            </readiness>
        </http_control>
    </keeper_server>
</clickhouse>

Флаги возможностей

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

Пример конфигурации флагов возможностей, которая отключает multi_read и включает check_not_exists:

<clickhouse>
    <keeper_server>
        <feature_flags>
            <multi_read>0</multi_read>
            <check_not_exists>1</check_not_exists>
        </feature_flags>
    </keeper_server>
</clickhouse>

Доступны следующие возможности:

FeatureDescriptionDefault
multi_readПоддержка запроса множественного чтения (read multi)1
filtered_listПоддержка запроса list, который фильтрует результаты по типу узла (эфемерный или постоянный)1
check_not_existsПоддержка запроса CheckNotExists, который проверяет, что узел не существует1
create_if_not_existsПоддержка запроса CreateIfNotExists, который пытается создать узел, если он не существует. Если он уже существует, изменения не применяются и возвращается ZOK1
remove_recursiveПоддержка запроса RemoveRecursive, который удаляет узел вместе с его поддеревом1
Примечание

Начиная с версии 25.7 некоторые флаги функций включены по умолчанию.
Рекомендуемый способ обновления Keeper до версии 25.7+ — сначала обновиться до версии 24.9+.

Миграция с ZooKeeper

Бесшовная миграция с ZooKeeper на ClickHouse Keeper невозможна. Необходимо остановить кластер ZooKeeper, преобразовать данные и запустить ClickHouse Keeper. Утилита clickhouse-keeper-converter позволяет преобразовать журналы и снимки состояния ZooKeeper в снимок состояния ClickHouse Keeper. Она работает только с ZooKeeper > 3.4. Шаги миграции:

  1. Остановите все узлы ZooKeeper.

  2. Необязательно, но рекомендуется: найдите ведущий (leader) узел ZooKeeper, запустите и снова остановите его. Это заставит ZooKeeper создать согласованный снимок состояния.

  3. Запустите clickhouse-keeper-converter на ведущем узле, например:

clickhouse-keeper-converter --zookeeper-logs-dir /var/lib/zookeeper/version-2 --zookeeper-snapshots-dir /var/lib/zookeeper/version-2 --output-dir /path/to/clickhouse/keeper/snapshots
  1. Скопируйте снимок (snapshot) на серверные узлы ClickHouse с настроенным keeper или запустите ClickHouse Keeper вместо ZooKeeper. Снимок должен храниться на всех узлах, иначе пустые узлы могут работать быстрее, и один из них может стать лидером.
Примечание

Инструмент keeper-converter недоступен в отдельном бинарнике Keeper. Если у вас установлен ClickHouse, вы можете использовать этот бинарник напрямую:

clickhouse keeper-converter ...

В противном случае вы можете скачать исполняемый файл и запустить инструмент, как описано выше, без установки ClickHouse.

Восстановление после потери кворума

Поскольку ClickHouse Keeper использует Raft, он может выдерживать определённое количество сбоев узлов в зависимости от размера кластера.
Например, в кластере из 3 узлов он будет продолжать корректную работу, если выйдет из строя только 1 узел.

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

Тем не менее, в ClickHouse Keeper есть режим восстановления, который позволяет принудительно переконфигурировать кластер, используя только один узел. К этому следует прибегать только в самом крайнем случае, если вы не можете заново запустить узлы или развернуть новый экземпляр на том же endpoint.

Важные замечания перед продолжением:

  • Убедитесь, что вышедшие из строя узлы не смогут снова подключиться к кластеру.
  • Не запускайте ни один из новых узлов, пока это не будет явно указано в шагах.

После того как вы убедились, что вышеперечисленные условия соблюдены, выполните следующие действия:

  1. Выберите один узел Keeper в качестве нового лидера. Имейте в виду, что данные этого узла будут использоваться для всего кластера, поэтому рекомендуется выбирать узел с наиболее актуальным состоянием.
  2. Прежде чем что-либо делать, создайте резервную копию каталогов log_storage_path и snapshot_storage_path выбранного узла.
  3. Переконфигурируйте кластер на всех узлах, которые вы планируете использовать.
  4. Отправьте четырёхбуквенную команду rcvr на выбранный узел, что переведёт его в режим восстановления, ИЛИ остановите экземпляр Keeper на выбранном узле и запустите его снова с аргументом --force-recovery.
  5. По одному запускайте экземпляры Keeper на новых узлах, убеждаясь, что mntr возвращает follower в поле zk_server_state перед запуском следующего.
  6. В режиме восстановления ведущий (лидирующий) узел будет возвращать сообщение об ошибке на команду mntr до тех пор, пока не достигнет кворума с новыми узлами, и будет отклонять любые запросы от клиента и ведомых узлов.
  7. После достижения кворума ведущий узел вернётся в нормальный режим работы и начнёт принимать все запросы через Raft — проверьте это с помощью mntr, который должен вернуть leader в поле zk_server_state.

Использование дисков с Keeper

Keeper поддерживает ограниченный набор внешних дисков для хранения снимков, файлов журнала и файла состояния.

Поддерживаемые типы дисков:

  • s3_plain
  • s3
  • local

Ниже приведён пример описаний дисков в файле конфигурации.

<clickhouse>
    <storage_configuration>
        <disks>
            <log_local>
                <type>local</type>
                <path>/var/lib/clickhouse/coordination/logs/</path>
            </log_local>
            <log_s3_plain>
                <type>s3_plain</type>
                <endpoint>https://some_s3_endpoint/logs/</endpoint>
                <access_key_id>ACCESS_KEY</access_key_id>
                <secret_access_key>SECRET_KEY</secret_access_key>
            </log_s3_plain>
            <snapshot_local>
                <type>local</type>
                <path>/var/lib/clickhouse/coordination/snapshots/</path>
            </snapshot_local>
            <snapshot_s3_plain>
                <type>s3_plain</type>
                <endpoint>https://some_s3_endpoint/snapshots/</endpoint>
                <access_key_id>ACCESS_KEY</access_key_id>
                <secret_access_key>SECRET_KEY</secret_access_key>
            </snapshot_s3_plain>
            <state_s3_plain>
                <type>s3_plain</type>
                <endpoint>https://some_s3_endpoint/state/</endpoint>
                <access_key_id>ACCESS_KEY</access_key_id>
                <secret_access_key>SECRET_KEY</secret_access_key>
            </state_s3_plain>
        </disks>
    </storage_configuration>
</clickhouse>

Чтобы использовать диск для логов, параметр конфигурации keeper_server.log_storage_disk должен содержать имя диска. Чтобы использовать диск для снимков (snapshots), параметр конфигурации keeper_server.snapshot_storage_disk должен содержать имя диска. Дополнительно для последних логов и снимков могут использоваться разные диски с помощью параметров keeper_server.latest_log_storage_disk и keeper_server.latest_snapshot_storage_disk соответственно. В этом случае Keeper будет автоматически перемещать файлы на соответствующие диски при создании новых логов или снимков. Чтобы использовать диск для файла состояния, параметр конфигурации keeper_server.state_storage_disk должен содержать имя диска.

Перемещение файлов между дисками безопасно, и нет риска потери данных, даже если Keeper остановится посреди передачи. Пока файл не будет полностью перенесён на новый диск, он не удаляется со старого.

Keeper с параметром keeper_server.coordination_settings.force_sync, установленным в true (true по умолчанию), не может обеспечить некоторые гарантии для всех типов дисков. В данный момент только диски типа local поддерживают надёжный sync на диск. Если используется force_sync, log_storage_disk должен быть диском типа local, если latest_log_storage_disk не используется. Если используется latest_log_storage_disk, он всегда должен быть диском типа local. Если force_sync отключён, диски любых типов могут использоваться в любой конфигурации.

Возможная конфигурация хранилища для экземпляра Keeper может выглядеть следующим образом:

<clickhouse>
    <keeper_server>
        <log_storage_disk>log_s3_plain</log_storage_disk>
        <latest_log_storage_disk>log_local</latest_log_storage_disk>

        <snapshot_storage_disk>snapshot_s3_plain</snapshot_storage_disk>
        <latest_snapshot_storage_disk>snapshot_local</latest_snapshot_storage_disk>
    </keeper_server>
</clickhouse>

Этот экземпляр будет хранить все логи, кроме последних, на диске log_s3_plain, а последние логи — на диске log_local. Такая же логика применяется к снапшотам: все, кроме последних снапшотов, будут храниться на snapshot_s3_plain, а последний снапшот — на диске snapshot_local.

Изменение конфигурации дисков

Справочные материалы

Перед применением новой конфигурации дисков вручную создайте резервную копию всех логов и снапшотов Keeper.

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

Если необходимо перенести файлы на полностью новый диск (или перейти с конфигурации с двумя дисками на конфигурацию с одним диском), можно использовать несколько определений параметров keeper_server.old_snapshot_storage_disk и keeper_server.old_log_storage_disk.

Следующая конфигурация показывает, как можно перейти с предыдущей конфигурации с двумя дисками на полностью новую конфигурацию с одним диском:

<clickhouse>
    <keeper_server>
        <old_log_storage_disk>log_local</old_log_storage_disk>
        <old_log_storage_disk>log_s3_plain</old_log_storage_disk>
        <log_storage_disk>log_local2</log_storage_disk>

        <old_snapshot_storage_disk>snapshot_s3_plain</old_snapshot_storage_disk>
        <old_snapshot_storage_disk>snapshot_local</old_snapshot_storage_disk>
        <snapshot_storage_disk>snapshot_local2</snapshot_storage_disk>
    </keeper_server>
</clickhouse>

При запуске все файлы журналов будут перемещены с дисков log_local и log_s3_plain на диск log_local2. Кроме того, все файлы снимков состояния будут перемещены с дисков snapshot_local и snapshot_s3_plain на диск snapshot_local2.

Настройка кэша логов

Чтобы минимизировать объём данных, читаемых с диска, Keeper кэширует записи журнала в памяти. Если запросы большие, журнальные записи будут занимать слишком много памяти, поэтому объём кэшируемых логов ограничен. Этот предел настраивается с помощью следующих двух конфигурационных параметров:

  • latest_logs_cache_size_threshold — общий размер последних логов, хранящихся в кэше
  • commit_logs_cache_size_threshold — общий размер следующих по порядку логов, которые предстоит закоммитить

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

Примечание

Вы можете использовать команду pfev, чтобы проверить объём логов, прочитанных из каждого кэша и из файла. Также вы можете использовать метрики с эндпоинта Prometheus для отслеживания текущего размера обоих кэшей.

Prometheus

Keeper может предоставлять метрики для сбора с помощью Prometheus.

Настройки:

  • endpoint – HTTP-эндпоинт для сбора метрик сервером Prometheus. Должен начинаться с '/'.
  • port – Порт для endpoint.
  • metrics – Флаг, включающий экспорт метрик из таблицы system.metrics.
  • events – Флаг, включающий экспорт метрик из таблицы system.events.
  • asynchronous_metrics – Флаг, включающий экспорт текущих значений метрик из таблицы system.asynchronous_metrics.

Пример

<clickhouse>
    <listen_host>0.0.0.0</listen_host>
    <http_port>8123</http_port>
    <tcp_port>9000</tcp_port>
    <!-- highlight-start -->
    <prometheus>
        <endpoint>/metrics</endpoint>
        <port>9363</port>
        <metrics>true</metrics>
        <events>true</events>
        <asynchronous_metrics>true</asynchronous_metrics>
    </prometheus>
    <!-- highlight-end -->
</clickhouse>

Проверьте (замените 127.0.0.1 на IP-адрес или имя хоста сервера ClickHouse):

curl 127.0.0.1:9363/metrics

См. также раздел ClickHouse Cloud Интеграция с Prometheus.

Руководство пользователя ClickHouse Keeper

В этом руководстве приведены простые и минимальные настройки для конфигурации ClickHouse Keeper с примером проверки распределённых операций. Пример выполняется с использованием 3 узлов под управлением Linux.

1. Настройка узлов с параметрами Keeper

  1. Установите 3 экземпляра ClickHouse на 3 хоста (chnode1, chnode2, chnode3). (См. раздел Быстрый старт для получения подробной информации по установке ClickHouse.)

  2. На каждом узле добавьте следующую запись, чтобы разрешить внешние подключения через сетевой интерфейс.

    <listen_host>0.0.0.0</listen_host>
    
  3. Добавьте следующую конфигурацию ClickHouse Keeper на все три сервера, обновив параметр <server_id> для каждого сервера; для chnode1 он будет 1, для chnode22 и т. д.

    <keeper_server>
        <tcp_port>9181</tcp_port>
        <server_id>1</server_id>
        <log_storage_path>/var/lib/clickhouse/coordination/log</log_storage_path>
        <snapshot_storage_path>/var/lib/clickhouse/coordination/snapshots</snapshot_storage_path>
    
        <coordination_settings>
            <operation_timeout_ms>10000</operation_timeout_ms>
            <session_timeout_ms>30000</session_timeout_ms>
            <raft_logs_level>warning</raft_logs_level>
        </coordination_settings>
    
        <raft_configuration>
            <server>
                <id>1</id>
                <hostname>chnode1.domain.com</hostname>
                <port>9234</port>
            </server>
            <server>
                <id>2</id>
                <hostname>chnode2.domain.com</hostname>
                <port>9234</port>
            </server>
            <server>
                <id>3</id>
                <hostname>chnode3.domain.com</hostname>
                <port>9234</port>
            </server>
        </raft_configuration>
    </keeper_server>
    

    Ниже приведены базовые настройки, использованные выше:

    ParameterDescriptionExample
    tcp_portпорт, используемый клиентами Keeper9181 — значение по умолчанию, аналогичное 2181 в ZooKeeper
    server_idидентификатор для каждого сервера ClickHouse Keeper, используемый в конфигурации Raft1
    coordination_settingsсекция с параметрами, такими как тайм-аутытайм-ауты: 10000, уровень логирования: trace
    serverопределение сервера-участникасписок определений каждого сервера
    raft_configurationнастройки для каждого сервера в кластере Keeperсервер и настройки для каждого
    idчисловой идентификатор сервера для сервисов Keeper1
    hostnameимя хоста (hostname), IP-адрес или FQDN каждого сервера в кластере Keeperchnode1.domain.com
    portпорт для прослушивания межсерверных подключений Keeper9234
  4. Включите компонент Zookeeper. Он будет использовать движок ClickHouse Keeper:

        <zookeeper>
            <node>
                <host>chnode1.domain.com</host>
                <port>9181</port>
            </node>
            <node>
                <host>chnode2.domain.com</host>
                <port>9181</port>
            </node>
            <node>
                <host>chnode3.domain.com</host>
                <port>9181</port>
            </node>
        </zookeeper>
    

    Ниже приведены базовые настройки, использованные выше:

    ParameterDescriptionExample
    nodeсписок узлов для подключений ClickHouse Keeperзапись настроек для каждого сервера
    hostимя хоста (hostname), IP-адрес или FQDN каждого узла ClickHouse Keeperchnode1.domain.com
    portклиентский порт ClickHouse Keeper9181
  5. Перезапустите ClickHouse и убедитесь, что каждый экземпляр Keeper запущен. Выполните следующую команду на каждом сервере. Команда ruok возвращает imok, если Keeper запущен и находится в исправном состоянии:

    # echo ruok | nc localhost 9181; echo
    imok
    
  6. В базе данных system есть таблица с именем zookeeper, которая содержит сведения о ваших экземплярах ClickHouse Keeper. Посмотрим содержимое таблицы:

    SELECT *
    FROM system.zookeeper
    WHERE path IN ('/', '/clickhouse')
    

Таблица выглядит так:

┌─name───────┬─value─┬─czxid─┬─mzxid─┬───────────────ctime─┬───────────────mtime─┬─version─┬─cversion─┬─aversion─┬─ephemeralOwner─┬─dataLength─┬─numChildren─┬─pzxid─┬─path────────┐
│ clickhouse │       │   124 │   124 │ 2022-03-07 00:49:34 │ 2022-03-07 00:49:34 │       0 │        2 │        0 │              0 │          0 │           2 │  5693 │ /           │
│ task_queue │       │   125 │   125 │ 2022-03-07 00:49:34 │ 2022-03-07 00:49:34 │       0 │        1 │        0 │              0 │          0 │           1 │   126 │ /clickhouse │
│ tables     │       │  5693 │  5693 │ 2022-03-07 00:49:34 │ 2022-03-07 00:49:34 │       0 │        3 │        0 │              0 │          0 │           3 │  6461 │ /clickhouse │
└────────────┴───────┴───────┴───────┴─────────────────────┴─────────────────────┴─────────┴──────────┴──────────┴────────────────┴────────────┴─────────────┴───────┴─────────────┘

2. Настройте кластер в ClickHouse

  1. Настроим простой кластер с 2 шардами и только одной репликой на 2 из узлов. Третий узел будет использоваться для достижения кворума, требуемого в ClickHouse Keeper. Обновите конфигурацию на chnode1 и chnode2. Следующий кластер определяет по 1 шарду на каждом узле, всего 2 шарда без репликации. В этом примере часть данных будет находиться на одном узле, а часть — на другом:

        <remote_servers>
            <cluster_2S_1R>
                <shard>
                    <replica>
                        <host>chnode1.domain.com</host>
                        <port>9000</port>
                        <user>default</user>
                        <password>ClickHouse123!</password>
                    </replica>
                </shard>
                <shard>
                    <replica>
                        <host>chnode2.domain.com</host>
                        <port>9000</port>
                        <user>default</user>
                        <password>ClickHouse123!</password>
                    </replica>
                </shard>
            </cluster_2S_1R>
        </remote_servers>
    
    ParameterDescriptionExample
    shardсписок реплик в определении кластерасписок реплик для каждого шарда
    replicaсписок настроек для каждой репликизаписи настроек для каждой реплики
    hosthostname, IP или FQDN сервера, на котором будет размещаться реплика шардаchnode1.domain.com
    portпорт, используемый для связи через нативный tcp‑протокол9000
    userимя пользователя, которое будет использоваться для аутентификации в экземплярах кластераdefault
    passwordпароль для пользователя, определённого для разрешения подключений к экземплярам кластераClickHouse123!
  2. Перезапустите ClickHouse и убедитесь, что кластер был создан:

    SHOW clusters;
    

    Вы должны увидеть свой кластер:

    ┌─cluster───────┐
    │ cluster_2S_1R │
    └───────────────┘
    

3. Создайте и протестируйте распределённую таблицу

  1. Создайте новую базу данных на новом кластере, используя ClickHouse client на chnode1. Оператор ON CLUSTER автоматически создаёт базу данных на обоих узлах.

    CREATE DATABASE db1 ON CLUSTER 'cluster_2S_1R';
    
  2. Создайте новую таблицу в базе данных db1. Как и раньше, ON CLUSTER создаёт таблицу на обоих узлах.

    CREATE TABLE db1.table1 on cluster 'cluster_2S_1R'
    (
        `id` UInt64,
        `column1` String
    )
    ENGINE = MergeTree
    ORDER BY column1
    
  3. На узле chnode1 добавьте пару строк:

    INSERT INTO db1.table1
        (id, column1)
    VALUES
        (1, 'abc'),
        (2, 'def')
    
  4. Добавьте пару строк на узле chnode2:

    INSERT INTO db1.table1
        (id, column1)
    VALUES
        (3, 'ghi'),
        (4, 'jkl')
    
  5. Обратите внимание, что выполнение запроса SELECT на каждом узле показывает только данные, находящиеся на этом узле. Например, на chnode1:

    SELECT *
    FROM db1.table1
    
    Query id: 7ef1edbc-df25-462b-a9d4-3fe6f9cb0b6d
    
    ┌─id─┬─column1─┐
    │  1 │ abc     │
    │  2 │ def     │
    └────┴─────────┘
    
    2 rows in set. Elapsed: 0.006 sec.
    

    На chnode2:

  6. SELECT *
    FROM db1.table1
    
    Query id: c43763cc-c69c-4bcc-afbe-50e764adfcbf
    
    ┌─id─┬─column1─┐
    │  3 │ ghi     │
    │  4 │ jkl     │
    └────┴─────────┘
    
  7. Вы можете создать таблицу Distributed, которая будет представлять данные на двух шардах. Таблицы с движком Distributed не хранят собственные данные, но обеспечивают распределённую обработку запросов по нескольким серверам. Чтения выполняются по всем шардам, а записи могут распределяться между шардами. Выполните следующий запрос на chnode1:

    CREATE TABLE db1.dist_table (
        id UInt64,
        column1 String
    )
    ENGINE = Distributed(cluster_2S_1R,db1,table1)
    
  8. Обратите внимание, что запрос к dist_table возвращает все четыре строки данных с двух шардов:

    SELECT *
    FROM db1.dist_table
    
    Query id: 495bffa0-f849-4a0c-aeea-d7115a54747a
    
    ┌─id─┬─column1─┐
    │  1 │ abc     │
    │  2 │ def     │
    └────┴─────────┘
    ┌─id─┬─column1─┐
    │  3 │ ghi     │
    │  4 │ jkl     │
    └────┴─────────┘
    
    4 rows in set. Elapsed: 0.018 sec.
    

Итоги

В этом руководстве показано, как настроить кластер с использованием ClickHouse Keeper. С ClickHouse Keeper вы можете настраивать кластеры и создавать распределённые таблицы, которые могут реплицироваться по шардам.

Настройка ClickHouse Keeper с уникальными путями

Not supported in ClickHouse Cloud
Примечание

This page is not applicable to ClickHouse Cloud. The procedure documented here is automated in ClickHouse Cloud services.

Описание

В этой статье описывается, как использовать встроенную настройку макроса {uuid} для создания уникальных записей в ClickHouse Keeper или ZooKeeper. Уникальные пути полезны при частом создании и удалении таблиц, поскольку это позволяет избежать ожидания в течение нескольких минут, пока сборщик мусора Keeper удалит записи путей: каждый раз при создании пути в нём используется новый uuid, пути никогда не переиспользуются.

Пример окружения

Кластер из трёх узлов, который будет настроен таким образом, что ClickHouse Keeper будет работать на всех трёх узлах, а ClickHouse — на двух из этих узлов. Это обеспечивает три узла для ClickHouse Keeper (включая узел-арбитр) и один шард ClickHouse, состоящий из двух реплик.

nodedescription
chnode1.marsnet.localузел данных — кластер cluster_1S_2R
chnode2.marsnet.localузел данных — кластер cluster_1S_2R
chnode3.marsnet.localузел-арбитр ClickHouse Keeper

Пример конфигурации для кластера:

    <remote_servers>
        <cluster_1S_2R>
            <shard>
                <replica>
                    <host>chnode1.marsnet.local</host>
                    <port>9440</port>
                    <user>default</user>
                    <password>ClickHouse123!</password>
                    <secure>1</secure>
                </replica>
                <replica>
                    <host>chnode2.marsnet.local</host>
                    <port>9440</port>
                    <user>default</user>
                    <password>ClickHouse123!</password>
                    <secure>1</secure>
                </replica>
            </shard>
        </cluster_1S_2R>
    </remote_servers>

Процедуры по настройке таблиц для использования {uuid}

  1. Настройте макросы на каждом сервере
    пример для сервера 1:
    <macros>
        <shard>1</shard>
        <replica>replica_1</replica>
    </macros>
Примечание

Обратите внимание, что мы определяем макросы для shard и replica, но {uuid} здесь не определён — это встроенный параметр, и его не нужно задавать вручную.

  1. Создайте базу данных
CREATE DATABASE db_uuid
      ON CLUSTER 'cluster_1S_2R'
      ENGINE Atomic;
CREATE DATABASE db_uuid ON CLUSTER cluster_1S_2R
ENGINE = Atomic

ID запроса: 07fb7e65-beb4-4c30-b3ef-bd303e5c42b5

┌─host──────────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ chnode2.marsnet.local │ 9440 │      0 │       │                   1 │                0 │
│ chnode1.marsnet.local │ 9440 │      0 │       │                   0 │                0 │
└───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘
  1. Создайте таблицу на кластере, используя макросы и {uuid}
CREATE TABLE db_uuid.uuid_table1 ON CLUSTER 'cluster_1S_2R'
   (
     id UInt64,
     column1 String
   )
   ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/db_uuid/{uuid}', '{replica}' )
   ORDER BY (id);
CREATE TABLE db_uuid.uuid_table1 ON CLUSTER cluster_1S_2R
(
    `id` UInt64,
    `column1` String
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/db_uuid/{uuid}', '{replica}')
ORDER BY id

Query id: 8f542664-4548-4a02-bd2a-6f2c973d0dc4

┌─host──────────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐ │ chnode1.marsnet.local │ 9440 │ 0 │ │ 1 │ 0 │ │ chnode2.marsnet.local │ 9440 │ 0 │ │ 0 │ 0 │ └───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘


4.  Создайте распределённую таблицу

```sql
CREATE TABLE db_uuid.dist_uuid_table1 ON CLUSTER 'cluster_1S_2R'
   (
     id UInt64,
     column1 String
   )
   ENGINE = Distributed('cluster_1S_2R', 'db_uuid', 'uuid_table1' );
CREATE TABLE db_uuid.dist_uuid_table1 ON CLUSTER cluster_1S_2R
(
    `id` UInt64,
    `column1` String
)
ENGINE = Distributed('cluster_1S_2R', 'db_uuid', 'uuid_table1')

Query id: 3bc7f339-ab74-4c7d-a752-1ffe54219c0e

┌─host──────────────────┬─port─┬─status─┬─error─┬─num_hosts_remaining─┬─num_hosts_active─┐
│ chnode2.marsnet.local │ 9440 │      0 │       │                   1 │                0 │
│ chnode1.marsnet.local │ 9440 │      0 │       │                   0 │                0 │
└───────────────────────┴──────┴────────┴───────┴─────────────────────┴──────────────────┘

Тестирование

  1. Добавьте данные на первый узел (например, chnode1)
INSERT INTO db_uuid.uuid_table1
   ( id, column1)
   VALUES
   ( 1, 'abc');
INSERT INTO db_uuid.uuid_table1 (id, column1) FORMAT Values

Идентификатор запроса: 0f178db7-50a6-48e2-9a1b-52ed14e6e0f9

ОК.

Обработана 1 строка. Время выполнения: 0.033 сек.
  1. Запишите данные на второй узел (например, chnode2)
INSERT INTO db_uuid.uuid_table1
   ( id, column1)
   VALUES
   ( 2, 'def');
INSERT INTO db_uuid.uuid_table1 (id, column1) FORMAT Values

Query id: edc6f999-3e7d-40a0-8a29-3137e97e3607

Ok.

Обработана 1 строка. Затрачено: 0.529 сек.
  1. Просмотр записей через распределённую таблицу
SELECT * FROM db_uuid.dist_uuid_table1;
SELECT *
FROM db_uuid.dist_uuid_table1

Query id: 6cbab449-9e7f-40fe-b8c2-62d46ba9f5c8

┌─id─┬─column1─┐
│  1 │ abc     │
└────┴─────────┘
┌─id─┬─column1─┐
│  2 │ def     │
└────┴─────────┘

2 строки в наборе. Затрачено: 0.007 сек.

Альтернативы

Путь репликации по умолчанию можно заранее задать с помощью макросов, включая {uuid}.

  1. Задать значение по умолчанию для таблиц на каждом узле
<default_replica_path>/clickhouse/tables/{shard}/db_uuid/{uuid}</default_replica_path>
<default_replica_name>{replica}</default_replica_name>
Совет

Вы также можете задать макрос {database} на каждом узле, если отдельные узлы используются для конкретных баз данных.

  1. Создайте таблицу без явных параметров:
CREATE TABLE db_uuid.uuid_table1 ON CLUSTER 'cluster_1S_2R'
   (
     id UInt64,
     column1 String
   )
   ENGINE = ReplicatedMergeTree
   ORDER BY (id);
CREATE TABLE db_uuid.uuid_table1 ON CLUSTER cluster_1S_2R
(
    `id` UInt64,
    `column1` String
)
ENGINE = ReplicatedMergeTree
ORDER BY id

ID запроса: ab68cda9-ae41-4d6d-8d3b-20d8255774ee

┌─хост──────────────────┬─порт─┬─статус─┬─ошибка─┬─число_оставшихся_хостов─┬─число_активных_хостов─┐ │ chnode2.marsnet.local │ 9440 │ 0 │ │ 1 │ 0 │ │ chnode1.marsnet.local │ 9440 │ 0 │ │ 0 │ 0 │ └───────────────────────┴──────┴────────┴────────┴───────────────────────────────┴──────────────────────────────┘

2 строки в наборе. Время выполнения: 1.175 сек.


3. Убедитесь, что использованы настройки из конфигурации по умолчанию
```sql
SHOW CREATE TABLE db_uuid.uuid_table1;
SHOW CREATE TABLE db_uuid.uuid_table1

CREATE TABLE db_uuid.uuid_table1
(
    `id` UInt64,
    `column1` String
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/db_uuid/{uuid}', '{replica}')
ORDER BY id

Получена 1 строка. Прошло: 0.003 сек.

Устранение неполадок

Пример команды для получения информации о таблице и UUID:

SELECT * FROM system.tables
WHERE database = 'db_uuid' AND name = 'uuid_table1';

Пример команды для получения информации о таблице в ZooKeeper, содержащей UUID таблицы, указанной выше

SELECT * FROM system.zookeeper
WHERE path = '/clickhouse/tables/1/db_uuid/9e8a3cc2-0dec-4438-81a7-c3e63ce2a1cf/replicas';
Примечание

База данных должна быть типа Atomic. Если вы выполняете обновление с предыдущей версии, то база данных default, скорее всего, имеет тип Ordinary.

Чтобы проверить:

Например,

SELECT name, engine FROM system.databases WHERE name = 'db_uuid';
SELECT
    name,
    engine
FROM system.databases
WHERE name = 'db_uuid'

Query id: b047d459-a1d2-4016-bcf9-3e97e30e49c2

┌─name────┬─engine─┐
│ db_uuid │ Atomic │
└─────────┴────────┘

Результат: 1 строка. Затрачено: 0.004 сек.

Динамическая переконфигурация ClickHouse Keeper

Not supported in ClickHouse Cloud
Примечание

This page is not applicable to ClickHouse Cloud. The procedure documented here is automated in ClickHouse Cloud services.

Описание

ClickHouse Keeper частично поддерживает команду ZooKeeper reconfig для динамической переконфигурации кластера, если параметр keeper_server.enable_reconfiguration включён.

Примечание

Если этот параметр выключен, вы можете переконфигурировать кластер, вручную изменив секцию raft_configuration реплики. Убедитесь, что вы редактируете файлы на всех репликах, так как только лидер применит изменения. В качестве альтернативы вы можете отправить запрос reconfig через любой клиент, совместимый с ZooKeeper.

Виртуальный узел /keeper/config содержит последнюю зафиксированную конфигурацию кластера в следующем формате:

server.id = server_host:server_port[;server_type][;server_priority]
server.id2 = ...
...
  • Каждая запись о сервере располагается на отдельной строке.
  • server_type может иметь значение participant или learner (learner не участвует в выборах лидера).
  • server_priority — неотрицательное целое число, определяющее, какие узлы должны иметь приоритет на выборах лидера. Приоритет 0 означает, что сервер никогда не станет лидером.

Пример:

:) get /keeper/config
server.1=zoo1:9234;participant;1
server.2=zoo2:9234;participant;1
server.3=zoo3:9234;participant;1

Вы можете использовать команду reconfig, чтобы добавлять новые серверы, удалять существующие и изменять их приоритеты. Ниже приведены примеры (с использованием clickhouse-keeper-client):

# Добавление двух новых серверов
reconfig add "server.5=localhost:123,server.6=localhost:234;learner"
# Удаление двух других серверов
reconfig remove "3,4"
# Изменение приоритета существующего сервера на 8
reconfig add "server.5=localhost:5123;participant;8"

Вот несколько примеров для kazoo:

# Добавление двух новых серверов и удаление двух других серверов
reconfig(joining="server.5=localhost:123,server.6=localhost:234;learner", leaving="3,4")

Изменить приоритет существующего сервера на 8

reconfig(joining="server.5=localhost:5123;participant;8", leaving=None)


Серверы в `joining` должны быть указаны в формате сервера, описанном выше. Записи серверов должны разделяться запятыми.
При добавлении новых серверов можно опустить `server_priority` (значение по умолчанию — 1) и `server_type` (значение по умолчанию — `participant`).

Если требуется изменить приоритет существующего сервера, добавьте его в `joining` с целевым приоритетом.
Хост, порт и тип сервера должны совпадать с существующей конфигурацией сервера.

Серверы добавляются и удаляются в порядке их появления в `joining` и `leaving`.
Все обновления из `joining` обрабатываются перед обновлениями из `leaving`.

В реализации переконфигурации Keeper существуют некоторые ограничения:

- Поддерживается только инкрементальная переконфигурация. Запросы с непустым `new_members` отклоняются.

  Реализация ClickHouse Keeper использует API NuRaft для динамического изменения состава участников. NuRaft позволяет
  добавлять или удалять только один сервер за раз. Это означает, что каждое изменение конфигурации
  (каждая часть `joining`, каждая часть `leaving`) должно обрабатываться отдельно. Таким образом, массовая
  переконфигурация недоступна, так как это могло бы ввести конечных пользователей в заблуждение.

  Изменение типа сервера (participant/learner) также невозможно, поскольку это не поддерживается NuRaft, и
  единственным способом было бы удаление и добавление сервера, что опять же могло бы ввести в заблуждение.

- Невозможно использовать возвращаемое значение `znodestat`.
- Поле `from_version` не используется. Все запросы с установленным `from_version` отклоняются.
  Это связано с тем, что `/keeper/config` является виртуальным узлом, то есть он не хранится в
  постоянном хранилище, а генерируется на лету с указанной конфигурацией узла для каждого запроса.
  Это решение было принято, чтобы не дублировать данные, поскольку NuRaft уже хранит эту конфигурацию.
- В отличие от ZooKeeper, отсутствует возможность ожидания переконфигурации кластера путем отправки команды `sync`.
  Новая конфигурация будет _в конечном итоге_ применена, но без гарантий по времени.
- Команда `reconfig` может завершиться неудачей по различным причинам. Можно проверить состояние кластера и убедиться, что обновление
  было применено.

Преобразование одиночного узла Keeper в кластер

Иногда требуется расширить экспериментальный узел Keeper до полноценного кластера. Ниже приведена пошаговая схема, как это сделать для кластера из 3 узлов:

  • ВАЖНО: новые узлы необходимо добавлять партиями, меньшими, чем текущий кворум, иначе они смогут выбрать лидера среди себя. В этом примере узлы добавляются по одному.
  • Для существующего узла Keeper должен быть включён конфигурационный параметр keeper_server.enable_reconfiguration.
  • Запустите второй узел с полной новой конфигурацией кластера Keeper.
  • После его запуска добавьте его к узлу 1 с помощью reconfig.
  • Теперь запустите третий узел и добавьте его с помощью reconfig.
  • Обновите конфигурацию clickhouse-server, добавив туда новый узел Keeper, и перезапустите сервер для применения изменений.
  • Обновите конфигурацию Raft на узле 1 и, при необходимости, перезапустите его.

Чтобы лучше освоить этот процесс, можно воспользоваться репозиторием-песочницей.

Неподдерживаемые функции

Хотя ClickHouse Keeper стремится быть полностью совместимым с ZooKeeper, есть несколько функций, которые в настоящее время не реализованы (разработка продолжается):

  • create не поддерживает возврат объекта Stat
  • create не поддерживает TTL
  • addWatch не работает с постоянными наблюдениями PERSISTENT
  • removeWatch и removeAllWatches не поддерживаются
  • setWatches не поддерживается
  • Создание узлов znode типа CONTAINER не поддерживается
  • Аутентификация по SASL не поддерживается