Если вы любите ClickHouse®, Altinity может упростить вашу работу с помощью нашего полностью управляемого сервиса в вашем облаке (BYOC) или нашего облака и круглосуточной экспертной поддержки. Узнайте больше.
По мере роста популярности ClickHouse объем аналитических данных в отдельных базах данных стремительно увеличивается. Нередко можно встретить приложения, которые начинаются с петабайта данных и растут дальше. Это поднимает вопрос о том, как хранить большие объемы данных недорого и гибко.
К счастью, таблицы ClickHouse MergeTree могут хранить данные в объектном хранилище S3, которое дешевле и не имеет ограничений по размеру блочного хранилища. Практически все публичные облака в настоящее время предлагают S3-совместимые сервисы хранения. MergeTree — это основной движок для больших таблиц, а поддержка S3 является важным расширением его возможностей. Мы накопили значительный опыт помощи клиентам в его эффективном использовании. Мы также активно работаем над улучшением возможностей S3 вместе со многими другими членами сообщества.
Эта серия блога представляет собой обзор управления таблицами MergeTree на базе S3. Первая статья описывает архитектуру хранения S3 и то, как создать таблицу MergeTree, использующую S3. Вторая статья суммирует текущие лучшие практики объектного хранения с MergeTree. Третья и последняя статья охватывает вопросы поддержания S3-хранилища в исправном состоянии. В частности, мы покажем, как очищать потерянные файлы S3, которые появляются, когда метаданные таблицы ClickHouse рассинхронизируются с данными, хранящимися в S3.
В примерах ниже используется официальная сборка ClickHouse версии 24.3.2.23, работающая на AWS EKS под управлением Altinity Kubernetes Operator для ClickHouse версии 0.23.5. Пример кода находится здесь. Вы можете применять эти практики как в других публичных облаках, так и в кластерах ClickHouse, работающих за пределами Kubernetes.
Высокоуровневый обзор хранилища MergeTree на базе S3
Начнем с общего обзора с высоты птичьего полета. Таблицы MergeTree на базе S3 сохраняют файловую структуру MergeTree на локальном хранилище, но используют объектное хранилище для хранения фактических байтов данных. Мы рассмотрим, как это работает в трех различных случаях.
Использование S3 на одном сервере ClickHouse
Таблицы MergeTree имеют следующую логическую организацию. Внутри именованной таблицы у нас есть партиции (parts), которые представляют собой разделы таблицы, разбитые по ключу партиционирования. Внутри каждой партиции находятся файлы, содержащие индексы, значения столбцов и описательную информацию о партиции, такую как контрольные суммы файлов. Файлы содержат фактические данные и хранятся на локальном диске. Вот простая диаграмма иерархии.
При использовании S3 байты хранятся в файлах S3, а не локально. Вот упрощенная схема, иллюстрирующая, как это работает в кластере с одной репликой.
Мы называем локальные файлы «метаданными», потому что они обеспечивают структуру каталогов и имена файлов, в которых живут данные MergeTree. Фактические байты мы называем «данными». Механизмы хранения данных MergeTree на локальном носителе работают практически так же, как и при хранении данных в S3. Это важное свойство таблиц MergeTree на базе S3. В следующем разделе мы поговорим о том, почему это выгодно.
Использование S3 с реплицированными таблицами MergeTree
В производственных развертываниях ClickHouse принято развертывать реплики. В этом случае у нас есть несколько серверов, каждый со своей собственной копией данных, хранящихся в S3. Следующая иллюстрация показывает это.
Давайте кратко рассмотрим процесс репликации. Когда вы вставляете блок данных в таблицу MergeTree, ClickHouse создает одну или несколько партиций MergeTree с файловыми структурами (т.е. метаданными) на локальном хранилище вместе с фактическими байтами информации таблицы (т.е. данными). Он также записывает партицию в [Zoo]Keeper. Другие реплики таблицы могут обратиться к Keeper, чтобы узнать, какие новые партиции им нужно получить. Они связываются с репликой, у которой есть эта партиция, скачивают ее и сохраняют копию партиции локально.
Процесс работает точно так же при хранении данных MergeTree в S3, за исключением того, что нам нужно скачивать байты данных из S3 вместо того, чтобы читать их с локального хранилища. Вот иллюстрация, прослеживающая процесс передачи партиции. Keeper опущен для наглядности.
Как показывает эта картинка, репликация работает практически так же, как и для локально хранимой таблицы MergeTree. Ключевой момент заключается в том, что каждая таблица-реплика имеет свою собственную копию файлов в S3, даже если они записаны в один и тот же бакет S3, как в этом примере. Тот факт, что байты находятся в S3, не влияет на процесс получения партиций.
Репликация без копирования (Zero-copy Replication)
Внимательные читатели (и многие пользователи ClickHouse) часто отмечают, что для каждой реплики ClickHouse нецелесообразно хранить собственную копию файлов MergeTree в S3. В конце концов, все они ссылаются на одни и те же данные. Разве не было бы эффективнее хранить одну копию каждого файла в S3 и заставить всех ссылаться на нее?
Существует такая функция, и она называется репликацией без копирования. Она управляется настройкой MergeTree, которая отключает репликацию файлов S3 и вместо этого направляет каждый сервер ClickHouse на одни и те же файлы. Репликация без копирования является экспериментальной. Altinity не рекомендует использовать ее, если вы не обладаете глубокими навыками работы с ClickHouse и не понимаете риски ее использования. Тем не менее, она существует, поэтому стоит понять, как она работает. Репликация без копирования позволяет нескольким серверам ClickHouse совместно использовать одни и те же файлы в S3. Вот как это выглядит.
Есть и другое преимущество — это ускоряет репликацию. Без репликации без копирования ClickHouse должен копировать файлы из S3, чтобы поделиться ими с другой репликой, которая затем записывает данные обратно в новый файл S3. Репликация без копирования позволяет избежать этих накладных расходов на пересылку.
Так почему же мы не рекомендуем репликацию без копирования? Помимо того, что она является экспериментальной, оказывается, что использование несколькими серверами одних и те же удаленных файлов создает большую сложность. ClickHouse должен координировать действия между серверами для поддержания точного подсчета ссылок на файлы S3 на всех серверах. Это включает в себя особые случаи, создаваемые такими операциями, как ALTER TABLE FREEZE, если назвать лишь одну из многих. Существует все еще ряд ошибок, и будут найдены новые. Помимо дополнительных способов потерять отслеживание файлов, репликация без копирования создает дополнительную нагрузку на [Zoo]Keeper.
Существует и другой риск, помимо ошибок: репликация без копирования может не поддерживаться в будущих выпусках. Существуют альтернативные подходы к проектированию, такие как улучшение дисков s3_plain, например, путем придания им возможности записи. Это может решить проблему лучше, объединив метаданные и данные в самом S3.
Команды, которые мы знаем и которые успешно используют репликацию без копирования, имеют собственных разработчиков ClickHouse, способных оценить риски и устранить проблемы. Свяжитесь с нами, если вам нужна дополнительная информация.
Имена файлов, жесткие ссылки и данные S3
Мы упоминали выше, что есть преимущества в том, что MergeTree обращается к хранилищу S3 способом, который максимально имитирует локальное хранилище. Такая конструкция имеет смысл, если вы понимаете, как ClickHouse управляет хранилищем MergeTree изнутри.
ClickHouse использует жесткие ссылки файловой системы Linux, чтобы позволить нескольким именам файлов ссылаться на базовые данные, хранящиеся в инодах. Например, ClickHouse может мгновенно и безопасно переименовать таблицу, создав новое имя файла со своей собственной жесткой ссылкой на базовую таблицу. ClickHouse использует тот же трюк для таких операций, как заморозка таблиц, отсоединение или присоединение партов и изменение столбцов. Благодаря жестким ссылкам ClickHouse может выполнять множество операций реструктуризации таблиц почти мгновенно, не затрагивая данные.
Вот пример работы жестких ссылок. Допустим, два имени файла ссылаются на файл в парте и на замороженную версию этого же файла. Последняя появляется, если мы выполняем команду ALTER TABLE FREEZE для создания снимка (снапшота) данных таблицы в целях резервного копирования. Оба они имеют жесткие ссылки на одни и те же бинарные данные в рамках одного и того же инода.
Приведенные выше ссылки представляют собой два представления одного и того же файла: одно в активной базе данных, а другое в теневом представлении, которое заморожено на время создания резервной копии.
Реализация диска S3 расширяет реализацию локального хранилища MergeTree, как показано на следующей схеме. Вместо размещения данных на локальном носителе ClickHouse хранит ссылку на расположение в S3.
При таком подходе такие операции, как переименование таблицы, «просто работают» даже тогда, когда данные таблицы находятся в S3. Это распространяется на все операции, включая репликацию.
Обратная сторона заключается в том, что ClickHouse зависит от метаданных, хранящихся в локальной файловой системе, для идентификации файлов S3. Если метаданные будут утеряны или рассинхронизируются с содержимым S3, это может привести к появлению так называемых «осиротевших» файлов S3. Мы поговорим об «осиротевших» файлах в третьей части этого блога.
Настройка таблицы MergeTree на базе S3
Давайте отойдем от картинок и посмотрим на реальные таблицы. Для иллюстрации мы настроим кластер ClickHouse с двумя репликами, как показано на рисунке выше. (Пример кода доступен здесь, если вы хотите следовать шагам вместе с нами.) Кластер работает в Kubernetes, но эти принципы применимы к любому кластеру ClickHouse, использующему объектное хранилище.
Хранилище S3 задается с помощью конфигурации хранилища. Конфигурация включает диск, определяющий местоположение хранилища, и политику для объединения дисков в тома с определенным именем. (Код конфигурации хранилища находится здесь.)
Важное примечание: В этом примере мы сделаем все очень просто и будем хранить данные таблицы напрямую только в S3. В реальных развертываниях вы обычно будете добавлять дисковый кэш, чтобы сократить количество вызовов API к S3. Вы также будете использовать многоуровневое хранилище (tiered storage), чтобы размещать горячие данные на блочном хранилище. Использование блочного хранилища позволяет недавно вставленным партам объединяться без накладных расходов на производительность и дополнительных вызовов API, связанных с постоянной перезаписью тех же данных в S3. Мы рассмотрим кэширование и многоуровневое хранилище в следующей статье этой серии.
Обратите внимание на макросы {installation} и {replica} в определении конечной точки S3. Они генерируются автоматически оператором Altinity Kubernetes Operator. Лучшей практикой является разделение хранилища S3, используемого каждой репликой, и макросы отлично справляются с этой задачей. Это гарантирует, что данные для каждого сервера записываются на уникальную конечную точку S3 и не будут смешиваться с другими репликами. Если вы не используете Kubernetes, вы можете настроить эти макросы самостоятельно и добиться того же эффекта.
Чтобы хранить данные в S3, создайте таблицу ReplicatedMergeTree и используйте настройку storage_policy для выбора описанной выше политики.
Макрос {cluster} — это еще одно творение оператора Altinity Operator. Если вы не используете Kubernetes, вы можете определить имя собственного кластера в качестве макроса. Это хорошая практика для всех инсталляций ClickHouse.
Отслеживание расположения файлов S3
Теперь давайте подробно разберем расположение данных. Байты любого файла, созданного для этой таблицы, будут храниться в S3. Однако метаданные таблицы будут находиться в локальном хранилище. Давайте добавим немного данных, чтобы у нас было на что посмотреть.
Теперь мы можем использовать системную таблицу system.parts, чтобы найти путь в Linux к парту, содержащему реальные данные. Вот запрос для поиска пути к парту.
Путь представляет собой реальный каталог, содержащий реальные файлы, которые ссылаются на данные, принадлежащие этому парту. Давайте выберем файл checksums.txt, который имеет следующий путь в локальной файловой системе.
Если бы мы посмотрели на checksums.txt для парта таблицы MergeTree, хранящейся в файловой системе, он содержал бы байты бинарных данных контрольных сумм. Вы бы увидели примерно следующее, если бы вывели его на экран с помощью команды Linux cat.
Полезный совет: Вывод подобных бинарных данных может сломать ваш терминал. Используйте команду Linux hd для безопасного вывода байтов и переведенных строк.
В таблице на базе S3 содержимое файла совершенно другое. Теперь это ссылка на данные, хранящиеся в S3, с суффиксом пути, который ClickHouse может использовать для поиска файла.
SQL-запросы для определения местоположения файлов MergeTree в S3
Нам на самом деле не обязательно перебирать файлы на диске, чтобы найти удаленные пути для данных MergeTree в S3. ClickHouse предоставляет их в таблице system.remote_data_paths. Вот пример поиска указанного выше файла. В нем показаны как локальный, так и удаленный пути к файлу.
Мы можем перепроверить нашу работу с помощью aws-cli от Amazon. Обратите внимание, что фактический размер файла в S3 совпадает как с размером, указанным в самом файле, так и с результатами запроса к system.remote_data_paths.
Тем не менее, нам также не обязательно использовать сторонние инструменты вроде aws-cli. Сам ClickHouse может напрямую читать метаданные файлов S3 с помощью табличной функции s3().
Подводя итог, можно выделить три важных момента для понимания того, как хранятся данные в MergeTree. Для каждого файла S3, используемого MergeTree:
- Каталог таблицы MergeTree и имена файлов (также известные как метаданные) хранятся в локальном хранилище сервера ClickHouse. Это дает каждому файлу правильное имя (или два, или три…), чтобы ClickHouse мог его найти. Локальный файл содержит указатель на расположение в S3.
- Данные хранятся в S3. Это просто байты в файле с внутренним именем.
- Для каждого выделенного файла S3 в таблице system.remote_data_paths есть строка, содержащая сопоставление локального и удаленного путей к файлам. Вы также можете проверить содержимое S3 с помощью aws-cli или выбрав данные из табличной функции s3().
Таким образом, метаданные файлов хранятся локально на сервере ClickHouse, а данные файлов хранятся в S3.
Заключение и продолжение следует
В этой первой статье о таблицах MergeTree в объектном хранилище S3 мы показали, как MergeTree управляет файлами S3, как настроить таблицу с S3 и как отслеживать расположение файлов. Мы также вкратце обсудили репликацию без копирования (zero-copy replication), которая является экспериментальной функцией ClickHouse и должна использоваться только в том случае, если вы абсолютно уверены в своих действиях.
Кстати, это не единственная документация о том, как работает S3. Вы также можете ознакомиться со следующими материалами, чтобы узнать больше.
- Как работает гибридное хранилище ClickHouse на базе S3 «под капотом» — Отличная сводка по внутреннему устройству S3 MergeTree от Антона Ивашкина, лид-разработчика DoubleCloud.
- Документация по таблицам ClickHouse MergeTree — Описывает синтаксис SQL ClickHouse, а также политики хранения и множество других тем.
Вы также можете прочитать исходный код, что всегда полезно, если вы хотите быть уверены в том, что происходит на самом деле. Большая часть реализации поведения S3 находится в каталоге ClickHouse Storages на GitHub.
В следующей статье мы представим практические рекомендации по настройке хранилища S3 и управлению таблицами MergeTree, использующими S3.










