Learning Platform
Глоссарий Troubleshooting
Урок 10.01 · 35 мин
Продвинутый
ReplicatedMergeTreeClickHouse KeeperRaftрепликация

ReplicatedMergeTree и ClickHouse Keeper

ReplicatedMergeTree — движок, который превращает обычную MergeTree-таблицу в реплицируемую. Он не работает сам по себе: для координации всех реплик требуется внешний сервис — ClickHouse Keeper. Keeper хранит метаданные репликации, координирует DDL-операции и отслеживает состояние каждой реплики. Без Keeper ReplicatedMergeTree не может принять ни одну запись.


Что хранит Keeper

Keeper организует данные в иерархию znodes — аналог ZooKeeper-узлов. Каждая реплицируемая таблица получает собственное поддерево в Keeper.

Иерархия znodes Keeper для реплицируемой таблицы
/clickhouseКорень: /clickhouse — стандартный префикс для всех ClickHouse-объектов в Keeper. Изменяется через параметр path в CREATE TABLE. Для изоляции нескольких кластеров используют разные корневые пути.
/clickhouse/tables/{shard}/db/events_localУровень шарда: /clickhouse/tables/{shard}/{db}/{table} — znode таблицы. Макрос {shard} подставляется из конфига сервера (<macros><shard>). Каждый шард имеет независимое дерево. КРИТИЧНО: два шарда не должны иметь одинаковый путь.
log/log/ — основной журнал репликации. Записи типа GET_PART, MERGE_PARTS, MUTATE_PART, ALTER_METADATA создаются здесь и читаются всеми репликами. Формат: log-0000000001, log-0000000002...
replicas/replicas/ — поддерево состояния каждой реплики. Содержит: is_active (сессия Keeper), queue (очередь задач реплики), min_unprocessed_insert_time, last_queue_update. Каждая реплика видит очереди других реплик.
blocks/blocks/ — дедупликация вставок. Каждый блок данных имеет уникальный хеш. ClickHouse проверяет Keeper перед записью: если такой хеш уже есть — вставка пропускается (idempotency). Окно: replicated_deduplication_window (по умолчанию 10000 в 26.3).
mutations/mutations/ — список мутаций (ALTER UPDATE/DELETE). Каждая мутация получает уникальный mutation_id. Реплики применяют мутации в том же порядке. Статус мутации: is_done флаг на всех репликах.

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

ReplicatedMergeTree принимает два параметра: путь в Keeper и имя реплики. В production оба параметра задаются через макросы сервера, а не жёстко прописываются.

-- Создание ReplicatedMergeTree с макросами (production-паттерн)
CREATE TABLE events_local
(
    event_time   DateTime,
    user_id      UInt64,
    event_type   LowCardinality(String),
    properties   String
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/db/events_local', '{replica}')
PARTITION BY toYYYYMM(event_time)
ORDER BY (event_type, user_id, event_time);

Макросы {'{shard}'} и {'{replica}'} подставляются из секции <macros> конфига сервера. Первый параметр — путь в Keeper (одинаковый для всех реплик одного шарда), второй — уникальное имя реплики на каждом узле.

WARNING

Если два шарда имеют одинаковый путь в Keeper (например, оба используют жёстко прописанный /clickhouse/tables/01/db/events), они начнут реплицировать данные друг другу как одна таблица. Это катастрофическая ошибка конфигурации. Всегда используйте макрос {'{shard}'} в пути.


Конфигурация Keeper на сервере ClickHouse

Каждый ClickHouse-сервер подключается к Keeper через секцию <zookeeper> в конфиге. Порт 9181 — клиентское соединение (не путать с 9234 — Raft-протокол между узлами Keeper).

<!-- /etc/clickhouse-server/config.d/keeper.xml -->
<clickhouse>
    <!-- Keeper client: порт 9181 -->
    <zookeeper>
        <node>
            <host>keeper-01</host>
            <port>9181</port>
        </node>
        <node>
            <host>keeper-02</host>
            <port>9181</port>
        </node>
        <node>
            <host>keeper-03</host>
            <port>9181</port>
        </node>
    </zookeeper>

    <!-- Макросы: подставляются в путь Keeper и имя реплики -->
    <macros>
        <shard>01</shard>
        <replica>clickhouse-01</replica>
    </macros>
</clickhouse>
TIP

Порт 9181 — это клиентский порт Keeper, который используют ClickHouse-серверы. Порт 9234 — Raft-протокол, который Keeper-узлы используют для общения между собой при выборах лидера. Firewall должен открыть оба: 9181 от CH-серверов к Keeper, 9234 между Keeper-узлами.


Диаграмма состояний реплики

Состояние реплики и журнал репликации
ActiveActive: реплика полностью синхронизирована, принимает записи и читает данные. Нормальное рабочее состояние. Фоновые merge/fetch/mutate выполняются по расписанию.
network / Keeper unavail
ReadOnlyReadOnly: реплика потеряла связь с Keeper (ZooKeeper session expired) или превысила max_replicated_merges_in_queue. Только чтение, запись заблокирована. Проверить: SELECT * FROM system.replicas WHERE is_readonly=1.
Keeper restored
RecoveringRecovering: реплика восстанавливается после сбоя. Выполняет GET_PART: скачивает отсутствующие части от других реплик. SYSTEM RESTORE REPLICA принудительно переводит в recovering из broken state.
queue empty
ActiveActive (вернулась): очередь репликации опустела, все части синхронизированы. SYSTEM SYNC REPLICA ожидает полной синхронизации — используется для проверки после восстановления.
GET_PARTGET_PART: скачать часть (part) от другой реплики. Возникает когда реплика отстала и у неё нет части которую другие уже имеют. Самый частый тип entry. Источник: system.replication_queue WHERE type='GET_PART'.
MERGE_PARTSMERGE_PARTS: выполнить слияние частей (merge). Координируется через Keeper: одна реплика выигрывает право делать merge, остальные GET_PART результат. Избегает дублирования merge-работы.
MUTATE_PARTMUTATE_PART: применить мутацию (ALTER TABLE UPDATE/DELETE) к части. Тяжёлая операция: перезаписывает данные. Координируется через Keeper, последовательная нумерация mutation_id.
DROP_RANGEDROP_RANGE: удалить части в указанном диапазоне партиции. Возникает при ALTER TABLE DROP PARTITION или TTL. Все реплики синхронно удаляют указанный диапазон.
REPLACE_RANGEREPLACE_RANGE: заменить диапазон частей новыми (ATTACH PARTITION FROM). Используется при перемещении партиций между таблицами или кластерами.
ALTER_METADATAALTER_METADATA: применить изменение схемы (ADD/DROP COLUMN, MODIFY). DDL-изменение синхронизируется через Keeper. Все реплики применяют одно и то же ALTER.

Ключевые выводы

  1. ReplicatedMergeTree требует Keeper для работы — без Keeper все вставки завершаются ошибкой сессии.
  2. Keeper хранит журнал репликации, состояние реплик, блоки дедупликации и метаданные мутаций в иерархии znodes.
  3. Путь в Keeper должен содержать макрос {'{shard}'} для изоляции шардов — иначе разные шарды начнут реплицироваться как одна таблица.
  4. Макросы {'{shard}'} и {'{replica}'} подставляются из <macros> в конфиге каждого ClickHouse-сервера.
  5. ClickHouse-серверы подключаются к Keeper по порту 9181 (клиентский), Keeper-узлы общаются между собой по 9234 (Raft).
Physical Streaming Replication в PostgreSQL: WAL по сети Streaming: event time, watermarks, windows

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 4. Разработчик создал ReplicatedMergeTree на двух шардах с одинаковым путём в Keeper: '/clickhouse/tables/events_local'. Оба шарда используют разные значения макроса {replica}, но {shard} не включён в путь. Что произойдёт?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 11