Hallo zusammen! In meinem habe ich über die Organisation eines modularen Monitoring-Systems für mikroservices Architektur geschrieben. Nichts steht still, unser Projekt wächst ständig, und die Anzahl der gespeicherten Metriken ebenfalls. Wie wir den Übergang von Graphite+Whisper zu Graphite+ClickHouse unter Hochlastbedingungen organisiert haben, welche Erwartungen wir daran hatten und welche Ergebnisse die Migration brachte, lesen Sie weiter unten.

Bevor ich erzähle, wie wir den Übergang von der Speicherung der Metriken in Graphite+Whisper auf Graphite+ClickHouse organisiert haben, möchte ich Informationen über die Gründe für diese Entscheidung und die Nachteile von Whisper geben, mit denen wir über einen längeren Zeitraum gelebt haben.
Probleme mit Graphite+Whisper
1. Hohe Last auf dem Speichersystem
Zum Zeitpunkt des Übergangs hatten wir etwa 1,5 Millionen Metriken pro Minute. Bei diesem Durchsatz lag die Speicherauslastung auf den Servern bei ca. 30%. Insgesamt war das ziemlich akzeptabel — alles lief stabil, es wurde schnell geschrieben und gelesen… Bis eines der Entwicklungsteams ein neues Feature veröffentlichte und uns 10 Millionen Metriken pro Minute zu schicken begann. Da wurde das Speichersystem stark belastet, und wir sahen eine 100%ige Auslastung. Das Problem konnte schnell gelöst werden, aber der Nachgeschmack blieb.
2. Fehlende Replikation und Konsistenz
Wahrscheinlich wie alle, die Graphite+Whisper verwenden/benutzt haben, haben wir einen identischen Metrikfluss gleichzeitig auf mehrere Graphite-Server geleitet, um Ausfallsicherheit zu gewährleisten. Damit gab es nicht wirklich Probleme — bis einer der Server aus irgendeinem Grund ausfiel. Manchmal schafften wir es, den ausgefallenen Server schnell wieder hochzufahren, und carbon-c-relay konnte die Metriken aus seinem Cache in ihn einspeisen, manchmal jedoch nicht. Und dann gab es in den Metriken eine Lücke, die wir mit rsync geschlossen haben. Das Verfahren dauerte ziemlich lange. Rettung brachte nur, dass so etwas sehr selten vorkam. Außerdem haben wir periodisch einen zufälligen Satz von Metriken genommen und sie mit ähnlichen auf benachbarten Knoten des Clusters verglichen. In etwa 5% der Fälle hatten einige Werte Abweichungen, was uns nicht besonders erfreute.
3. Großer Platzbedarf
Da wir in Graphite nicht nur Infrastruktur-, sondern auch Geschäftsmesswerte (und nun auch Metriken aus Kubernetes) erfassen, kommt es häufig vor, dass in einer Metrik nur wenige Werte vorhanden sind, während die .wsp-Datei unter Berücksichtigung des gesamten Retention-Zeitraums erstellt wird und den vorab festgelegten Speicherplatz von ~2 MB einnimmt. Das Problem wird noch verschärft, da im Laufe der Zeit viele solcher Dateien entstehen und beim Erstellen von Berichten über diese viele Zeit und Ressourcen benötigt werden, um die leeren Punkte zu lesen.
Zunächst möchte ich darauf hinweisen, dass man die oben beschriebenen Probleme mit verschiedenen Methoden und unterschiedlicher Effizienz angehen kann, aber je mehr Daten Sie erhalten, desto ausgeprägter werden diese Probleme.
Unter Berücksichtigung des oben Genannten (unter Berücksichtigung der vorherigen ), sowie des ständigen Wachstums der empfangenen Metriken und dem Wunsch, alle Metriken auf einem Speicherrhythmus von 30 Sekunden (bei Bedarf bis zu 10 Sekunden) zu übertragen, haben wir beschlossen, Graphite+ClickHouse als vielversprechende Alternative zu Whisper auszuprobieren.
Graphite+ClickHouse. Erwartungen
Nachdem wir einige Meetups mit den Kollegen von Yandex besucht, , die Dokumentation durchgesehen und vernünftige Komponenten zum Binden von ClickHouse an Graphite gefunden haben, haben wir beschlossen, zu handeln!
Wir wollten Folgendes erreichen:
- die Nutzung des Speichers von 30% auf 5% zu senken;
- den benötigten Speicherplatz von 1 TB auf 100 GB zu reduzieren;
- die Möglichkeit zu haben, 100 Millionen Metriken pro Minute auf den Server zu empfangen;
- Datenreplikation und Ausfallsicherheit sofort verfügbar;
- nicht ein Jahr an diesem Projekt zu arbeiten und den Übergang in einem vernünftigen Zeitraum zu schaffen;
- ohne Ausfallzeiten umzuschalten.
Ziemlich ambitioniert, oder?
Graphite+ClickHouse. Komponenten
Um Daten über das Graphite-Protokoll zu erhalten und anschließend in ClickHouse zu schreiben, wurde entschieden, (golang).
Als Datenbank für die Speicherung von Zeitreihen wurde die zu diesem Zeitpunkt neueste stabile Version von ClickHouse 1.1.54253 gewählt. Bei der Arbeit damit traten Probleme auf: eine Menge Fehler wurden in die Logs geschrieben, und es war nicht ganz klar, was damit zu tun war. In der Diskussion mit (Autor von carbon-clickhouse, graphite-clickhouse und vielen anderen Projekten) wurde eine ältere Version ausgewählt. Die Fehler verschwanden – alles funktionierte einwandfrei.
Für das Auslesen von Daten aus ClickHouse wurde gewählt: (golang). Als API-Schnittstelle für Graphite – (golang). Für die Organisation der Replikation zwischen den ClickHouse-Tabellen wurde verwendet . Für das Routing der Metriken haben wir unser heiß geliebtes (C) .
Graphite+ClickHouse. Die Struktur der Tabellen
„graphite“ – die von uns erstellte Datenbank für Überwachungstabellen.
„graphite.metrics“ – Tabelle mit dem Engine ReplicatedReplacingMergeTree (replizierter ). In dieser Tabelle werden die Namen der Metriken und deren Pfade gespeichert.
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“ – Tabelle mit dem Engine ReplicatedGraphiteMergeTree (replizierter ). In dieser Tabelle werden die Werte der Metriken gespeichert.
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“ – Tabelle, die bedingt gefüllt wird, mit dem Engine ReplicatedReplacingMergeTree. In diese Tabelle werden die Namen aller Metriken geschrieben, die im Laufe eines Tages aufgetreten sind. Die Gründe für die Erstellung sind im Abschnitt am Ende dieses Artikels beschrieben.
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“ – Tabelle, die bedingt gefüllt wird, mit dem Engine ReplicatedAggregatingMergeTree (replizierter ). In diese Tabelle wird die Anzahl der eingehenden Metriken mit einer Aufschlüsselung bis zu 4 Ebenen gespeichert.
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, PrefixGraphite+ClickHouse. Das Schema der Interaktion der Komponenten

Graphite+ClickHouse. Migration von Daten
Wie wir uns aus den Erwartungen an dieses Projekt erinnern, sollte der Übergang zu ClickHouse ohne Ausfallzeiten erfolgen, entsprechend mussten wir unsere gesamte Überwachungssystem so nahtlos wie möglich auf das neue Speicherformat umstellen, ohne dass unsere Benutzer etwas davon bemerkten.
So haben wir das gemacht.
Wir haben eine Regel in carbon-c-relay hinzugefügt, um einen zusätzlichen Strom von Metriken an carbon-clickhouse eines der Server zu senden, die an der Replikation der ClickHouse-Tabellen teilnehmen.
Wir haben ein kleines Skript in Python geschrieben, das mit der Bibliothek whisper-dump alle .wsp-Dateien aus unserem Speicher ausgelesen hat und diese Daten in das oben beschriebene carbon-clickhouse in 24 Streams gesendet hat. Die Anzahl der empfangenen Metriken in carbon-clickhouse erreichte 125 Millionen pro Minute, und ClickHouse kam dabei nicht ins Schwitzen.
Wir haben eine separate Datenquelle in Grafana erstellt, um die Funktionen zu debuggen, die in den bestehenden Dashboards verwendet werden. Wir haben eine Liste von Funktionen identifiziert, die wir verwendet haben, die jedoch nicht in carbonapi implementiert waren. Diese Funktionen haben wir nachträglich hinzugefügt und PRs an die Autoren von carbonapi gesendet (ein großes Dankeschön an sie).
- Um die Leselast zu verschieben, haben wir in den Einstellungen der Load Balancer die Endpunkte von graphite-api (API-Schnittstelle für Graphite+Whisper) auf carbonapi geändert.
Graphite+ClickHouse. Ergebnisse
Wir haben die Auslastung des Speichersystems von 30 % auf 1 % gesenkt;

- Wir haben den belegten Speicherplatz von 1 TB auf 300 GB reduziert;
- Wir haben die Möglichkeit, 125 Millionen Metriken pro Minute auf den Server zu empfangen (Spitzen während der Migration);
- Wir haben alle Metriken auf ein Intervall von 30 Sekunden zur Speicherung umgestellt;
- Wir haben Datenreplikation und Ausfallsicherheit erhalten;
- Wir haben ohne Ausfallzeiten umgeschaltet;
- Insgesamt haben wir dafür etwa 7 Wochen gebraucht.
Graphite+ClickHouse. Probleme
In unserem Fall gab es auch einige versteckte Schwierigkeiten. Hier sind die Probleme, mit denen wir nach dem Wechsel konfrontiert wurden.
- ClickHouse liest nicht immer die Konfigurationen zur Laufzeit neu, manchmal muss man es neu starten. Zum Beispiel bei der Beschreibung des Zookeeper-Clusters in der ClickHouse-Konfiguration – sie wurde bis zum Neustart des clickhouse-servers nicht angewendet.
- Große Abfragen wurden in ClickHouse nicht verarbeitet, daher sieht unsere Verbindung zu ClickHouse in graphite-clickhouse folgendermaßen aus:
url = "http://localhost:8123/?max_query_size=268435456&max_ast_elements=1000000" - In ClickHouse erscheinen ziemlich oft neue Versionen stabiler Releases, in denen Überraschungen auftreten können: Seien Sie vorsichtig.
- Dynamisch erstellte Container in Kubernetes senden eine große Menge an Metriken mit kurzer und zufälliger Lebensdauer. Es gibt nicht viele Punkte für diese Metriken, und es gibt keine Platzprobleme. Doch beim Erstellen von Abfragen zieht ClickHouse eine riesige Anzahl dieser Metriken aus der Tabelle ‚metrics‘ hoch. In 90 % der Fälle sind die Daten dazu für das Zeitfenster (24 Stunden) nicht verfügbar. Die Zeit, die benötigt wird, um diese Daten in der Tabelle ‚data‘ zu finden, summiert sich und führt schließlich zu einem Timeout. Um dieses Problem zu lösen, haben wir begonnen, eine separate Ansicht mit Informationen über die Metriken zu führen, die im Laufe eines Tages angezeigt wurden. Auf diese Weise fragen wir beim Erstellen von Berichten (Grafiken) zu dynamisch erstellten Containern nur die Metriken ab, die innerhalb des vorgegebenen Zeitfensters aufgetreten sind, anstatt über die gesamte Zeit, was die Erstellung der Berichte erheblich beschleunigt hat. , einschließlich der Implementierung der Arbeit mit der Tabelle date_metrics.
Graphite+ClickHouse. Tags
Seit Version 1.1.0 unterstützt Graphite offiziell . Und wir denken aktiv darüber nach, was und wie wir tun müssen, um diese Initiative im Stack graphite+clickhouse zu unterstützen.
Graphite+ClickHouse. Anomalie-Detektor
Auf Basis der oben beschriebenen Infrastruktur haben wir einen Prototyp des Anomalie-Detektors entwickelt, und er funktioniert! Aber darüber wird im nächsten Artikel berichtet.
Folgt uns, drückt den Daumen nach oben und bleibt glücklich!
Quelle: habr.com

