ClickHouse + Grafito: kiel signife redukti konsumon de diskspaco

ClickHouse + Grafito: kiel signife redukti konsumon de diskspaco

Saluton, habr.

Se iu ekspluatas la sistemon grafito-retejo kaj renkontis stokan rendimentoproblemon flustras (IO, diskospaco konsumita), tiam la ŝanco ke ClickHouse estis ĵetita kiel anstataŭaĵo devus tendenci al unu. Ĉi tiu deklaro implicas, ke triaparta efektivigo jam estas uzata kiel demono ricevanta metrikojn, ekzemple karbonoverkistogo-karbono.

ClickHouse bone solvas la priskribitajn problemojn. Ekzemple, post translokado de 2TiB de datumoj de flustro, ili konvenas en 300GiB. Mi ne detale detalos pri la komparo; estas multaj artikoloj pri ĉi tiu temo. Krome, ĝis antaŭ nelonge, ne ĉio estis perfekta kun nia ClickHouse-stokado.

Problemoj kun konsumita spaco

Unuavide, ĉio devus funkcii bone. Sekvante dokumentado, kreu agordon por la metrika stokadoskemo (pli retention), tiam kreu tabelon laŭ la rekomendo de la elektita backend por grafito-retejo: karbon-clickhouse+grafito-clickhousegrafozo, depende de kiu stako estas uzata. Kaj... la horloĝbombo eksplodas.

Por kompreni kiun, vi devas scii kiel funkcias enigaĵoj kaj la pluan vivvojon de datumoj en tabeloj de motoroj de la * familio.MergeTree ClickHouse (diagramoj prenitaj de prezentoj Aleksej Zatelepin):

  • enigita блок datumoj. En nia kazo, estis la metrikoj kiuj alvenis.
    ClickHouse + Grafito: kiel signife redukti konsumon de diskspaco
  • Ĉiu tia bloko estas ordigita laŭ la ŝlosilo antaŭ esti skribita al disko. ORDER BYspecifita dum kreado de la tabelo.
  • Post ordigo, кусок (part) datumoj estas skribitaj al disko.
    ClickHouse + Grafito: kiel signife redukti konsumon de diskspaco
  • La servilo monitoras en la fono tiel ke ne estas multaj tiaj pecoj, kaj lanĉas fonon слияния (merge, ĉi-poste kunfandi).
    ClickHouse + Grafito: kiel signife redukti konsumon de diskspaco
    ClickHouse + Grafito: kiel signife redukti konsumon de diskspaco
  • La servilo ĉesas funkcii kunfandiĝas memstare tuj kiam datumoj ĉesas aktive flui en la партицию (partition), sed vi povas komenci la procezon permane per la komando OPTIMIZE.
  • Se restas nur unu peco en la subdisko, tiam vi ne povos ruli la kunfandiĝon per la kutima komando; vi devas uzi OPTIMIZE ... FINAL

Do, la unuaj metrikoj alvenas. Kaj ili okupas iom da spaco. Postaj okazaĵoj povas varii iom depende de multaj faktoroj:

  • La dispartiga ŝlosilo povas esti aŭ tre malgranda (tage) aŭ tre granda (pluraj monatoj).
  • La konserva agordo povas ĝustigi plurajn signifajn datumajn agregsojlojn ene de la aktiva sekcio (kie metrikoj estas registritaj), aŭ eble ne.
  • Se estas multe da datumoj, tiam la plej fruaj pecoj, kiuj pro fona kunfandiĝo eble jam estas grandegaj (se vi elektas neoptimuman dispartigan ŝlosilon), ne kunfandiĝos kun freŝaj malgrandaj pecoj.

Kaj ĉiam finiĝas same. La spaco okupita de metrikoj en ClickHouse nur pliiĝas se:

  • ne aplikas OPTIMIZE ... FINAL permane aŭ
  • ne enmetu datumojn en ĉiujn subdiskojn daŭrante, tiel ke baldaŭ aŭ malfrue fono-kunfandiĝo komenciĝos

La dua metodo ŝajnas esti la plej facila por efektivigi kaj, tial, ĝi estas malĝusta kaj estis provita unue.
Mi skribis sufiĉe simplan python-skripton, kiu sendis simulajn metrikojn por ĉiutage dum la pasintaj 4 jaroj kaj kuris cron ĉiun horon.
Ĉar la tuta funkciado de ClickHouse DBMS baziĝas sur la fakto, ke ĉi tiu sistemo pli aŭ malpli frue faros la tutan fonan laboron, sed oni ne scias kiam, mi ne povis atendi la momenton, kiam la malnovaj grandegaj pecoj degnas komenci kunfandiĝi kun novaj malgrandaj. Evidentiĝis, ke ni bezonas serĉi manieron aŭtomatigi devigitajn optimumigojn.

ClickHouse + Grafito: kiel signife redukti konsumon de diskspaco

Informoj en ClickHouse-sistemaj tabeloj

Ni rigardu la tabelstrukturon sistemo.partoj. Ĉi tio estas ampleksa informo pri ĉiu peco de ĉiuj tabeloj sur la servilo ClickHouse. Enhavas, interalie, la sekvajn kolumnojn:

  • db nomo (database);
  • nomo de tabelo (table);
  • nomo kaj diskidentigilo (partition & partition_id);
  • kiam la peco estis kreita (modification_time);
  • minimuma kaj maksimuma dato en peco (dispartigo estas farita tage) (min_date & max_date);

Estas ankaŭ tablo sistemo.grafito_retenoj, kun la sekvaj interesaj kampoj:

  • db nomo (Tables.database);
  • nomo de tabelo (Tables.table);
  • metrika aĝo kiam la sekva agregado devus esti aplikita (age);

Do:

  1. Ni havas tabelon de pecoj kaj tabelon de agregaj reguloj.
  2. Ni kombinas ilian intersekciĝon kaj ricevas ĉiujn tabelojn *GraphiteMergeTree.
  3. Ni serĉas ĉiujn sekciojn en kiuj:
    • pli ol unu peco
    • aŭ venis la tempo por apliki la sekvan agregan regulon, kaj modification_time pli malnova ol ĉi tiu momento.

Реализация

Ĉi tiu peto

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

redonas ĉiun el la *GraphiteMergeTree-tabelsekcioj, kies kunfandiĝo devus liberigi diskospacon. La nura afero por fari estas trarigardi ilin ĉiujn kun peto OPTIMIZE ... FINAL. La fina efektivigo ankaŭ konsideras la fakton, ke ne necesas tuŝi sekciojn kun aktiva registrado.

Ĝuste ĉi tion faras la projekto grafito-ch-optimumigilo. Eksaj kolegoj de Yandex.Market provis ĝin en produktado, la rezulto de la laboro videblas sube.

ClickHouse + Grafito: kiel signife redukti konsumon de diskspaco

Se vi rulas la programon sur servilo kun ClickHouse, ĝi simple komencos funkcii en demona reĝimo. Unufoje hore peto estos ekzekutita, kontrolante ĉu novaj subdiskoj pli malnovaj ol tri tagoj aperis optimumeblaj.

Niaj tujaj planoj estas provizi almenaŭ deb-pakaĵojn, kaj se eble ankaŭ rpm.

Anstataŭ konkludo

Dum la pasintaj 9+ monatoj mi estis en mia firmao innogames pasigis multan tempon tuŝante ĉe la intersekco de ClickHouse kaj grafito-retejo. Ĝi estis bona sperto, kiu rezultigis rapidan transiron de flustro al ClickHouse kiel metrika stokado. Mi esperas, ke ĉi tiu artikolo estas io de la komenco de serio pri kiaj plibonigoj ni faris al diversaj partoj de ĉi tiu stako, kaj kio estos farita en la estonteco.

Pluraj litroj da biero kaj administraj tagoj estis elspezitaj por disvolvi la peton, kune kun v0diablo, pro kiu mi volas esprimi mian dankon al li. Kaj ankaŭ por revizii ĉi tiun artikolon.

Projekta paĝo sur github

fonto: www.habr.com

Aldoni komenton