При зростанні обсягів даних 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+ успішних проектів — довіртеся професіоналам. Зв'яжіться з нами для оцінки вашого проекту.







