Archiviazione delle metriche: come siamo passati da Graphite+Whisper a Graphite+ClickHouse

Ciao a tutti! Nel suo ultimo articolo Ho scritto sull'organizzazione di un sistema di monitoraggio modulare per l'architettura dei microservizi. Niente resta fermo, il nostro progetto è in continua crescita, così come il numero di metriche memorizzate. Come abbiamo organizzato la transizione da Graphite+Whisper a Graphite+ClickHouse in condizioni di carico elevato, leggi le aspettative e i risultati della migrazione sotto il taglio.

Archiviazione delle metriche: come siamo passati da Graphite+Whisper a Graphite+ClickHouse

Prima di raccontarti come abbiamo organizzato il passaggio dall'archiviazione delle metriche in Graphite+Whisper a Graphite+ClickHouse, vorrei fornire informazioni sui motivi di tale decisione e sugli svantaggi di Whisper con cui abbiamo convissuto per molto tempo.

Problemi di grafite+Whisper

1. Carico elevato sul sottosistema del disco

Al momento della transizione ci arrivavano circa 1.5 milioni di parametri al minuto. Con un flusso di questo tipo, l'utilizzo del disco sui server è stato pari a circa il 30%. In generale, questo era abbastanza accettabile: tutto funzionava stabilmente, veniva scritto velocemente, letto velocemente... Fino a quando uno dei team di sviluppo non ha lanciato una nuova funzionalità e ha iniziato a inviarci 10 milioni di parametri al minuto. È stato allora che il sottosistema del disco si è rafforzato e abbiamo riscontrato un utilizzo del 100%. Il problema è stato risolto rapidamente, ma è rimasto un residuo.

2. Mancanza di replica e coerenza

Molto probabilmente, come tutti coloro che utilizzano/usano Graphite+Whisper, abbiamo riversato lo stesso flusso di parametri su più server Graphite contemporaneamente per creare tolleranza agli errori. E non ci sono stati problemi particolari con questo, fino al momento in cui uno dei server si è bloccato per qualche motivo. A volte siamo riusciti a recuperare un server caduto abbastanza velocemente e carbon-c-relay è riuscito a caricarvi i parametri dalla sua cache, ma a volte no. E poi c'è stato un buco nei parametri, che abbiamo riempito con rsync. La procedura è stata piuttosto lunga. L’unica cosa che redime era che ciò accadeva molto raramente. Inoltre, periodicamente abbiamo preso una serie casuale di parametri e li abbiamo confrontati con altri dello stesso tipo sui nodi vicini del cluster. In circa il 5% dei casi diversi valori erano diversi, cosa di cui non eravamo molto contenti.

3. Ampio ingombro

Poiché scriviamo in Graphite non solo l'infrastruttura, ma anche le metriche aziendali (e ora anche le metriche di Kubernetes), molto spesso otteniamo una situazione in cui la metrica contiene solo pochi valori e il file .wsp viene creato tenendo conto di tutta la conservazione periodo e occupa una quantità di spazio preassegnata, che per noi era di circa 2 MB. Il problema è ulteriormente aggravato dal fatto che nel tempo compaiono molti file simili e quando si creano report su di essi, la lettura dei punti vuoti richiede molto tempo e risorse.

Vorrei subito notare che i problemi sopra descritti possono essere affrontati con vari metodi e con diversi gradi di efficacia, ma più dati si iniziano a ricevere, più essi peggiorano.

Avendo tutto quanto sopra (tenendo conto di quanto precedente articoli), nonché un aumento costante del numero di parametri ricevuti, il desiderio di trasferire tutti i parametri a un intervallo di memorizzazione di 30 secondi. (fino a 10 secondi se necessario), abbiamo deciso di provare Graphite+ClickHouse come promettente alternativa a Whisper.

Grafite+ClickHouse. Aspettative

Dopo aver visitato diversi incontri dei ragazzi di Yandex, aver letto un paio di articoli su Habré, dopo aver esaminato la documentazione e trovato componenti validi per legare ClickHouse sotto Grafite, abbiamo deciso di agire!

Desidero ricevere quanto segue:

  • ridurre l'utilizzo del sottosistema disco dal 30% al 5%;
  • ridurre la quantità di spazio occupato da 1TB a 100GB;
  • essere in grado di ricevere 100 milioni di parametri al minuto nel server;
  • replica dei dati e tolleranza agli errori pronte all'uso;
  • non restare seduto su questo progetto per un anno ed effettuare la transizione entro un lasso di tempo ragionevole;
  • passare senza tempi di inattività.

Abbastanza ambizioso, vero?

Grafite+ClickHouse. Componenti

Per ricevere i dati tramite il protocollo Graphite e successivamente registrarli in ClickHouse, ho selezionato carbon-clickhouse (Golang).

Come database per l'archiviazione delle serie temporali è stata scelta l'ultima versione di ClickHouse, la versione stabile 1.1.54253. Si sono verificati problemi durante il lavoro: una montagna di errori si riversava nei registri e non era del tutto chiaro cosa farne. In discussione con Romano Lomonosov (autore di carbon-clickhouse, graphite-clickhouse e molti, molti altri) è stato scelto quello più vecchio versione 1.1.54236. Gli errori sono scomparsi: tutto ha iniziato a funzionare alla grande.

Selezionato per leggere i dati da ClickHouse grafite-lickhouse (Golang). Come API per Graphite − carbonapi (Golang). ClickHouse è stato utilizzato per organizzare la replica tra tabelle guardiano dello zoo. Per le metriche di routing, abbiamo lasciato il nostro amato carbonio-c-relè (C) (vedi articolo precedente).

Grafite+ClickHouse. Struttura della tabella

“grafite” è un database che abbiamo creato per monitorare le tabelle.

“graphite.metrics” - tabella con motore ReplicatedReplacingMergeTree (replicato Sostituzione di MergeTree). Questa tabella memorizza i nomi delle metriche e i relativi percorsi.

CREATE TABLE graphite.metrics ( Date Date, Level UInt32, Path String, Deleted UInt8, Version UInt32 ) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/replicator/graphite.metrics', ‘r1’, Date, (Level, Path), 8192, Version);

“graphite.data” - tabella con motore ReplicatedGraphiteMergeTree (replicato GraphiteMergeTree). Questa tabella memorizza i valori metrici.

CREATE TABLE graphite.data ( Path String, Value Float64, Time UInt32, Date Date, Timestamp UInt32 ) ENGINE = ReplicatedGraphiteMergeTree('/clickhouse/tables/replicator/graphite.data', 'r1', Date, (Path, Time), 8192, 'graphite_rollup')

"graphite.date_metrics" è una tabella compilata in modo condizionale con il motore ReplicatedReplacingMergeTree. Questa tabella registra i nomi di tutte le metriche rilevate durante il giorno. Le ragioni della sua creazione sono descritte nella sezione "I problemi" alla fine di questo articolo.

CREATE MATERIALIZED VIEW graphite.date_metrics ( Path String,  Level UInt32,  Date Date) ENGINE = ReplicatedReplacingMergeTree('/clickhouse/tables/replicator/graphite.date_metrics', 'r1', Date, (Level, Path, Date), 8192) AS SELECT toUInt32(length(splitByChar('.', Path))) AS Level, Date, Path FROM graphite.data

"graphite.data_stat" - una tabella riempita per condizione, con il motore ReplicatedAggregatingMergeTree (replicato AggregazioneMergeTree). Questa tabella registra il numero di metriche in entrata, suddivise in 4 livelli di nidificazione.

CREATE MATERIALIZED VIEW graphite.data_stat ( Date Date,  Prefix String,  Timestamp UInt32,  Count AggregateFunction(count)) ENGINE = ReplicatedAggregatingMergeTree('/clickhouse/tables/replicator/graphite.data_stat', 'r1', Date, (Timestamp, Prefix), 8192) AS SELECT toStartOfMonth(now()) AS Date, replaceRegexpOne(Path, '^([^.]+.[^.]+.[^.]+).*$', '1') AS Prefix, toUInt32(toStartOfMinute(toDateTime(Timestamp))) AS Timestamp, countState() AS Count FROM graphite.data  GROUP BY Timestamp, Prefix

Grafite+ClickHouse. Diagramma di interazione dei componenti

Archiviazione delle metriche: come siamo passati da Graphite+Whisper a Graphite+ClickHouse

Grafite+ClickHouse. Migrazione dei dati

Come ricordiamo dalle aspettative di questo progetto, il passaggio a ClickHouse dovrebbe avvenire senza tempi di inattività, di conseguenza abbiamo dovuto in qualche modo trasferire l'intero nostro sistema di monitoraggio sul nuovo spazio di archiviazione nel modo più trasparente possibile per i nostri utenti.
Ecco come lo abbiamo fatto.

  • È stata aggiunta una regola a carbon-c-relay per inviare un flusso aggiuntivo di metriche alla carbon-clickhouse di uno dei server che partecipano alla replica delle tabelle ClickHouse.

  • Abbiamo scritto un piccolo script in Python che, utilizzando la libreria Whisper-dump, legge tutti i file .wsp dal nostro archivio e invia questi dati alla carbon-clickhouse sopra descritta in 24 thread. Il numero di valori metrici accettati in carbon-clickhouse ha raggiunto i 125 milioni/min e ClickHouse non ha nemmeno sudato.

  • Abbiamo creato un DataSource separato in Grafana per eseguire il debug delle funzioni utilizzate nei dashboard esistenti. Abbiamo identificato un elenco di funzioni che abbiamo utilizzato, ma non sono state implementate in carbonapi. Abbiamo aggiunto queste funzioni e inviato PR agli autori di carbonapi (un ringraziamento speciale a loro).

  • Per cambiare il carico di lettura nelle impostazioni del bilanciatore, abbiamo cambiato gli endpoint da graphite-api (interfaccia API per Graphite+Whisper) a carbonapi.

Grafite+ClickHouse. risultati

  • ridotto utilizzo del sottosistema disco dal 30% all'1%;

    Archiviazione delle metriche: come siamo passati da Graphite+Whisper a Graphite+ClickHouse

  • ridotto lo spazio occupato da 1 TB a 300 GB;
  • abbiamo la capacità di ricevere sul server 125 milioni di metriche al minuto (picchi al momento della migrazione);
  • trasferito tutte le metriche a un intervallo di archiviazione di trenta secondi;
  • replicazione dei dati ricevuti e tolleranza agli errori;
  • commutato senza tempi di inattività;
  • Ci sono volute circa 7 settimane per completare tutto.

Grafite+ClickHouse. I problemi

Nel nostro caso c'erano alcune insidie. Questo è ciò che abbiamo riscontrato dopo la transizione.

  1. ClickHouse non sempre rilegge le configurazioni al volo; a volte è necessario riavviarlo. Ad esempio, nel caso della descrizione del cluster zookeeper nella configurazione di ClickHouse, non è stato utilizzato fino al riavvio del server clickhouse.
  2. Le richieste ClickHouse di grandi dimensioni non sono state soddisfatte, quindi in graphite-clickhouse la nostra stringa di connessione ClickHouse è simile alla seguente:
    url = "http://localhost:8123/?max_query_size=268435456&max_ast_elements=1000000"
  3. ClickHouse molto spesso rilascia nuove versioni di release stabili; queste possono contenere sorprese: fai attenzione.
  4. I contenitori creati dinamicamente in Kubernetes inviano un gran numero di parametri con una durata breve e casuale. Non ci sono molti punti per tali parametri e non ci sono problemi di spazio. Ma quando crea query, ClickHouse preleva un numero enorme di queste stesse metriche dalla tabella "metriche". Nel 90% dei casi non sono disponibili dati oltre la finestra temporale (24 ore). Ma il tempo viene impiegato per cercare questi dati nella tabella "dati" e alla fine si verifica un timeout. Per risolvere questo problema, abbiamo iniziato a mantenere una visione separata con le informazioni sulle metriche riscontrate durante la giornata. Pertanto, quando creiamo report (grafici) per contenitori creati dinamicamente, interroghiamo solo le metriche che sono state rilevate all'interno di una determinata finestra e non per l'intero tempo, il che ha accelerato significativamente la costruzione di report su di essi. Per la soluzione sopra descritta, ho raccolto clickhouse in grafite (forcella), che include l'implementazione dell'utilizzo della tabella date_metrics.

Grafite+ClickHouse. Tag

Con la versione 1.1.0 Graphite è diventata ufficiale tag di supporto. E stiamo pensando attivamente a cosa e come fare per supportare questa iniziativa nello stack grafite+clickhouse.

Grafite+ClickHouse. Rilevatore di anomalie

Sulla base dell'infrastruttura sopra descritta, abbiamo implementato un prototipo di rilevatore di anomalie e funziona! Ma di più su di lui nel prossimo articolo.

Iscriviti, premi la freccia su e sii felice!

Fonte: habr.com

Aggiungi un commento