ClickHouse + Graphite: kuidas märkimisväärselt vähendada kettaruumi tarbimist

ClickHouse + Graphite: kuidas märkimisväärselt vähendada kettaruumi tarbimist

Tere, habr.

Kui keegi kasutab süsteemi graphite-web ja on jõudnud salvestusruumi jõudlusprobleemide taha whisper (IO, kasutatud ketas ruum), siis tõenäosus, et ClickHouse'le kui asendajale on tähelepanu pööratud, peaks lähenema ühele. See väide eeldab, et metrikate demonina on juba kasutusel kolmanda osapoole rakendus, näiteks carbonwriter või go-carbon.

ClickHouse lahendab kirjeldatud probleemid hästi. Näiteks, pärast 2TiB andmete kolimist whisperist, mahtusid nad 300GiB. Ma ei hakka detailidesse laskuma, sellel teemal on piisavalt artikleid. Lisaks, hiljuti polnud meie ClickHouse salvestus mitte kõik hästi.

Kohustusliku ruumi probleemid

Esmapilgul peaks kõik hästi töötama. Järgides dokumentatsioon, loome metrikate salvestamise skeemi konfiguratsiooni (edasi retention), seejärel loome tabeli vastavalt valitud tagasiside soovitusele graphite-web jaoks: carbon-clickhouse+graphite-clickhouse või graphouse, sõltuvalt sellest, millist teeki kasutatakse. Ja… käivitub aeglane pomm.

Selleks, et mõista, milline see on, tuleb teada, kuidas toimivad sisestused ja andmete edasine elu tabelites mootortüüpide *MergeTree ClickHouse (diagrammid on pärit esitlusest. Aleksei Zatelepinilt):

  • Sisestatakse blok andmeid. Meie puhul on need metrikad.
    ClickHouse + Graphite: kuidas märkimisväärselt vähendada kettaruumi tarbimist
  • Iga selline block enne ketast kirjutamist sorteeritakse vastavalt võtmele CLR kasutaja määratletud agregaatfunktsioon, mis on määratud tabeli loomisel.
  • Pärast sorteerimist, tükk (part) andmeid kirjutatakse kettale.
    ClickHouse + Graphite: kuidas märkimisväärselt vähendada kettaruumi tarbimist
  • Server jälgib taustal, et selliseid tükkide arvu ei oleks liiga palju ja käivitab tausta ülendused (merge, edasi mergenid).
    ClickHouse + Graphite: kuidas märkimisväärselt vähendada kettaruumi tarbimist
    ClickHouse + Graphite: kuidas märkimisväärselt vähendada kettaruumi tarbimist
  • Server lõpetab mergenide automaatse käivitamise, kui andmed enam aktiivselt ei sisene partitsioon (partition), kuid protsessi saab käsitsi käivitada käsuga OPTIMIZE.
  • Kui partitsioonis on jäänud vaid üks tükk, siis ei saa tavalise käsuga merge'd käivitada, tuleb kasutada OPTIMIZE ... FINAL

Ja nii hakkavad esimesed metrikad saabuma. Ning nad hõivavad mingisuguse ruumi. Edasised sündmused võivad varieeruda sõltuvalt paljusid teguritest:

  • Partitsioneerimise võti võib olla kas väga väike (päev) või väga suur (mõned kuud).
  • Retention конфигурация может включать несколько значительных порогов агрегации данных внутри активной партиции (куда записываются метрики), а может и нет.
  • Если данных очень много, то самые ранние куски, которые из-за фоновых мержей могут уже стать огромными (при выборе неоптимального ключа партиционирования), не будут мержиться сами с новыми маленькими кусками.

И всё заканчивается всегда одинаково. Место, занимаемое метриками в ClickHouse, только растёт, если:

  • не применять OPTIMIZE ... FINAL вручную или
  • не вставлять данные во все партиции на постоянной основе, чтобы рано или поздно запустить фоновый мерж.

Второй способ кажется наиболее простым в реализации и, следовательно, он неправильный и был протестирован в первую очередь.
Я написал достаточно простой скрипт на python, который отправлял фиктивные метрики для каждого дня за последние 4 года и запускался каждый час кроном.
Поскольку вся работа ClickHouse DBMS построена на том, что эта система рано или поздно выполнит всю фоновую работу, но неизвестно когда, мне не удалось дождаться момента, когда старые огромные куски начнут мерж с новыми маленькими. Стало ясно, что нужно искать способ автоматизировать принудительные оптимизации.

ClickHouse + Graphite: kuidas märkimisväärselt vähendada kettaruumi tarbimist

Информация в системных таблицах ClickHouse

Давайте посмотрим на структуру таблицы system.parts. Это исчерпывающая информация о каждом куске всех таблиц на сервере ClickHouse. Содержит, в том числе, следующие столбцы:

  • имя базы данных (database);
  • имя таблицы (table);
  • имя и ID партиции (partition & partition_id);
  • время создания куска (modification_time);
  • минимальная и максимальная дата в куске (партиционирование происходит по дням) (min_date & max_date);

Также есть таблица system.graphite_retentions, со следующими интересными полями:

  • имя базы данных (Tables.database);
  • имя таблицы (Tables.table);
  • возраст метрики, когда должна быть применена следующая агрегация (age);

Nii:

  1. У нас есть таблица кусков и таблица правил агрегации.
  2. Объединяем их пересечение и получаем все таблицы *GraphiteMergeTree.
  3. Ищем все партиции, в которых:
    • больше одного куска
    • или настала пора применить следующее правило агрегации, и modification_time старше этого момента.

Rakendamine

Данный запрос

VALI
    concat(p.database, '.', p.table) KUI table,
    p.partition_id KUI partition_id,
    p.partition KUI partition,
    -- Kõige "vanem" reegel, mida saab rakendada
    -- partitsioonile, kuid mitte tulevikus, vt (*)
    max(g.age) KUI age,
    -- Osade arv partitsioonis
    countDistinct(p.name) KUI parts,
    -- Kõige vanemaks mõõdikuks partitsioonis peetakse järgmise päeva 00:00:00
    toDateTime(max(p.max_date + 1)) KUI max_time,
    -- Millal partitsioon tuleks optimeerida
    max_time + age KUI rollup_time,
    -- Millal kõige vanem tükk partitsioonis viimati uuendati
    min(p.modification_time) KUI modified_at
FROM system.parts KUI p
INNER JOIN
(
    -- Kõik reeglid kõikide tabelite *GraphiteMergeTree jaoks
    VALI
        Tables.database KUI database,
        Tables.table KUI table,
        age
    FROM system.graphite_retentions
    ARRAY JOIN Tables
    GROUP BY
        database,
        table,
        age
) KUI g ON
    (p.table = g.table)
    JA (p.database = g.database)
KUS
    -- Ainult aktiivsed tükid
    p.active
    -- (*) Ja ainult need read, kus aggregeerimise reeglid peaksid juba olema rakendatud
    JA ((toDateTime(p.max_date + 1) + g.age) < now())
GROUP BY
    table,
    partition
HAVING
    -- Ainult partitsioonid, mis on nooremad optimeerimise hetkest
    (modified_at  1)
KORDA
    table ASC,
    partition ASC,
    age ASC

tagastab iga *GraphiteMergeTree tabelite partitsiooni, mille ühinemine peaks vabastama kettaruumi. Jääb vaid tükkide mitmekordsus läbi käia käsuga OPTIMIZE ... FINAL. Lõplikus teostuses on samuti arvestatud, et aktiivse kirjutamisega partitsioone pole vaja puudutada.

Just seda teeb projekt graphite-ch-optimizer. Endised kolleegid Yandex.Market'ist katsetasid seda tootmises, töö tulemusi saab näha allpool.

ClickHouse + Graphite: kuidas märkimisväärselt vähendada kettaruumi tarbimist

Kui käivitada programm ClickHouse serveris, siis see lihtsalt töötab deemonirežiimis. Iga tunni järel käivitatakse päring, kontrollides, kas on tekkinud uusi partitsioone, mis on vanemad kui kolm päeva, mida võiks optimeerida.

Lähitulevikus on plaanis pakkuda vähemalt deb-pakette ja võimalusel ka rpm.

Lõpetuseks

Viimase 9 kuu jooksul olen oma ettevõttes InnoGames veetnud palju aega, olles ClickHouse ja graphite-web vahel. See oli hea kogemus, mille tulemuseks on peaaegu võimalik üleminek whisperilt ClickHouse'ile mõõtmete salvestamiseks. Loodan, et see artikkel on midagi, mis sarnaneb tsükli algusele selle kohta, milliseid täiustusi oleme teinud nende tehnoloogiate erinevates osades ja mida tulevikus veel tehakse.

Projekti taotluse arendamisele kulus mitu liitrit õlut ja administratiivpäevi koos v0devil, mille eest tahan talle oma tänu avaldada. Samuti selle artikli ülevaatamise eest.

Projektileht githubis

Allikas: habr.com

Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne hostimine veebilehtede jaoks DDoS-i kaitsega, VPS VDS serverid | ProHoster