Tinybird рассказала о 5 годах эксплуатации ClickHouse на петабайтах

Хави Сантана, сооснователь аналитической компании Tinybird, опубликовал в блоге Tinybird разбор многолетней эксплуатации кластеров ClickHouse, открытой колоночной СУБД для аналитики. В заголовке поста заявлено 5 лет опыта, а в первых строках самого текста Сантана уточняет иначе: с ClickHouse в Tinybird он работает с версии 18.4, по его словам, это было «почти шесть лет назад»; свой самый первый пост о ClickHouse (о геопространственной аналитике) он написал ещё раньше, «почти восемь лет назад». Источник сам не поясняет расхождение между «5 годами» в заголовке и «почти шестью» в тексте. Материал сопровождает отдельная оговорка для юристов ClickHouse, Inc: Tinybird, независимый пользователь и контрибьютор open-source проекта, никак не аффилированный с компанией, держателем товарного знака ClickHouse. Пост обозначен как первая часть из двух: во второй автор обещает разбор мониторинга кластера, поведения под нагрузкой и типичных проблем эксплуатации.
Архитектура, которую предлагает сам ClickHouse для больших кластеров, строится на шардах и репликах: данные делятся на «бакеты» (например, по хешу user_id), каждый бакет попадает в свой шард, а у каждого шарда есть несколько реплик-копий. Несколько лет назад Tinybird начинала без шардирования, только с репликами: нагрузку масштабировали вертикально и добавлением новых реплик, а от шардирования отказались, потому что переразбиение на шарды оказалось слишком сложным техническим шагом, и при продуманной схеме данных клиентам оно, по сути, не требовалось. Перед репликами стоит HTTP-балансировщик нагрузки, Сантана объясняет отказ от «родного» TCP-протокола ClickHouse именно доступом к широкому и проверенному временем инструментарию для HTTP; балансировщик распределяет запросы по типу, текущей нагрузке и консистентному хешированию (чтобы эффективнее использовать кеш). Отдельная реплика в Tinybird выделена только под запись, Сантана называет это «compute-compute separation», с автоматическим переключением при сбое. Чтобы показать, во сколько обходится хранение полной копии данных на каждой машине, Сантана приводит условный пример: гипотетическая таблица на 300 ТБ при нагрузке 1000 запросов в секунду и лимите 100 запросов в секунду на реплику потребует 10 реплик, то есть 3000 ТБ суммарного объёма хранения, это не реальные цифры Tinybird, а иллюстрация экономики репликации. Для запросов с жёстким требованием к 99-му процентилю задержки (p99) он советует держать выделенную под них реплику нагруженной не выше чем на 40%, чтобы хвостовые задержки оставались стабильными.
Главной слабостью открытой версии ClickHouse Сантана называет ограниченную поддержку облачных хранилищ: по его мнению, современным OLAP-системам стоит разделять вычисления и хранение ради экономии и независимого масштабирования, этот стандарт задала Snowflake больше десяти лет назад, и open-source ClickHouse в этом отстаёт (в отличие, например, от StarRocks). Хранить данные можно локально, тогда каждая реплика копирует данные остальных через служебную систему ZooKeeper, либо в едином внешнем хранилище вроде S3, откуда реплики могут читать данные напрямую без собственной копии; второй вариант и называется репликацией без копирования, или zero-copy-репликацией. Механизм zero-copy в открытый ClickHouse в своё время добавил контрибьютор со стороны, не из ClickHouse, Inc, и, по словам Сантаны, в самой компании его недолюбливают не без причины: он «бажный», может терять данные и оставляет мусор в S3; в какой-то момент ClickHouse, Inc даже планировала убрать эту функцию, но в итоге передумала. Tinybird использует доработанную версию zero-copy-репликации в собственном приватном форке ClickHouse, поверх S3 держит локальные SSD как кеш переменного размера, а для клиентов с высокими требованиями к задержке, гибридную схему «горячего/холодного» хранения (локальные SSD плюс S3). Отдельная статья экономии, то, как ClickHouse по умолчанию пишет в S3: это множество мелких операций записи, потому что формат хранения изначально проектировался под локальные диски, где сама запись условно «бесплатна» (в отличие от операций ввода-вывода в секунду, которые стоят денег). Из практических советов по сжатию, использовать ZSTD(1) или ZSTD(2) как разумный компромисс между скоростью и степенью сжатия (по опыту Сантаны, ZSTD почти всегда лучше LZ4) и время от времени тестировать другие форматы сжатия на своих данных.
Апгрейды кластера дались Tinybird дорогой ценой опыта. Самое первое обновление заняло 3 часа выкатки при двух неделях подготовки. Со временем команда научилась обновляться без остановки сервиса, без потери данных и без просадки производительности, а затем встроила сам процесс апгрейда прямо в CI/CD-конвейер, но на весь этот путь ушло 4 года, и, насколько известно Сантане, больше ни одна компания такого не добилась. Порядок действий при апгрейде, который он описывает: поднять новую реплику на новой версии → последить за логами на предмет ложных «критических» сообщений → по возможности не вносить структурных изменений в таблицы на время апгрейда → не использовать новые функции, пока весь кластер не обновлён → пустить на новую реплику тестовый трафик на чтение, затем тестовые записи → постепенно перевести реальный трафик, при сомнениях подержав реплику подольше → и только потом обновлять остальные реплики; всё это работает благодаря обратной совместимости протокола репликации, над которой Tinybird целенаправленно работала, в том числе находя проблемы через собственный CI ещё до релиза ClickHouse и отправляя патчи разработчикам. Среди проблем при апгрейдах: несовместимые изменения формата хранения данных, редко, но случались 2, 3 раза за последние 2 года, минимум два случая команда исправила сама (Сантана объясняет, что замечает такие проблемы только потому, что в клиентской базе Tinybird встречаются вообще все комбинации типов данных, и уточняет, что в обычном, не мультитенантном, развёртывании столкнуться с этим маловероятно); изменения поведения SQL из-за фиксов багов, способные незаметно сломать запросы (отслеживать помогает системная таблица system.query_log); изменения производительности, не всегда к худшему, но требующие тестирования перед откатом на старую версию; и изменения настроек по умолчанию, которые нужно отдельно вычитывать в списке изменений между версиями. Общая рекомендация, не обновляться сразу после релиза, выждав хотя бы месяц, и не включать экспериментальные функции без чёткого понимания последствий. Для валидации Tinybird прогоняет тесты на разных версиях и на кластерах со смешанными версиями в CI, а раз в день дополнительно прогоняет реальные клиентские запросы на следующей версии ClickHouse, чтобы заранее заметить проблему.
Раздел о затратах Сантана сводит к внешне простой арифметике: стоимость самих реплик и шардов (зависит от цены инфраструктуры); минимум 3 реплики ZooKeeper, обязательно изолированные на отдельных машинах, по его словам, проблема с ZooKeeper означает, что кластеру конец; выбор и расчёт стоимости хранения (локально, в S3 или гибридно, с поправкой на то, что диски нельзя уменьшить «на лету», а у операций в S3 есть отдельная стоимость); резервный балансировщик нагрузки (для отказоустойчивости нужен не один); и стоимость хранения бэкапов, которая зависит от политики хранения и объёма данных. Ориентир по железу, который он даёт: одна 32-ядерная машина уверенно обрабатывает около 5 ГБ/с несжатых данных. По людям: для небольшого кластера достаточно человека с частичной занятостью, но при потоке вставок свыше 20 тысяч строк в секунду (и когда в схему часто вносят изменения) нужен уже инженер на полную ставку, соблюдение базовых правил эксплуатации, по оценке Сантаны, даёт разницу в 3, 4 раза в объёме необходимого железа. Он прямо признаёт: специалистов по ClickHouse и инфраструктуре данных найти тяжело, а обычные процессы найма плохо отбирают именно под этот профиль. Отсюда, по сути, и логика существования самой Tinybird: Сантана не советует компаниям обслуживать такой кластер самостоятельно и говорит, что Tinybird создали именно ради того, чтобы не заниматься этой болью, сервис не хостит ClickHouse как таковой, а решает более узкую задачу аналитики поверх него.
Больше всего проблем, по словам Сантаны, доставляет приём данных (ingestion): с потерей и задвоением данных при неверно настроенной вставке, по его выражению, «мучается» буквально каждая компания, работающая с ClickHouse, причём часто узнают об этом не сразу. Причина, в тонком балансе между вставками, слияниями (merges), чтениями, мутациями и самим дизайном таблиц: каждая вставка создаёт новый «кусок» (part) данных, куски периодически сливаются в более крупные фоновым процессом слияния (по сути аналог процесса уплотнения, compaction, в Iceberg), крупные куски ускоряют чтение, но сами слияния становятся дороже по процессору и памяти. Увеличение вставочных пакетов снижает число кусков, но повышает задержку и нагрузку на память при вставке; типичный сценарий отказа, запрос выедает процессор или ввод-вывод, вставки начинают копиться, память растёт, происходит аварийное завершение процесса из-за нехватки памяти (OOM), и как следствие теряются данные. Рекомендации Сантаны: батчировать вставки умеренного размера (в идеале, один кусок на вставку), по возможности разносить их по партициям с разным временем сброса на диск; гонять частые вставки только там, где это действительно нужно; при хранении в S3 использовать формат Compact parts, это резко снижает число операций записи и бережёт от лимитов S3 по частоте запросов; иногда выгодно держать небольшой «горячий» диск, чтобы первые слияния шли не через S3; аккуратно подбирать максимальный размер куска, чтобы не плодить лишние слияния, но и не разрастить их сверх меры; и обучать команду проектированию партиционирования, потому что дизайн таблицы неотделим от того, как в неё пишут, неверно выбранный ключ партиционирования, слишком частые вставки или неудачно спроектированное материализованное представление способны привести кластер к отказу. Материализованные представления Сантана называет отдельным источником проблем с памятью: неудачно написанное представление может занять больше памяти, чем нужно, и вызвать аварийное завершение сервера из-за нехватки памяти, в Tinybird на такой случай сделали систему, которая автоматически отключает проблемные представления. Среди повторяющихся сбоев он перечисляет: таблицы, «залипающие» в режиме только для чтения (обычно при старте реплики, иногда без ясной причины, тогда помогает пересоздание таблицы и повторная репликация); слишком большое число кусков при заливке данных (например, если одной вставкой залить сразу три года данных в таблицу с посуточным партиционированием, писать стоит только в одну партицию за раз) и ситуацию, когда слияния не успевают за вставками и очередь слияний растёт (лечится увеличением пула потоков и/или сдерживанием темпа вставки). Отдельно Сантана говорит о механизме противодавления (backpressure): часть компаний ставит перед ClickHouse очередь Kafka, но Tinybird разработала для этого собственное решение, Kafka оказалась слишком дорогой при их мультитенантной модели и не позволяла тонко настраивать приём данных под каждую таблицу отдельно; без какого-то подобного механизма, по его словам, в проде любой мелкий сбой оборачивается потерей данных. В списке проблем также, внезапные всплески нагрузки, под которые не успеть поднять новую реплику (нужна очередь, сглаживающая пик), и дублирование данных при неудачно спроектированной обработке ошибок вставки, которое ломает материализованные представления и портит статистику.
Пост обозначен как первая часть серии из двух материалов; во второй Сантана обещает разобрать эксплуатацию и мониторинг кластера (в том числе связку с Grafana), поведение под нагрузкой, точечные настройки производительности и другие типичные проблемы.
Ключевые факты
- Хави Сантана, сооснователь Tinybird, работает с ClickHouse в компании с версии 18.4, по его словам, «почти шесть лет» (при этом в заголовке самого поста фигурирует другая цифра, «5 лет»).
- Архитектура Tinybird строится на репликах без шардирования, с HTTP-балансировщиком нагрузки; отдельная реплика выделена только под запись, а для запросов с жёстким требованием к 99-му процентилю задержки рекомендуется держать реплику нагруженной не выше 40%.
- Репликация без копирования (zero-copy) поверх S3 в открытом ClickHouse, по словам автора, «бажная» и может терять данные, ClickHouse, Inc даже раздумывала убрать эту функцию; Tinybird использует доработанную версию в собственном приватном форке.
- Первый апгрейд кластера занял 3 часа при двух неделях подготовки; выход на апгрейды без остановки сервиса и потери данных прямо в CI/CD занял у команды 4 года, а несовместимые изменения формата хранения случались 2, 3 раза за последние 2 года.
- Главный источник потерь и задвоения данных, неверно настроенный приём данных (ingestion); для кластеров с потоком вставок свыше 20 тысяч строк в секунду Сантана рекомендует держать инженера на полную ставку, а не человека с частичной занятостью.
Почему это важно
Материал даёт редкий взгляд на эксплуатацию ClickHouse не из документации, а из первых рук, от сооснователя Tinybird, который держит петабайтные кластеры этой СУБД около шести лет. Такой опыт заметно расходится с маркетинговыми описаниями: автор прямо называет слабые места открытой версии ClickHouse (слабую поддержку облачных хранилищ, «бажную» и рискованную по сохранности данных репликацию без копирования, дорогую по числу операций запись в S3) и показывает, сколько инженерной работы стоит за тем, что коротко называют «апгрейдом без остановки сервиса»: в случае Tinybird на это ушло четыре года практики. Для рынка, где ClickHouse и похожие колоночные СУБД всё активнее используются как аналитический слой под дата- и ИИ-продуктами, такая прямая и местами самокритичная инвентаризация проблем, редкость.
Кому это важно
Прежде всего, инженерам данных, DevOps/SRE-специалистам и администраторам баз данных, которые уже эксплуатируют ClickHouse на больших объёмах или выбирают между ним и другими OLAP-системами (в тексте упомянуты Snowflake и StarRocks). Также техническим руководителям и нанимающим менеджерам: автор отдельно отмечает, что специалистов по ClickHouse и инфраструктуре данных найти тяжело, обычные процессы найма плохо под них заточены, а при потоке вставок свыше 20 тысяч строк в секунду такому кластеру, по его оценке, нужен уже инженер на полную ставку, а не человек с частичной занятостью. И тем, кто присматривается к готовым облачным сервисам поверх ClickHouse вроде Tinybird, пост по сути объясняет, от какой именно инженерной нагрузки такой сервис избавляет.
Как это применить
Из текста можно вынести конкретный операционный чек-лист: держать минимум 3 реплики ZooKeeper на изолированных машинах; при обновлении версии сначала поднимать новую реплику и следить за логами, не включать новые функции до полного обновления кластера, переводить трафик постепенно (сначала чтение, потом запись) и не апгрейдиться раньше чем через месяц после релиза; для сжатия по умолчанию брать ZSTD(1) или ZSTD(2); при вставке данных стремиться примерно к одному куску (part) на вставку, разносить вставки по партициям и при хранении в S3 использовать формат Compact parts, чтобы не упереться в лимиты по числу операций; закладывать в расчёт железа ориентир «32 ядра ≈ 5 ГБ/с несжатых данных»; и строить собственный механизм противодавления на вставке данных, а не полагаться на то, что перед ClickHouse просто поставили очередь Kafka.
Можно ли доверять
Источник, личный опыт практика, а не независимая оценка или бенчмарк: автор, сооснователь Tinybird, коммерческой аналитической платформы поверх ClickHouse, и часть описанного (например, доработанный приватный форк с изменённым механизмом zero-copy), это архитектурное решение именно Tinybird, не обязательно применимое к любой другой инсталляции. Сам автор отдельно оговаривает, что не аффилирован с ClickHouse, Inc, компанией, держателем товарного знака и основным майнтейнером проекта, что скорее говорит в пользу непредвзятости его критики открытой версии. Часть цифр в посте, не измерения, а условные иллюстрации: например, пример с таблицей на 300 ТБ и нагрузкой 1000 запросов в секунду, это гипотетический расчёт экономики реплик, а не реальные показатели Tinybird; точных цифр по объёму данных или числу кластеров Tinybird в тексте нет, встречается только общая формулировка «петабайтный масштаб». Есть и небольшая нестыковка в самом источнике: заголовок поста говорит о 5 годах опыта, а в первом абзаце текста автор пишет «почти шесть лет», сам источник это расхождение не поясняет. Наконец, это первая часть из двух: часть тем (мониторинг, поведение под нагрузкой) в этом посте не раскрыта и обещана в продолжении.
Риски и подводные камни
Главный риск, который выделяет сам автор, приём данных (ingestion): с потерей и задвоением данных при неверно настроенной вставке, по его словам, сталкивается «каждая компания, использующая ClickHouse», причём часто узнают об этом не сразу. Отдельно рискованна репликация без копирования (zero-copy) поверх S3 в открытой версии ClickHouse, сам автор называет её «бажной», способной терять данные и оставлять мусор в S3, и напоминает, что ClickHouse, Inc в какой-то момент даже собиралась убрать эту функцию. Неудачно спроектированное материализованное представление может исчерпать память и обрушить сервер; всплеск нагрузки, на который кластер не успевает среагировать новой репликой, и проблемы с ZooKeeper при недостаточной изоляции сервиса переводят таблицы в режим только для чтения или останавливают кластер целиком. Апгрейд версии без выдержки после релиза рискует упереться в нечастые, но неприятные несовместимости формата хранения (по опыту Tinybird, 2, 3 раза за 2 года) и в изменения поведения SQL или настроек по умолчанию, которые тихо ломают существующие запросы.
«Нам потребовалось всего четыре года, чтобы разобраться с этим. Насколько мне известно, ни одна другая компания так не делает.»
— Хави Сантана, сооснователь Tinybird