Масштабирование кластера ClickHouse по горизонтали включает добавление дополнительных узлов для увеличения ёмкости хранилища, производительности запросов и отказоустойчивости. Это позволяет системе эффективно обрабатывать большие наборы данных и большее количество одновременных запросов.

1. Методы масштабирования ClickHouse по горизонтали

ClickHouse поддерживает две основные стратегии горизонтального масштабирования:

Стратегия масштабированияОписаниеЛучшее применение
Шардинг (Добавление новых шардов)Разделяет данные по новым узламБольшие наборы данных, высокая пропускная способность для записи
Репликация (Добавление новых реплик)Копирует данные на дополнительные узлыВысокая доступность, отказоустойчивость, балансировка нагрузки

2. Масштабирование ClickHouse по горизонтали с использованием шардинга

Шардинг распределяет данные по нескольким узлам, снижая нагрузку на каждый узел хранения данных.

Шаг 1: Добавление нового шарда в кластер

Обновите файл config.xml на всех узлах для добавления нового шарда.

<remote_servers>
    <my_cluster>
        <shard> <!-- Существующий Шард 1 -->
            <replica>
                <host>clickhouse1</host>
                <port>9000</port>
            </replica>
            <replica>
                <host>clickhouse2</host>
                <port>9000</port>
            </replica>
        </shard>
        <shard> <!-- Новый Шард 2 -->
            <replica>
                <host>clickhouse3</host>
                <port>9000</port>
            </replica>
            <replica>
                <host>clickhouse4</host>
                <port>9000</port>
            </replica>
        </shard>
    </my_cluster>
</remote_servers>
 

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

sudo systemctl restart clickhouse-server

Шаг 2: Создание локальных таблиц на новом шарде

На новых узлах (clickhouse3, clickhouse4) создайте ту же таблицу MergeTree:

CREATE TABLE events_local (
    event_id UInt32,
    event_time DateTime,
    user_id UInt32
) ENGINE = MergeTree()
ORDER BY event_time;

Шаг 3: Обновление распределённой таблицы

На всех узлах обновите распределённую таблицу, чтобы она включала новый шард:

CREATE OR REPLACE TABLE events_distributed
ENGINE = Distributed(my_cluster, default, events_local, rand());

✅ Теперь новые запросы будут автоматически маршрутизироваться на новый шард!

Шаг 4: Перераспределение старых данных по шардом

🚨 Проблема: При добавлении нового шарда старые данные остаются неравномерно распределёнными.

Решение: Перераспределите данные вручную.

✅ Шаг 1: Создание Временной Таблицы

Создайте временную таблицу для хранения данных, пока мы выполняем перераспределение.

CREATE TABLE events_temp AS events_local ENGINE = MergeTree() ORDER BY event_time;

✅ Эта таблица временно будет содержать все старые данные.

✅ Шаг 2: Копирование Данных из Распределённой Таблицы в Временную Таблицу

INSERT INTO events_temp SELECT * FROM events_distributed;

✅ Теперь в events_temp содержатся все данные со всех старых шардов.

✅ Шаг 3: Удаление Старых Данных из Существующих Шардов

Удалите данные с существующих шардов, чтобы подготовить их к перераспределению.

ALTER TABLE events_local ON CLUSTER my_cluster DELETE WHERE 1;

✅ Теперь все шардовые таблицы пусты, но данные сохранены в events_temp.

✅ Шаг 4: Повторное Вставление Данных через Распределённую Таблицу

Повторно вставьте данные из events_temp в распределённую таблицу, что позволит перераспределить данные по всем шартам, включая новые.

INSERT INTO events_distributed SELECT * FROM events_temp;

🚀 Теперь ClickHouse перераспределит данные по ВСЕМ шартам, включая новые!

✅ Шаг 5: Удаление Временной Таблицы (Очистка)

Удалите временную таблицу после завершения процесса.

DROP TABLE events_temp;

3. Масштабирование ClickHouse по горизонтали с использованием репликации

Репликация добавляет больше копий существующих данных, улучшая производительность чтения, отказоустойчивость и доступность.

Шаг 1: Добавление реплики к существующему шарду

На новом узле создайте ту же таблицу ReplicatedMergeTree:

CREATE TABLE events_local (
    event_id UInt32,
    event_time DateTime,
    user_id UInt32
) ENGINE = ReplicatedMergeTree('/clickhouse/tables/shard1/events', '{replica}')
ORDER BY event_time;
 

✅ ClickHouse автоматически синхронизирует данные с новой репликой!

Шаг 2: Обновление распределённой таблицы

Обновите распределённую таблицу, чтобы запросы использовали новую реплику:

CREATE OR REPLACE TABLE events_distributed
ENGINE = Distributed(my_cluster, default, events_local, rand());

✅ Теперь ClickHouse будет распределять запросы по всем репликам!

4. Как ClickHouse обрабатывает балансировку нагрузки после масштабирования

  • Для запросов: ClickHouse автоматически распределяет SELECT-запросы по репликам.
  • Для вставок: Данные отправляются в один шард за раз (распределение через rand() или хэширование).
  • Для отказоустойчивости: Если узел выходит из строя, запросы автоматически перенаправляются на доступные реплики.

✅ Включите prefer_localhost_replica, чтобы оптимизировать маршрутизацию запросов:

SET prefer_localhost_replica = 1;

✅ Это обеспечит использование ближайшей доступной реплики, уменьшая сетевые задержки!

5. Резюме: Как масштабировать ClickHouse по горизонтали

Метод масштабированияШагиЛучшее применение
Шардинг (Больше шардов)Обновите config.xml → Создайте новые таблицы MergeTree → Обновите распределённую таблицу → Перераспределите данныеБольшие наборы данных, высокая нагрузка на запись
Репликация (Больше реплик)Создайте таблицы ReplicatedMergeTree на новых узлах → Обновите распределённую таблицу → Запросы автоматически используют репликиВысокая доступность, чтение с высокой нагрузкой

🚀 Основной вывод:

  • Шардинг улучшает производительность записи, распространяя данные по нескольким узлам.
  • Репликация улучшает производительность чтения и защиту от сбоев.
  • Перераспределение данных — это вручную выполняемый процесс при добавлении новых шардов.