ClickHouse + Graphite: hvordan redusere diskplassforbruket betydelig

ClickHouse + Graphite: hvordan redusere diskplassforbruket betydelig

Hilsen, habr.

Hvis noen utnytter systemet grafitt-nett og oppdaget et problem med lagringsytelsen hviske (IO, diskplass forbrukt), da burde sjansen for at ClickHouse ble castet som en erstatning tendere til en. Denne uttalelsen antyder at en tredjepartsimplementering allerede er brukt som en demon som mottar metrikker, for eksempel karbonskriver eller go-karbon.

ClickHouse løser de beskrevne problemene godt. For eksempel, etter å ha overført 2TiB med data fra whisper, passer de inn i 300GiB. Jeg vil ikke dvele ved sammenligningen i detalj; det er mange artikler om dette emnet. I tillegg, inntil nylig, var ikke alt perfekt med vår ClickHouse-lagring.

Problemer med forbrukt plass

Ved første øyekast skal alt fungere bra. Følgende dokumentasjon, lag en konfigurasjon for metrikklagringsskjemaet (videre retention), lag deretter en tabell i henhold til anbefalingen fra den valgte backend for graphite-web: karbon-klikkhus+grafitt-klikkhus eller graphouse, avhengig av hvilken stabel som brukes. Og... tidsinnstilt bombe går av.

For å forstå hvilken, må du vite hvordan innsatser fungerer og den videre livsveien til data i tabeller over motorer i *-familienMergeTree ClickHouse (diagrammer hentet fra presentasjoner Alexey Zatelepin):

  • Innsatt блок data. I vårt tilfelle var det beregningene som kom.
    ClickHouse + Graphite: hvordan redusere diskplassforbruket betydelig
  • Hver slik blokk sorteres i henhold til nøkkelen før den skrives til disk. ORDER BYspesifisert når du oppretter tabellen.
  • Etter sortering, кусок (part) data skrives til disk.
    ClickHouse + Graphite: hvordan redusere diskplassforbruket betydelig
  • Serveren overvåker i bakgrunnen slik at det ikke er mange slike biter, og starter bakgrunnen слияния (merge, heretter sammenslåing).
    ClickHouse + Graphite: hvordan redusere diskplassforbruket betydelig
    ClickHouse + Graphite: hvordan redusere diskplassforbruket betydelig
  • Serveren slutter å kjøre sammenslåinger av seg selv så snart data slutter å strømme aktivt inn i партицию (partition), men du kan starte prosessen manuelt med kommandoen OPTIMIZE.
  • Hvis det bare er ett stykke igjen i partisjonen, vil du ikke kunne kjøre sammenslåingen med den vanlige kommandoen; du må bruke OPTIMIZE ... FINAL

Så de første beregningene kommer. Og de tar litt plass. Påfølgende hendelser kan variere noe avhengig av mange faktorer:

  • Partisjoneringsnøkkelen kan enten være veldig liten (en dag) eller veldig stor (flere måneder).
  • Oppbevaringskonfigurasjonen kan passe til flere betydelige dataaggregeringsterskler innenfor den aktive partisjonen (hvor beregninger er registrert), eller kanskje ikke.
  • Hvis det er mye data, vil ikke de tidligste bitene, som på grunn av bakgrunnssammenslåing allerede er enorme (hvis du velger en ikke-optimal partisjoneringsnøkkel), slå seg sammen med ferske små biter.

Og det ender alltid likt. Plassen okkupert av beregninger i ClickHouse øker bare hvis:

  • gjelder ikke OPTIMIZE ... FINAL manuelt eller
  • ikke legg inn data i alle partisjoner fortløpende, slik at en bakgrunnssammenslåing før eller siden starter

Den andre metoden ser ut til å være den enkleste å implementere, og derfor er den feil og ble prøvd først.
Jeg skrev et ganske enkelt python-skript som sendte dummy-beregninger for hver dag de siste 4 årene og kjørte cron hver time.
Siden hele driften av ClickHouse DBMS er basert på det faktum at dette systemet før eller siden vil gjøre alt bakgrunnsarbeidet, men det er ikke kjent når, klarte jeg ikke å vente på øyeblikket da de gamle enorme stykkene verdig seg til å begynne å slå seg sammen med nye små. Det ble klart at vi måtte se etter en måte å automatisere tvungne optimaliseringer.

ClickHouse + Graphite: hvordan redusere diskplassforbruket betydelig

Informasjon i ClickHouse systemtabeller

La oss ta en titt på tabellstrukturen systemdeler. Dette er omfattende informasjon om hver del av alle tabellene på ClickHouse-serveren. Inneholder blant annet følgende kolonner:

  • db navn (database);
  • tabellnavn (table);
  • partisjonsnavn og ID (partition & partition_id);
  • når stykket ble opprettet (modification_time);
  • minimum og maksimum dato i et stykke (partisjonering gjøres etter dag) (min_date & max_date);

Det er også et bord system.graphite_retentions, med følgende interessante felt:

  • db navn (Tables.database);
  • tabellnavn (Tables.table);
  • metrisk alder når neste aggregering skal brukes (age);

Så:

  1. Vi har en tabell med biter og en tabell med aggregeringsregler.
  2. Vi kombinerer skjæringspunktet deres og får alle tabellene *GraphiteMergeTree.
  3. Vi ser etter alle partisjoner hvor:
    • mer enn ett stykke
    • eller tiden er inne for å bruke neste aggregeringsregel, og modification_time eldre enn dette øyeblikket.

implementering

Denne forespørselen

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 av *GraphiteMergeTree-tabellpartisjonene hvis sammenslåing skal frigjøre diskplass. Det eneste som gjenstår er å gå gjennom dem alle med en forespørsel OPTIMIZE ... FINAL. Den endelige implementeringen tar også hensyn til det faktum at det ikke er behov for å berøre partisjoner med aktivt opptak.

Det er nettopp dette prosjektet gjør grafitt-ch-optimizer. Tidligere kolleger fra Yandex.Market prøvde det i produksjon, resultatet av arbeidet kan ses nedenfor.

ClickHouse + Graphite: hvordan redusere diskplassforbruket betydelig

Hvis du kjører programmet på en server med ClickHouse, vil det ganske enkelt begynne å fungere i daemon-modus. En gang i timen vil en forespørsel bli utført, som sjekker om det har dukket opp nye partisjoner eldre enn tre dager som kan optimaliseres.

Våre umiddelbare planer er å gi minst deb-pakker, og om mulig også rpm.

I stedet for en konklusjon

I løpet av de siste 9+ månedene har jeg vært inne i selskapet mitt innogames brukte mye tid på å fikse i skjæringspunktet mellom ClickHouse og grafittnett. Det var en god opplevelse, som resulterte i en rask overgang fra hvisking til ClickHouse som metrikklagring. Jeg håper denne artikkelen er noe av begynnelsen på en serie om hvilke forbedringer vi har gjort på ulike deler av denne stabelen, og hva som vil bli gjort i fremtiden.

Det ble brukt flere liter øl og admindager på å utvikle forespørselen, sammen med v0devil, som jeg vil uttrykke min takknemlighet til ham for. Og også for å gjennomgå denne artikkelen.

Prosjektside på github

Kilde: www.habr.com

Legg til en kommentar