Files
clickhouse-learning-cluster/README.md
T

291 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Учебный кластер ClickHouse на Docker Compose
Готовый к использованию стенд для изучения кластерных возможностей ClickHouse. Проект создан для быстрого развертывания учебного кластера на любой машине с Docker.
## 🎯 Зачем это нужно
- **Быстрый старт**: поднять кластер ClickHouse на ноутбуке за 5 минут
- **Практическое изучение**: пощупать репликацию, шардинг, балансировку и отказоустойчивость
- **Безопасность**: всё в Docker Compose, сломалось — пересобрали без риска для продакшена
- **Наглядность**: прозрачная структура конфигураций для понимания принципов работы
## 🏗️ Архитектура стенда
### Состав инфраструктуры
- **4× ClickHouse Server** (версия 25.1) — основные узлы кластера
- **1× ZooKeeper** (3.9.3) — координатор для репликации
- **1× HAProxy** (3.1.7) — балансировщик нагрузки
- **3 типа кластерных конфигураций**: 1×4, 2×2, 4×1 (шарды×реплики)
![Схема кластера](./Cluster_schema.drawio.svg)
## 🚀 Быстрый старт
### Предварительные требования
- Docker и Docker Compose
- Минимум 4GB RAM
- Свободные порты: 8124, 9001, 8002-8005, 9123-9126, 2182
### Запуск
```bash
# Клонируем репозиторий
git clone https://github.com/dementev-dev/clickhouse-learning-cluster
cd clickhouse-learning-cluster
# Запускаем кластер
docker compose up
# Проверяем статус
docker compose ps
```
### Проверка работоспособности
```bash
# Через HAProxy (рекомендуемый способ)
curl "http://default:123456@localhost:8124" -d "SELECT version()"
# Или через прямое подключение к узлу
curl "http://default:123456@localhost:9123" -d "SELECT version()"
```
## 🔧 Конфигурация кластера
### Доступные кластерные топологии
| Кластер | Шарды | Реплики | Назначение |
|---------|-------|---------|------------|
| `c1sh4rep` | 1 | 4 | Максимальная отказоустойчивость |
| `c2sh2rep` | 2 | 2 | Сбалансированное решение |
| `c4sh1rep` | 4 | 1 | Максимальная производительность |
### Порты и доступ
| Сервис | HTTP | Native | Назначение |
|--------|------|--------|------------|
| HAProxy | 8124 | 9001 | Балансировка (основной доступ) |
| click1 | 9123 | 8002 | Прямой доступ для отладки |
| click2 | 9124 | 8003 | Прямой доступ для отладки |
| click3 | 9125 | 8004 | Прямой доступ для отладки |
| click4 | 9126 | 8005 | Прямой доступ для отладки |
| ZooKeeper | - | 2182 | Координация кластера |
### Аутентификация
- **Пользователь**: `default`
- **Пароль**: `123456`
## 📊 Примеры работы с кластером
### Проверка кластерной конфигурации
```sql
-- Список доступных кластеров
SHOW CLUSTERS;
-- Детальная информация о узлах
SELECT cluster, groupArray(concat(host_name,':',toString(port))) AS hosts
FROM system.clusters
GROUP BY cluster
ORDER BY cluster;
```
### Создание реплицируемых таблиц
```sql
-- Создаем локальную реплицируемую таблицу на всех узлах
CREATE TABLE user_scores_local ON CLUSTER c2sh2rep (
user_id UInt32,
avg_score Float32,
created_at DateTime
)
ENGINE = ReplicatedMergeTree(
'/clickhouse/shard_{shard_c2sh2rep}/{database}/{table}',
'{replica_c2sh2rep}'
)
ORDER BY (user_id);
-- Создаем Distributed таблицу для прозрачного доступа
CREATE TABLE user_scores ON CLUSTER c2sh2rep
AS user_scores_local
ENGINE = Distributed(c2sh2rep, default, user_scores_local, user_id);
```
### Тестирование с данными
```sql
-- Генерируем тестовые данные
INSERT INTO user_scores
SELECT
number % 10000000 + 1 AS user_id,
toFloat32(rand() % 50 + rand() % 50) / 10 AS avg_score,
now() - (number * 86400 / 1000) AS created_at
FROM numbers(10000000);
-- Проверяем распределение данных по шардам
SELECT
shardNum() AS shard_id,
count() AS rows_per_shard
FROM user_scores
GROUP BY shard_id
ORDER BY shard_id;
```
### Мониторинг репликации
```sql
-- Состояние репликационных очередей
SELECT
hostName() AS host,
database,
table,
replica_name,
total_replicas,
active_replicas,
is_leader,
is_readonly
FROM clusterAllReplicas('c2sh2rep', 'system', 'replicas')
ORDER BY host, table;
-- Лог репликации
SELECT
hostName() AS host,
event_time,
table,
event_type, -- NewPart / MergeParts / DownloadPart и т.д.
part_name -- имя парты (универсальное поле)
FROM clusterAllReplicas('c2sh2rep', 'system', 'part_log')
ORDER BY event_time DESC
LIMIT 100;
```
## 🛠️ Структура проекта
```
clickhouse-learning-cluster/
├── docker-compose.yml # Основная конфигурация сервисов
├── configs/
│ ├── default_user.xml # Настройки пользователя default
│ ├── z_config.xml # Конфигурация кластеров и ZooKeeper
│ ├── macros_ch1.xml # Макросы для узла click1
│ ├── macros_ch2.xml # Макросы для узла click2
│ ├── macros_ch3.xml # Макросы для узла click3
│ ├── macros_ch4.xml # Макросы для узла click4
│ └── haproxy/
│ └── haproxy.cfg # Конфигурация балансировщика
├── sql/
│ └── sample_queries.sql # Примеры запросов для тестирования
└── data/ # Директория для пользовательских файлов
```
## 🔍 Отладка и мониторинг
### Логи сервисов
```bash
# Логи всех сервисов
docker compose logs -f
# Логи конкретного узла
docker compose logs -f click1
# Логи балансировщика
docker compose logs -f haproxy
```
### Проверка состояния
```bash
# Статус контейнеров
docker compose ps
# Использование ресурсов
docker stats
```
### Подключение к узлам напрямую
```bash
# ClickHouse client к первому узлу
docker exec -it clickhouse-learning-cluster-click1-1 clickhouse-client --user default --password 123456
# Или через внешний клиент
clickhouse-client --host localhost --port 8002 --user default --password 123456
```
## ⚠️ Важные особенности
### Уникальность путей в ZooKeeper
Каждая реплицируемая таблица должна иметь уникальный путь в ZooKeeper. Используйте макросы:
- `{shard_c2sh2rep}` — имя шарда
- `{replica_c2sh2rep}` — имя реплики
- `{database}`, `{table}` — имя базы и таблицы
### Лимиты ресурсов
Настроены оптимальные ulimits для ClickHouse:
- `nofile: 262144` — файловые дескрипторы
- `nproc: 65535` — процессы/потоки
### Сети
Все сервисы изолированы в сети `ch_learning_net` для безопасности.
## 🧪 Сценарии для экспериментов
### Тестирование отказоустойчивости
Подразумевается, что создана Distributed таблица user_scores из примеров.
```bash
# Остановим одну реплику шарда 2
docker compose stop click3
# Прроверим чтение распределенной таблицы
curl "http://default:123456@localhost:8124" -d "SELECT count() FROM user_scores"
# Остановим вторую реплику шарда 2
docker compose stop click4
# Снова проверим чтение распределенной таблицы
curl "http://default:123456@localhost:8124" -d "SELECT count() FROM user_scores"
# Восстановим узлы узлы
docker compose start click3
docker compose start click4
```
### Проверка балансировки
```bash
for i in {1..8}; do
echo "Запрос $i:"
curl -s "http://default:123456@localhost:8124" -d "SELECT hostName() AS current_node, now() AS request_time"
echo ""
done
```
## 📚 Полезные ссылки
- [Официальная документация ClickHouse](https://clickhouse.com/docs/)
- [Репликация в ClickHouse](https://clickhouse.com/docs/en/engines/table-engines/mergetree-family/replication)
- [Масштабирование и кластеры](https://clickhouse.com/docs/en/architecture/cluster-deployment)
- [ClickHouse Keeper](https://clickhouse.com/docs/en/guides/sre/keeper/clickhouse-keeper)
## 📝 Лицензия
MIT License — используйте свободно в учебных и коммерческих целях.
## 🤝 Вклад в проект
Приветствуются pull requests с улучшениями:
- Дополнительные примеры запросов
- Новые конфигурации кластеров
- Улучшения документации
- Скрипты автоматизации
## 📞 Поддержка
При возникновении вопросов создавайте issue в репозитории или обращайтесь к официальной документации ClickHouse.