При росте объёмов данных ClickHouse на одной ноде перестаёт справляться: запросы замедляются, отказ одной ноды приводит к недоступности всей аналитики. Типичная ситуация — 10 млн записей в день, когда CPU упирается в 100%, а дисковый I/O становится узким местом. Таблица размером 2 ТБ, запросы к которой занимают минуты — не редкость. Мы регулярно сталкиваемся с такими задачами и помогаем клиентам развернуть отказоустойчивый кластер с репликацией (ReplicatedMergeTree) и шардированием (Distributed таблицы). Это не две разные концепции, а взаимодополняющие механизмы, которые мы настраиваем под ваши нагрузки. Наш опыт — более 50 успешных проектов, в том числе с нагрузкой до 1 млн вставок в секунду.
Типичная продакшн-схема — 2–3 шарда по 2 реплики, итого 4–6 нод ClickHouse плюс отдельный кластер ClickHouse Keeper для координации. Такая конфигурация обеспечивает отказоустойчивость (выход из строя одной ноды не влияет на доступность) и горизонтальное масштабирование запросов. При вставке 100 тыс. строк в секунду кластер из 4 нод обрабатывает нагрузку с задержкой менее 50 мс.
Мы берём на себя проектирование топологии, развёртывание, настройку репликации и тестирование под нагрузкой. Результат — стабильный кластер, готовый к продакшену, с гарантией отказоустойчивости. Оценим ваш проект в течение одного дня. Получите консультацию по конфигурации.
Почему мы рекомендуем ClickHouse Keeper вместо ZooKeeper?
ClickHouse Keeper — встроенная замена ZooKeeper, доступная с версии 22.4. Он не требует отдельного Java-процесса, проще в эксплуатации и быстрее восстанавливается. По нашим тестам, время восстановления после сбоя сокращается в 3 раза, а затраты на инфраструктуру снижаются на 40%. Конфигурация Keeper задаётся в config.d/keeper.xml на трёх нодах:
<clickhouse>
<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>
<raft_configuration>
<server>
<id>1</id>
<hostname>ch-keeper1.internal</hostname>
<port>9234</port>
</server>
<server>
<id>2</id>
<hostname>ch-keeper2.internal</hostname>
<port>9234</port>
</server>
<server>
<id>3</id>
<hostname>ch-keeper3.internal</hostname>
<port>9234</port>
</server>
</raft_configuration>
</keeper_server>
</clickhouse>Кворум из трёх нод гарантирует работу кластера при отказе одной из них. Используйте Keeper для новых проектов — это упрощает администрирование и экономит ресурсы.
Как описать топологию кластера?
Топология задаётся в config.d/cluster.xml на каждой ноде. Пример для двух шардов с двумя репликами и интеграцией с Keeper:
<clickhouse>
<remote_servers>
<production_cluster>
<shard>
<internal_replication>true</internal_replication>
<replica>
<host>ch-shard1-replica1.internal</host>
<port>9000</port>
</replica>
<replica>
<host>ch-shard1-replica2.internal</host>
<port>9000</port>
</replica>
</shard>
<shard>
<internal_replication>true</internal_replication>
<replica>
<host>ch-shard2-replica1.internal</host>
<port>9000</port>
</replica>
<replica>
<host>ch-shard2-replica2.internal</host>
<port>9000</port>
</replica>
</shard>
</production_cluster>
</remote_servers>
<zookeeper>
<node>
<host>ch-keeper1.internal</host>
<port>9181</port>
</node>
<node>
<host>ch-keeper2.internal</host>
<port>9181</port>
</node>
<node>
<host>ch-keeper3.internal</host>
<port>9181</port>
</node>
</zookeeper>
<macros>
<cluster>production_cluster</cluster>
<shard>01</shard>
<replica>ch-shard1-replica1</replica>
</macros>
</clickhouse>macros — макросы, уникальные для каждой ноды. Они подставляются в DDL-запросах, что исключает дублирование кода. Закажите оценку вашего проекта.
ReplicatedMergeTree: репликация данных
Для создания реплицируемой таблицы используем ReplicatedMergeTree:
CREATE TABLE events ON CLUSTER production_cluster (
event_date Date,
event_time DateTime,
user_id UInt64,
event_type String,
properties String
) ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/events', '{replica}')
PARTITION BY toYYYYMM(event_date)
ORDER BY (event_type, user_id, event_time)
SETTINGS index_granularity = 8192;Путь в Keeper содержит {shard} и {replica}, которые автоматически заменяются значениями из macros. ON CLUSTER выполняет DDL на всех нодах. Каждая реплика хранит полный набор данных шарда. При вставке на одну реплику данные асинхронно копируются на другую. Запрос SELECT можно направлять на любую реплику.
Distributed таблица: шардирование запросов
Distributed таблица — это прокси, не хранящее данные:
CREATE TABLE events_distributed ON CLUSTER production_cluster AS events
ENGINE = Distributed(production_cluster, default, events, rand());rand() — функция шардирования. Для детерминированного распределения используйте cityHash64(user_id). При SELECT запрос выполняется на всех шардах параллельно, результаты агрегируются на координаторе. Это ключевой момент для производительности: запрос к 6 нодам выполняется до 4 раз быстрее, чем на одной.
Какую стратегию вставки выбрать?
| Стратегия | Преимущества | Недостатки |
|---|---|---|
| Через Distributed | Простота, не требует логики на стороне приложения | Дополнительный сетевой хоп, риск потери данных при сбое координатора |
| Прямая вставка в шард | Надёжность, минимальная нагрузка на сеть | Сложнее в реализации, требуется балансировка |
Для высоких нагрузок (более 50 тыс. вставок/с) мы предпочитаем прямую вставку с балансировкой через ClickHouse Load Balancer.
Диагностика и устранение отставаний репликации
Мониторинг через системные таблицы:
-- Очередь репликации
SELECT database, table, num_replicas_delay, last_exception
FROM system.replicas
WHERE last_exception != '';
-- Размер очереди на каждой реплике
SELECT database, table, queue_size, absolute_delay
FROM system.replicas
ORDER BY absolute_delay DESC;
-- Состояние кластера
SELECT *
FROM system.clusters
WHERE cluster = 'production_cluster';absolute_delay выше 300 секунд — реплика отстаёт. Причины: перегруженный диск, сетевые задержки, большие части данных. Решение — увеличить количество потоков репликации (max_replicated_mutations_in_queue) или оптимизировать партиционирование.
Что делать при отставании реплики?
Проверьте загрузку диска, сетевые задержки и размер вставляемых данных. Увеличьте количество потоков репликации или оптимизируйте схему партиционирования. Если проблема системная, рассмотрите переход на ClickHouse Keeper.Как предотвратить split brain при недоступности Keeper?
Если Keeper недоступен, ReplicatedMergeTree переходит в read-only режим. Вставки блокируются. Именно поэтому Keeper должен быть кластером из 3 нод. При отказе одной из них кворум сохраняется, и кластер продолжает работу. Мы гарантируем, что ваш кластер будет спроектирован с учётом этих рисков.
Что входит в нашу работу?
- Аудит текущей инфраструктуры и проектирование топологии.
- Развёртывание ClickHouse Keeper и настройка репликации.
- Создание Distributed таблиц и оптимизация шардирования.
- Нагрузочное тестирование и настройка мониторинга (Prometheus + Grafana).
- Документация по эксплуатации и обучение команды.
- Поддержка после запуска (опционально).
Процесс работы
- Аналитика: сбор требований по нагрузке и доступности.
- Проектирование: выбор количества шардов, реплик, стратегии вставки.
- Реализация: развёртывание кластера, настройка конфигураций, создание таблиц.
- Тестирование: проверка репликации, failover, производительности.
- Деплой: ввод в эксплуатацию, передача документации.
Сроки ориентировочно
| Конфигурация | Сроки |
|---|---|
| 2 шарда × 2 реплики, новая установка | 4–7 дней |
| Миграция данных на кластер | +3–5 дней |
| Оптимизация существующего кластера | 3–5 дней |
Стоимость рассчитывается индивидуально. Более 5 лет опыта развёртывания ClickHouse, 50+ успешных проектов — доверьтесь профессионалам. Свяжитесь с нами для оценки вашего проекта.







