Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Репликация и отказоустойчивость
replication

Репликация и отказоустойчивость

ReplicatedMergeTree, ZooKeeper/ClickHouse Keeper, кворумы вставки, восстановление после сбоев

Репликация и отказоустойчивость

ReplicatedMergeTree, ZooKeeper/Keeper, кворумы вставки и восстановление после сбоев

#Результат урока

Вы зададите модель отказов, выберете число реплик и семантику подтверждения записи, а затем диагностируете отставание по системным таблицам.

#Обзор репликации в ClickHouse

Обычная репликация ClickHouse асинхронна. Кворум вставки позволяет ждать нужное число реплик для конкретной записи, но не превращает все чтения и операции кластера в линейно согласованные:

  • Данные автоматически копируются на несколько серверов
  • При сбое одного сервера данные доступны с других реплик
  • Консистентность обеспечивается через ZooKeeper или ClickHouse Keeper

Архитектура:

Клиент → [Реплика 1] ←→ ZooKeeper/Keeper ←→ [Реплика 2]
                                    ↓
                              [Реплика 3]

#ReplicatedMergeTree

#Базовый синтаксис

CREATE TABLE events ON CLUSTER cluster_default ( event_time DateTime, user_id UInt64, event_type String ) ENGINE = ReplicatedMergeTree( '/clickhouse/tables/{shard}/events', -- ZooKeeper путь '{replica}' -- Имя реплики ) ORDER BY (event_time, user_id);

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

  1. ZooKeeper path — уникальный путь в ZK для метаданных таблицы
  2. Replica name — уникальное имя реплики в шарде

#Макросы

Макросы подставляются из конфигурации ClickHouse:

<!-- config.xml --> <clickhouse> <macros> <shard>01</shard> <replica>01</replica> </macros> </clickhouse>

Стандартные макросы:

  • {shard} — номер шарда (например, 01)
  • {replica} — номер реплики (например, 01)
  • {database} — имя базы данных
  • {table} — имя таблицы

Пример пути после подстановки:

'/clickhouse/tables/01/events' -- для shard=01, replica=01

#Как работает репликация

  1. Вставка данных:

    • Клиент вставляет данные в одну из реплик
    • Реплика создаёт новую часть данных (part)
    • Информация о части записывается в ZooKeeper
  2. Синхронизация:

    • Другие реплики отслеживают изменения в ZooKeeper
    • Реплики скачивают новые части с исходной реплики
    • После скачивания часть считается реплицированной
  3. Слияние (merge):

    • Фоновый процесс merge работает независимо на каждой реплике
    • Metadata merge координируется через ZooKeeper
Реплика 1 (leader для вставки):
INSERT → Часть 1 → ZooKeeper: "Часть 1 создана"
                          ↓
Реплика 2 (follower):    ← Скачивает Часть 1
Реплика 3 (follower):    ← Скачивает Часть 1

#ZooKeeper vs ClickHouse Keeper

#ZooKeeper

Apache ZooKeeper — распределённая система координации:

<!-- config.xml --> <clickhouse> <zookeeper> <node index="1"> <host>zookeeper-1</host> <port>2181</port> </node> <node index="2"> <host>zookeeper-2</host> <port>2181</port> </node> <node index="3"> <host>zookeeper-3</host> <port>2181</port> </node> </zookeeper> </clickhouse>

Требования:

  • Минимум 3 узла для кворума
  • 5 узлов для рабочей среды, если система должна переживать отказ 2 узлов
  • Низкая задержка между узлами (<10ms)

#ClickHouse Keeper

ClickHouse Keeper — встроенная альтернатива ZooKeeper:

<!-- keeper_config.xml --> <clickhouse> <keeper_server> <tcp_port>9181</tcp_port> <server_id>1</server_id> <coordination_settings> <operation_timeout_ms>10000</operation_timeout_ms> <session_timeout_ms>30000</session_timeout_ms> </coordination_settings> <raft_configuration> <server> <id>1</id> <hostname>keeper-1</hostname> <port>9234</port> </server> <server> <id>2</id> <hostname>keeper-2</hostname> <port>9234</port> </server> <server> <id>3</id> <hostname>keeper-3</hostname> <port>9234</port> </server> </raft_configuration> </keeper_server> </clickhouse>

Преимущества Keeper:

  • Поведение предсказуемо под характерной для ClickHouse нагрузкой
  • Проще развёртывание (входит в состав ClickHouse)
  • Меньше задержка

Когда использовать:

  • Новый кластер → Keeper
  • Существующий ZooKeeper → можно мигрировать

#Кворумы вставки

#insert_quorum

Гарантия записи на несколько реплик перед подтверждением клиенту:

-- Вставка с кворумом INSERT INTO TABLE events SETTINGS insert_quorum = 2 -- Ждать подтверждения от 2 реплик VALUES (...);

Настройки:

  • insert_quorum — минимальное число реплик для подтверждения
  • insert_quorum_timeout — таймаут ожидания (мс)

Пример:

-- Надёжная вставка INSERT INTO events SETTINGS insert_quorum = 2, insert_quorum_timeout = 5000 VALUES (now(), 1, 'click'); -- Если 2 реплики не подтвердят за 5 секунд → ошибка

#select_sequential_consistency

Гарантия чтения актуальных данных:

SELECT * FROM events SETTINGS select_sequential_consistency = 1;

Поведение:

  • ClickHouse ждёт пока реплики догонят лидера
  • Гарантирует чтение последних записанных данных
  • Увеличивает задержку чтения

#Восстановление после сбоев

#Сбой реплики

При сбое одной реплики:

  1. Данные доступны с других реплик
  2. После восстановления реплика автоматически синхронизируется
  3. Отставшие части скачиваются с других реплик

Проверка статуса:

SELECT table, is_readonly, is_session_expired, future_parts, last_queue_update, absolute_delay FROM system.replicas WHERE table = 'events';

Поля:

  • is_readonly — реплика в режиме только для чтения
  • is_session_expired — сессия в ZooKeeper истекла
  • absolute_delay — отставание в секундах

#Потеря ZooKeeper

При потере соединения с ZooKeeper:

  1. Реплики переходят в режим readonly
  2. Вставка данных невозможна
  3. Чтение данных работает

Восстановление:

  1. Восстановить ZooKeeper
  2. ClickHouse автоматически переподключится
  3. Синхронизация продолжится

#Ручное восстановление

-- Перезапуск репликации SYSTEM RESTART REPLICA events; -- Синхронизация реплики SYSTEM SYNC REPLICA events; -- Принудительное восстановление SYSTEM RESTORE REPLICA events;

#Распределённые DDL

#ON CLUSTER

Выполнение DDL на всех узлах кластера:

-- Создание таблицы на всех узлах CREATE TABLE events ON CLUSTER cluster_default ( event_time DateTime, user_id UInt64 ) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/events', '{replica}') ORDER BY (event_time, user_id); -- Изменение на всех узлах ALTER TABLE events ON CLUSTER cluster_default ADD COLUMN country String; -- Удаление на всех узлах DROP TABLE temp_table ON CLUSTER cluster_default;

#Мониторинг DDL

-- Статус выполнения DDL SELECT query, host, exception_code, exception_text, query_finish_time FROM system.distributed_ddl_queue ORDER BY entry DESC;

#Практика проектирования репликации

#1. Количество реплик

Начните не с числа, а с отказа, который система обязана пережить:

2 реплики: есть копия данных, но обслуживание и второй одновременный отказ требуют особого плана
3 реплики: можно выбрать кворум 2 и сохранить запас на обслуживание
Больше реплик: дороже хранение, сеть и операции; оправдание следует из модели отказов

#2. Распределение по стойкам/DC

Стойка A:        Стойка B:
[Реплика 1]      [Реплика 2]
                 ↓
           ZooKeeper (кворум)

Правило: Реплики одного шарда должны быть в разных стойках/DC.

#3. Мониторинг отставания

-- Проверка отставания реплик SELECT table, total_replicas, active_replicas, max_absolute_delay FROM system.replicas WHERE active_replicas < total_replicas;

#4. Избегайте частых мелких вставок

-- Плохо: много мелких вставок INSERT INTO events VALUES (...); -- × 1000 раз -- Хорошо: пакетная вставка INSERT INTO events VALUES (...), (...), ...; -- 1000 строк за раз

#5. Настройка таймаутов

<!-- users.xml --> <clickhouse> <profiles> <default> <insert_quorum>2</insert_quorum> <insert_quorum_timeout>5000</insert_quorum_timeout> <select_sequential_consistency>0</select_sequential_consistency> </default> </profiles> </clickhouse>

#Диагностика проблем

#Проверка репликации

-- Статус реплик SELECT database, table, total_replicas, active_replicas, is_readonly, is_session_expired, absolute_delay FROM system.replicas; -- Очередь репликации SELECT table, position, node_name, required_quorum, is_currently_executing FROM system.replication_queue; -- Части таблиц SELECT table, partition, name, active, level, bytes_on_disk FROM system.parts WHERE active = 1 ORDER BY partition;

#Частые проблемы

1. Отставание реплики:

-- Проверка отставания SELECT table, absolute_delay FROM system.replicas WHERE absolute_delay > 60; -- Решение: проверить сеть, нагрузку на диск

2. Session expired:

-- Проверка сессии SELECT table, is_session_expired FROM system.replicas WHERE is_session_expired = 1; -- Решение: проверить ZooKeeper, переподключить реплику

3. Readonly режим:

-- Проверка readonly SELECT table, is_readonly FROM system.replicas WHERE is_readonly = 1; -- Решение: проверить ZooKeeper, права доступа

#Практика: отставание реплики

На учебном кластере остановите одну реплику, продолжите контролируемые вставки и запишите симптомы в system.replicas и system.replication_queue. Верните реплику, измерьте время схождения и проверьте контрольные агрегаты. До остановки задайте безопасную границу эксперимента и команду возврата.

Репликация сохраняет копии одних и тех же данных. Шардирование, которому посвящён следующий урок, делит данные между узлами и меняет цену распределённого запроса.

Далее: Шардирование и распределённые запросы