ClickHouse + Graphite: jak znacząco zmniejszyć zużycie miejsca na dysku

ClickHouse + Graphite: jak znacząco zmniejszyć zużycie miejsca na dysku

Pozdrawiam, hab.

Jeśli ktoś wykorzystuje system siatka grafitowa i napotkał problem z wydajnością pamięci szept (IO, zużyte miejsce na dysku), wówczas szansa, że ​​ClickHouse zostanie obsadzony jako zamiennik, powinna wynosić jeden. To stwierdzenie oznacza, że ​​implementacja strony trzeciej jest już używana na przykład jako demon odbierający metryki karbonarz lub go-karbon.

ClickHouse dobrze rozwiązuje opisane problemy. Przykładowo po przesłaniu 2TiB danych z szeptu mieszczą się one w 300GiB. Nie będę się rozpisywał szczegółowo nad porównaniem, artykułów na ten temat jest mnóstwo. Poza tym do niedawna nie wszystko układało się idealnie z naszą pamięcią masową ClickHouse.

Problemy z zajętą ​​przestrzenią

Na pierwszy rzut oka wszystko powinno działać dobrze. Następny dokumentacja, utwórz konfigurację schematu przechowywania metryk (dalej retention), następnie utwórz tabelę zgodnie z rekomendacją wybranego backendu dla graphite-web: klikhouse z włókna węglowego+grafitowy klikhouse lub grafu, w zależności od używanego stosu. I... bomba zegarowa wybucha.

Aby zrozumieć który trzeba wiedzieć jak działają wstawki i dalsza droga życia danych w tabelach silników rodziny *Połącz drzewo ClickHouse (wykresy zaczerpnięte z презентации Aleksiej Zatelepin):

  • Wstawiono блок dane. W naszym przypadku pojawiły się metryki.
    ClickHouse + Graphite: jak znacząco zmniejszyć zużycie miejsca na dysku
  • Każdy taki blok przed zapisaniem na dysk jest sortowany według klucza. ORDER BYokreślone podczas tworzenia tabeli.
  • Po sortowaniu, кусок (part) dane są zapisywane na dysku.
    ClickHouse + Graphite: jak znacząco zmniejszyć zużycie miejsca na dysku
  • Serwer monitoruje w tle, żeby takich fragmentów nie było zbyt wiele i uruchamia tło слияния (merge, zwane dalej połączeniem).
    ClickHouse + Graphite: jak znacząco zmniejszyć zużycie miejsca na dysku
    ClickHouse + Graphite: jak znacząco zmniejszyć zużycie miejsca na dysku
  • Serwer sam przestaje wykonywać operacje scalania, gdy tylko dane przestaną aktywnie napływać do pliku партицию (partition), ale możesz uruchomić proces ręcznie za pomocą polecenia OPTIMIZE.
  • Jeśli na partycji pozostała tylko jedna część, nie będziesz mógł przeprowadzić scalania przy użyciu zwykłego polecenia; musisz użyć OPTIMIZE ... FINAL

Tak więc pojawiają się pierwsze metryki. I zajmują trochę miejsca. Późniejsze wydarzenia mogą się nieco różnić w zależności od wielu czynników:

  • Klucz partycjonowania może być bardzo mały (dzień) lub bardzo duży (kilka miesięcy).
  • Konfiguracja przechowywania może pasować do kilku znaczących progów agregacji danych w ramach aktywnej partycji (gdzie rejestrowane są metryki), ale może nie.
  • Jeśli danych jest dużo, to najwcześniejsze porcje, które ze względu na scalanie w tle mogą już być ogromne (jeśli wybierzesz nieoptymalny klucz partycjonowania), nie połączą się ze świeżymi małymi porcjami.

I zawsze kończy się tak samo. Miejsce zajmowane przez metryki w ClickHouse zwiększa się tylko wtedy, gdy:

  • nie aplikuj OPTIMIZE ... FINAL ręcznie lub
  • nie wstawiaj na bieżąco danych do wszystkich partycji, bo prędzej czy później rozpocznie się scalanie w tle

Druga metoda wydaje się najłatwiejsza do wdrożenia, dlatego jest błędna i została wypróbowana jako pierwsza.
Napisałem dość prosty skrypt w Pythonie, który wysyłał fałszywe dane dla każdego dnia przez ostatnie 4 lata i uruchamiał cron co godzinę.
Ponieważ całe działanie ClickHouse DBMS opiera się na tym, że system ten prędzej czy później wykona całą pracę w tle, ale nie wiadomo kiedy, nie mogłem się doczekać momentu, w którym stare ogromne kawałki raczą zacząć się łączyć z nowe, małe. Stało się jasne, że musimy poszukać sposobu na zautomatyzowanie wymuszonych optymalizacji.

ClickHouse + Graphite: jak znacząco zmniejszyć zużycie miejsca na dysku

Informacje w tabelach systemu ClickHouse

Przyjrzyjmy się strukturze tabeli części.systemu. To wyczerpujące informacje o każdym fragmencie wszystkich tabel na serwerze ClickHouse. Zawiera między innymi następujące kolumny:

  • nazwa bazy danych (database);
  • Nazwa tabeli (table);
  • nazwa i identyfikator partycji (partition & partition_id);
  • kiedy utwór powstał (modification_time);
  • minimalna i maksymalna data w sztuce (podział odbywa się według dni) (min_date & max_date);

Jest też stół system.graphite_retentions, z następującymi interesującymi polami:

  • nazwa bazy danych (Tables.database);
  • Nazwa tabeli (Tables.table);
  • wiek metryczny, kiedy należy zastosować kolejną agregację (age);

Tak więc:

  1. Mamy tabelę fragmentów i tabelę reguł agregacji.
  2. Łączymy ich przecięcie i otrzymujemy wszystkie tabele *GraphiteMergeTree.
  3. Poszukujemy wszystkich przegród, w których:
    • więcej niż jeden kawałek
    • lub nadszedł czas na zastosowanie kolejnej reguły agregacji, oraz modification_time starsze niż ta chwila.

realizacja

Ta prośba

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

zwraca każdą z partycji tabeli *GraphiteMergeTree, której połączenie powinno zwolnić miejsce na dysku. Pozostaje tylko przejrzeć je wszystkie z prośbą OPTIMIZE ... FINAL. Ostateczna realizacja uwzględnia także fakt, że nie ma konieczności dotykania partycji z aktywnym zapisem.

Właśnie to ma na celu projekt Optymalizator grafitowy. Byli koledzy z Yandex.Market wypróbowali to w produkcji, wynik pracy można zobaczyć poniżej.

ClickHouse + Graphite: jak znacząco zmniejszyć zużycie miejsca na dysku

Jeśli uruchomisz program na serwerze z ClickHouse, po prostu zacznie on działać w trybie demona. Raz na godzinę będzie wykonywane żądanie sprawdzające, czy pojawiły się nowe partycje starsze niż trzy dni, które można zoptymalizować.

Nasze najbliższe plany to dostarczenie co najmniej pakietów deb, a jeśli to możliwe, także pakietów RPM.

Zamiast zawierania

Przez ostatnie ponad 9 miesięcy pracowałem w mojej firmie innogames spędził dużo czasu majsterkując na styku ClickHouse i graphite-web. Było to dobre doświadczenie, które zaowocowało szybkim przejściem z szeptu na ClickHouse jako magazyn metryk. Mam nadzieję, że ten artykuł jest początkiem serii o tym, jakie ulepszenia wprowadziliśmy w różnych częściach tego stosu i co zostanie zrobione w przyszłości.

Kilka litrów piwa i dni administracyjnych poświęcono na opracowanie wniosku wraz z v0devil, za co chcę mu serdecznie podziękować. A także za recenzję tego artykułu.

Strona projektu na githubie

Źródło: www.habr.com

Dodaj komentarz