
Здравейте, habr.
Ако някой експлоатира системата и се сблъсква с проблеми с производителността на хранилището (IO, заето дисково пространство), то вероятността да е обърнато внимание на ClickHouse като алтернатива трябва да се стреми към единица. Това предположение предполага, че вече се използва трета страна за приемане на метрики, например или .
ClickHouse успешно решава описаните проблеми. Например, след прехвърляне на 2TiB данни от whisper, те се побират в 300GiB. Няма да се спирам подробно на сравнението, тъй като има достатъчно статии по темата. Освен това, до скоро с нашето ClickHouse хранилище не всичко беше идеално.
Проблеми с заетото пространство
На пръв поглед всичко трябва да работи добре. Спазвайки , създаваме конфигурация за схемата на съхранение на метрики (по-нататък retention), след което създаваме таблица в съответствие с препоръките на избрания бекенд за graphite-web: + или , в зависимост от това какъв стек се използва. И... активира се бомба със забавен таймер.
За да разберем коя, трябва да знаем как работят вставките и по-нататъшния жизнен цикъл на данните в таблиците на двигателите от семейството *MergeTree ClickHouse (схемите са взети от Алексея Зателепина):
- Вмъква се
блокданни. В нашия случай това са метриките.

- Всеки такъв блок се сортира по ключа
CLR потребителска агрегатна функция, посочен при създаването на таблицата. - След сортирането,
парче(part) данни се записва на диска.

- Сървърът следи на фона, за да не бъде много на брой, и стартира фонови
слияния(обединение, по-нататък мержи).


- Сървърът спира да стартира мержи самостоятелно, когато данните престават активно да постъпват в
партиция(partition), но можем да стартираме процеса ръчно с командаOPTIMIZE. - Ако в партицията е останало само едно парче, не може да се стартира мерж с обикновена команда, необходима е
OPTIMIZE ... FINAL
И така, постъпват първите метрики. И те заемат определено пространство. Последващите събития могат да варират в зависимост от много фактори:
- Ключът за партициониране може да бъде както много малък (ден), така и много голям (няколко месеца).
- Конфигурацията на retention може да включва няколко значителни прага на агрегация на данни вътре в активната партиция (към която се записват метриките), или пък не.
- Ако данните са много, то най-старите парчета, които поради фоновите обединения могат вече да са огромни (при избор на неоптимален ключ за партизиране), няма да се обединяват сами с новите малки парчета.
И всичко завършва по един и същи начин. Мястото, заето от метриките в ClickHouse, само нараства, ако:
- не се прилага
OPTIMIZE ... FINALръчно или - не се вкарват данни във всички партиции на постоянно основание, за да се стартира след време фоново обединение.
Вторият метод изглежда най-прост за изпълнение и затова той е неправилен и е бил тестван на първо място.
Написах достатъчно прост скрипт на python, който изпращаше фалшиви метрики за всеки ден през последните 4 години и се пускаше всеки час от cron.
Тъй като цялата работа на ClickHouse DBMS е построена на принципа, че системата в крайна сметка ще свърши цялата фонова работа, но не е известно кога, не успях да изчакам момента, в който старите огромни парчета ще започнат да се обединяват с новите малки. Стана ясно, че трябва да се търси начин за автоматизиране на принудителните оптимизации.

Информацията в системните таблици на ClickHouse
Нека погледнем структурата на таблицата . Това е изчерпателна информация за всяко парче от всички таблици на сървъра ClickHouse. Включва, между другото, следните колони:
- име на БД (
database); - име на таблицата (
table); - име и ID на партицията (
partition&partition_id); - когато парчето е създадено (
modification_time); - минимална и максимална дата в парчето (партиционирането става по дни) (
min_date&max_date);
Има и таблица , със следните интересни полета:
- име на БД (
Tables.database); - име на таблицата (
Tables.table); - възраст на метриката, когато трябва да се приложи следващата агрегация (
age);
И така:
- Имаме таблица с парчета и таблица с правила за агрегация.
- Обединяваме техните пресечни точки и получаваме всички таблици *GraphiteMergeTree.
- Търсим всички партиции, в които:
- повече от едно парче
- или е настъпил моментът да се приложи следващото правило за агрегация, и
modification_timeпо-стари от този момент.
Реализация
Тази заявка
ИЗБЕРИТЕ
concat(p.database, '.', p.table) КАК table,
p.partition_id КАК partition_id,
p.partition КАК partition,
-- Найстарейшее "правило", которое можно будет применить к
-- партиции, но не в будущем, см (*)
max(g.age) КАК age,
-- Количество частей в партиции
countDistinct(p.name) КАК parts,
-- Для самой старшей метрики в партиции принимается 00:00:00 следующего дня
toDateTime(max(p.max_date + 1)) КАК max_time,
-- Когда необходимо оптимизировать партицию
max_time + age КАК rollup_time,
-- Когда самый старый кусок в партиции был обновлён
min(p.modification_time) КАК modified_at
ИЗ system.parts КАК p
INNER JOIN
(
-- Все правила для всех таблиц *GraphiteMergeTree
ИЗ system.graphite_retentions
МАССИВ JOIN Tables
ГРУППИРОВАТЬ ПО
database,
table,
age
) КАК g ON
(p.table = g.table)
И (p.database = g.database)
ГДЕ
-- Только активные куски
p.active
-- (*) И только строки, где правила агрегации уже должны быть применены
И ((toDateTime(p.max_date + 1) + g.age) < теперь())
ГРУППИРОВАТЬ ПО
table,
partition
ИМЕЕТ
-- Только партиции, которые младше момента оптимизации
(modified_at 1)
ORDER BY
table ASC,
partition ASC,
age ASCвозвращает каждую из партиций таблиц *GraphiteMergeTree, слияние которых должно привести к освобождению дискового пространства. Осталось только дело за малым: пройтись по всем ним с запросом OPTIMIZE ... FINAL. В конечной реализации также учтён тот момент, что партиции с активной записью трогать не нужно.
Именно это делает проект . Бывшие коллеги из Яндекс.Маркет опробовали его в продакшене, результат работы можно увидеть ниже.

Если запустить программу на сервере с ClickHouse, она просто начнёт работать в режиме демона. Раз в час будет выполняться запрос, проверяя, не появились ли новые партиции старше трёх суток, которые можно оптимизировать.
В ближайших планах — предоставить, по крайней мере, deb пакеты, а по возможности — ещё и rpm.
Вместо заключение
За прошедшие 9 с лишним месяцев я внутри своей компании провёл много времени, работая на стыке ClickHouse и graphite-web. Это был хороший опыт, результатом которого стал возможен скорый переход с whisper на ClickHouse в качестве хранилища метрик. Надеюсь, что эта статья станет чем-то вроде начала цикла о том, какие улучшения были внесены нами в различные части этого стека и что будет сделано в будущем.
Няколко литра бира и административни дни бяха вложени в разработването на запитването заедно с , за което искам да му благодаря. Също така за рецензирането на тази статия.
Източник: habr.com




