Hilsen habr.
Hvis nogen betjener systemet
ClickHouse løser de beskrevne problemer godt. For eksempel, efter at have hældt 2TiB data fra whisper, passer de ind i 300GiB. Jeg vil ikke dvæle ved sammenligningen i detaljer, der er nok artikler om dette emne. Derudover var alt indtil for nylig ikke perfekt med vores ClickHouse opbevaring.
Problemer med forbrugt plads
Ved første øjekast skulle alt fungere godt. Følge retention
), opret derefter en tabel i henhold til anbefalingen fra den valgte grafitweb-backend:
For at forstå hvilken, skal du vide, hvordan skær fungerer og den videre livsbane for data i tabeller over familiemotorer *MergeTree ClickHouse (diagrammer taget fra
- indsat
блок
data. I vores tilfælde er disse målinger.
- Hver sådan blok sorteres efter nøglen, før den skrives til disken.
ORDER BY
Den angivne, da tabellen blev oprettet. - Efter sortering,
кусок
(part
) data skrives til disk.
- Serveren overvåger i baggrunden, så der ikke er mange sådanne stykker, og starter baggrunden
слияния
(merge
, flet derefter).
- Serveren holder op med at lancere fusionerer af sig selv, så snart dataene stopper aktivt med at strømme ind
партицию
(partition
), men du kan starte processen manuelt med kommandoenOPTIMIZE
. - Hvis der kun er et stykke tilbage i partitionen, så vil du ikke være i stand til at starte sammenfletningen med den sædvanlige kommando, du skal bruge
OPTIMIZE ... FINAL
Så de første målinger ankommer. Og de fylder lidt. Efterfølgende begivenheder kan variere noget afhængigt af mange faktorer:
- Partitionsnøglen kan enten være meget lille (en dag) eller meget stor (adskillige måneder).
- Opbevaringskonfigurationen kan passe til flere væsentlige dataaggregeringstærskler inde i den aktive partition (hvor metrikken er skrevet), eller måske ikke.
- Hvis der er mange data, så vil de tidligste bidder, som allerede kan være enorme på grund af baggrundsfletning (når man vælger en ikke-optimal partitioneringsnøgle), ikke flette sig selv sammen med friske små bidder.
Og det ender altid det samme. Det sted, der er optaget af metrics i ClickHouse, vokser kun, hvis:
- gælder ikke
OPTIMIZE ... FINAL
manuelt eller - indsæt ikke data i alle partitioner løbende for at starte en baggrundsfletning før eller siden
Den anden metode ser ud til at være den nemmeste at implementere, og derfor er den forkert og blev testet i første omgang.
Jeg skrev et ret simpelt python-script, der sender dummy-metrics for hver dag i de sidste 4 år og kører hver time med cron.
Da alt arbejdet i ClickHouse DBMS er baseret på det faktum, at dette system før eller siden vil gøre alt baggrundsarbejdet, men det vides ikke hvornår, nåede jeg ikke at vente på det øjeblik, hvor de gamle enorme stykker værdiger sig til at begynde at smelte sammen med nye små. Det blev klart, at vi skulle finde en måde at automatisere tvungne optimeringer på.
Oplysninger i ClickHouse-systemtabeller
Lad os tage et kig på strukturen af tabellen
- database navn (
database
); - tabel navn (
table
); - partitionsnavn og ID (
partition
&partition_id
); - da stykket blev skabt (
modification_time
); - minimum og maksimum dato i klumpen (opdeling er efter dag) (
min_date
&max_date
);
Der er også et bord
- database navn (
Tables.database
); - tabel navn (
Tables.table
); - alderen for metrikken, når den næste aggregering skal anvendes (
age
);
So:
- Vi har en tabel med bidder og en tabel med aggregeringsregler.
- Vi forener deres skæringspunkt, og vi modtager alle *GraphiteMergeTree-tabeller.
- Vi leder efter alle partitioner, hvor:
- mere end et stykke
- eller tiden er inde til at anvende den næste sammenlægningsregel, og
modification_time
ældre end dette øjeblik.
implementering
Denne anmodning
SELECT
concat(p.database, '.', p.table) AS table,
p.partition_id AS partition_id,
p.partition AS partition,
-- Самое "старое" правило, которое может быть применено для
-- партиции, но не в будущем, см (*)
max(g.age) AS age,
-- Количество кусков в партиции
countDistinct(p.name) AS parts,
-- За самую старшую метрику в партиции принимается 00:00:00 следующего дня
toDateTime(max(p.max_date + 1)) AS max_time,
-- Когда партиция должна быть оптимизированна
max_time + age AS rollup_time,
-- Когда самый старый кусок в партиции был обновлён
min(p.modification_time) AS modified_at
FROM system.parts AS p
INNER JOIN
(
-- Все правила для всех таблиц *GraphiteMergeTree
SELECT
Tables.database AS database,
Tables.table AS table,
age
FROM system.graphite_retentions
ARRAY JOIN Tables
GROUP BY
database,
table,
age
) AS g ON
(p.table = g.table)
AND (p.database = g.database)
WHERE
-- Только активные куски
p.active
-- (*) И только строки, где правила аггрегации уже должны быть применены
AND ((toDateTime(p.max_date + 1) + g.age) < now())
GROUP BY
table,
partition
HAVING
-- Только партиции, которые младше момента оптимизации
(modified_at < rollup_time)
-- Или с несколькими кусками
OR (parts > 1)
ORDER BY
table ASC,
partition ASC,
age ASC
returnerer hver af *GraphiteMergeTree tabelpartitionerne, der skal flettes for at frigøre diskplads. Det er kun tilfældet for små ting: gennemgå dem alle med en anmodning OPTIMIZE ... FINAL
. Den endelige implementering tog også højde for, at der ikke er behov for at røre partitioner med en aktiv registrering.
Det er, hvad projektet gør.
Hvis du kører programmet på en server med ClickHouse, vil det simpelthen begynde at arbejde i dæmontilstand. En gang i timen vil der blive udført en forespørgsel, som kontrollerer, om der er nye partitioner, der er ældre end tre dage, som kan optimeres.
I den nærmeste fremtid - for at give mindst deb-pakker, og hvis muligt - også rpm.
I stedet for en konklusion
I de sidste 9+ måneder har jeg været inde i mit firma
Der blev brugt adskillige liter øl og admin-dage på udviklingen af forespørgslen, sammen med
Kilde: www.habr.com