Перейти к содержанию
Learning Platform
Глоссарий Troubleshooting
Урок 16.06 · 30 мин
Продвинутый
PostHogCloudflareGitLabwide flat tablesKafka ingestiondenormalization

Архитектуры на ClickHouse: PostHog, Cloudflare, GitLab

ClickHouse используется в production у сотен компаний. Три крупнейших публичных case study — PostHog, Cloudflare и GitLab — демонстрируют повторяющиеся архитектурные паттерны: широкие плоские таблицы, Kafka для ingestion, агрессивная денормализация и TTL для управления жизненным циклом данных.


PostHog: шардированный кластер для product analytics

PostHog — open-source продуктовая аналитика с само-хостингом. Их ClickHouse-кластер хранит события поведения пользователей в масштабе.

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

  • Шардированный кластер: несколько узлов с горизонтальным масштабированием
  • Kafka pull model: PostHog использует Kafka engine в ClickHouse для pull-чтения из Kafka-топиков (не push через HTTP). Materialized view записывает данные в основные таблицы
  • ReplacingMergeTree для профилей пользователей: person profiles требуют дедупликации — при обновлении свойств пользователя вставляется новая версия, старая вытесняется при merge
  • Агрессивная дедупликация: OPTIMIZE TABLE FINAL используется на небольших таблицах; для production масштаба — SELECT ... FINAL или дедупликация через приложение
-- Kafka engine для pull ingestion (PostHog-like паттерн)
CREATE TABLE events_kafka_queue
(
    uuid        String,
    team_id     UInt32,
    event       String,
    properties  String,    -- JSON-строка
    timestamp   DateTime64(3)
)
ENGINE = Kafka()
SETTINGS
    kafka_broker_list    = 'kafka:9092',
    kafka_topic_list     = 'clickhouse_events',
    kafka_group_name     = 'clickhouse-consumer',
    kafka_format         = 'JSONEachRow';

-- Основная таблица событий (широкая, денормализованная)
CREATE TABLE events
(
    uuid        UUID,
    team_id     UInt32,
    event       LowCardinality(String),
    distinct_id String,
    properties  String,
    timestamp   DateTime64(3),
    -- Денормализованные свойства для быстрых фильтров
    browser     LowCardinality(String) MATERIALIZED
        JSONExtractString(properties, '$browser'),
    os          LowCardinality(String) MATERIALIZED
        JSONExtractString(properties, '$os'),
    country     LowCardinality(String) MATERIALIZED
        JSONExtractString(properties, '$geoip_country_code')
)
ENGINE = ReplacingMergeTree()
PARTITION BY toYYYYMM(timestamp)
ORDER BY (team_id, toDate(timestamp), event, uuid)
TTL toDate(timestamp) + INTERVAL 2 YEAR;

-- Materialized view: Kafka queue -> основная таблица
CREATE MATERIALIZED VIEW events_mv TO events AS
SELECT
    toUUID(uuid)                AS uuid,
    team_id,
    event,
    JSONExtractString(properties, 'distinct_id') AS distinct_id,
    properties,
    timestamp
FROM events_kafka_queue;

-- Person profiles: ReplacingMergeTree для дедупликации по версии
CREATE TABLE person
(
    team_id         UInt32,
    id              UUID,
    created_at      DateTime64(3),
    properties      String,    -- JSON-строка с атрибутами
    version         UInt64     -- монотонно возрастает при каждом update
)
ENGINE = ReplacingMergeTree(version)
ORDER BY (team_id, id);

Паттерн multi-tenancy через RBAC: Каждый PostHog team_id изолируется через CREATE ROW POLICY — tenant видит только свои данные.


Cloudflare: 6 миллионов запросов в секунду

Cloudflare использует ClickHouse для bot management, customer dashboards и real-time network analytics. Масштаб: более 6M RPS на пике.

Ключевые архитектурные решения:

  • Columnar performance: ClickHouse обрабатывает HTTP-запросы с признаками (IP-адрес, User-Agent, заголовки, геолокация) в одной широкой строке. Колоночное хранение позволяет сканировать только нужные атрибуты бота
  • Real-time customer dashboards: Клиенты Cloudflare видят свой трафик с задержкой менее 1 минуты через pre-aggregated materialized views
  • Многоуровневый MergeTree: Горячие данные (последние 24 часа) на быстрых NVMe SSD, архивные данные в S3 через tiered storage (JBOD + S3)
-- Упрощённая схема запроса HTTP-событий (Cloudflare-like)
CREATE TABLE http_requests
(
    -- Ключевые измерения
    zone_id         UInt32,
    client_ip       IPv4,
    ray_id          UInt64,
    request_time    DateTime64(3),

    -- Bot detection features (денормализованы для скорости)
    user_agent      String,
    cf_threat_score UInt8,
    cf_bot_score    UInt8,
    is_bot          UInt8,

    -- Геолокация
    country_code    LowCardinality(String),
    region          LowCardinality(String),

    -- HTTP метаданные
    method          LowCardinality(String),
    status_code     UInt16,
    bytes_sent      UInt32,
    edge_server_id  UInt16
)
ENGINE = MergeTree()
PARTITION BY toStartOfHour(request_time)
ORDER BY (zone_id, toDate(request_time), client_ip)
TTL request_time + INTERVAL 30 DAY;

-- Pre-aggregated view для customer dashboard (sub-second latency)
CREATE MATERIALIZED VIEW zone_hourly_stats
ENGINE = SummingMergeTree()
ORDER BY (zone_id, hour, country_code)
AS SELECT
    zone_id,
    toStartOfHour(request_time) AS hour,
    country_code,
    count()                      AS total_requests,
    sum(bytes_sent)              AS total_bytes,
    countIf(is_bot = 1)          AS bot_requests,
    countIf(status_code >= 400)  AS error_requests
FROM http_requests
GROUP BY zone_id, hour, country_code;

GitLab: sub-second queries для миллионов пользователей

GitLab — крупнейшая платформа DevOps с само-хостингом и GitLab.com. ClickHouse используется для CI/CD аналитики и метрик разработчиков.

Масштаб: Десятки миллионов пользователей, миллиарды CI/CD событий, требования к задержке ниже 1 секунды для большинства dashboard-запросов.

Архитектурные решения:

  • CI/CD аналитика: Данные о pipeline jobs, stage timings, test results — в ClickHouse вместо PostgreSQL. PostgreSQL не справлялся с аналитическими запросами при таком масштабе
  • Широкие таблицы: Pipeline job денормализован (включает данные о project, namespace, runner, stage) — исключает JOIN на горячем пути
  • Async_insert для высокого throughput: GitLab.com генерирует тысячи CI-событий в секунду; async_insert=1 буферизует вставки и снижает нагрузку на ClickHouse
-- Упрощённая схема CI/CD событий (GitLab-like)
CREATE TABLE ci_builds
(
    build_id            UInt64,
    pipeline_id         UInt64,
    project_id          UInt32,
    namespace_id        UInt32,

    -- Денормализованные атрибуты проекта
    project_path        String,
    namespace_path      String,

    -- Характеристики job
    stage_name          LowCardinality(String),
    job_name            String,
    status              LowCardinality(String),   -- success/failed/canceled
    runner_type         LowCardinality(String),   -- shared/group/project

    -- Временные метки
    created_at          DateTime,
    started_at          DateTime,
    finished_at         DateTime,
    duration_seconds    Float32 MATERIALIZED
        if(finished_at > started_at,
           dateDiff('second', started_at, finished_at),
           NULL)
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(created_at)
ORDER BY (project_id, created_at, build_id)
TTL created_at + INTERVAL 3 YEAR;

-- Запрос: среднее время сборки по проекту за последние 30 дней
SELECT
    project_path,
    stage_name,
    avg(duration_seconds)           AS avg_duration,
    quantile(0.95)(duration_seconds) AS p95_duration,
    countIf(status = 'failed')      AS failed_count,
    count()                         AS total_count
FROM ci_builds
WHERE created_at >= now() - INTERVAL 30 DAY
  AND status IN ('success', 'failed')
GROUP BY project_path, stage_name
ORDER BY avg_duration DESC
LIMIT 20;

Общие паттерны production-архитектур

ClickHouse production: 3 ключевых архитектуры
PostHogPostHog: Kafka pull model через Kafka engine + MV. ReplacingMergeTree для person profiles с дедупликацией по version. RBAC ROW POLICY для multi-tenant изоляции. Агрессивная денормализация событий с MATERIALIZED колонками.
CloudflareCloudflare: 6M RPS bot management. Широкие HTTP request таблицы с всеми bot-detection признаками. Pre-aggregated SummingMergeTree MV для customer dashboards. Tiered storage: NVMe для горячих данных, S3 для архива.
GitLabGitLab: CI/CD аналитика заменила PostgreSQL для аналитических запросов. Денормализованные широкие таблицы исключают JOIN на горячем пути. async_insert=1 для высокого throughput вставок. Sub-second queries для миллионов пользователей.

Повторяющиеся паттерны во всех трёх архитектурах:

Широкие плоские таблицы: Вместо 3NF нормализации — денормализованные события с повторяющимися атрибутами. ClickHouse компрессирует повторяющиеся значения лучше, чем JOIN-операции при каждом запросе.

-- Anti-pattern: JOIN на горячем пути запроса
SELECT e.event, u.country, p.name
FROM events e
JOIN users u ON e.user_id = u.id
JOIN projects p ON e.project_id = p.id
WHERE e.ts >= now() - INTERVAL 1 HOUR;

-- ClickHouse pattern: денормализованная таблица, нет JOIN
SELECT event, user_country, project_name
FROM events_denormalized
WHERE ts >= now() - INTERVAL 1 HOUR;

Kafka engine pull model: PostHog и аналоги используют Kafka engine (ClickHouse тянет из Kafka) вместо Kafka Connect (внешний процесс пушит в ClickHouse). Преимущество: нет дополнительной инфраструктуры, backpressure управляется ClickHouse.

MergeTree + TTL для data lifecycle: Все три компании используют TTL для автоматического удаления старых данных. Исключает ручные DELETE-мутации на больших таблицах.

async_insert для высокого throughput: При вставках с клиентских агентов (особенно при высоком числе параллельных источников) async_insert=1 буферизует вставки и снижает число частей на диске.


Ключевые выводы

  1. PostHog демонстрирует стандартный паттерн product analytics: Kafka pull model через Kafka engine + MV, ReplacingMergeTree для mutable entity profiles, RBAC для multi-tenancy.

  2. Cloudflare (6M RPS) доказывает: columnar storage ClickHouse эффективнее row-based DB для real-time analytics с высокой кардинальностью. Pre-aggregated MV обеспечивают sub-second customer dashboards.

  3. GitLab показывает сценарий миграции: PostgreSQL заменён ClickHouse только для аналитических запросов (CI/CD analytics), OLTP данные остались в PostgreSQL — правильное разделение ответственности.

  4. Широкие плоские таблицы + агрессивная денормализация — универсальный паттерн. ClickHouse компрессирует повторяющиеся значения в колонках эффективно; JOIN overhead при каждом запросе дороже дублирования данных.

  5. Kafka + async_insert + TTL — тройная основа production-архитектур с высоким throughput: Kafka для надёжного ingestion, async_insert для сглаживания пиков, TTL для автоматического жизненного цикла данных.

OLAP-платформы: архитектурные паттерны Snowflake, BigQuery, Redshift Денормализация для OLAP: wide tables, precomputed joins и компромиссы

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 7