Zabbix ist ein Überwachungssystem. Wie jedes andere System sieht es sich mit drei Hauptproblemen aller Überwachungssysteme konfrontiert: Datensammlung und -verarbeitung, Speicherung der Historie und deren Bereinigung.
Die Phasen der Datenakquise, -verarbeitung und -speicherung benötigen Zeit. Wenig, aber für ein großes System kann das zu erheblichen Verzögerungen führen. Das Problem der Speicherung ist eine Frage des Zugriffs auf die Daten. Diese werden für Berichte, Prüfungen und Trigger verwendet. Verzögerungen beim Zugriff auf die Daten beeinflussen ebenfalls die Leistung. Wenn Datenbanken wachsen, müssen veraltete Daten gelöscht werden. Das Löschen ist ein ressourcenintensiver Prozess, der auch einen Teil der Ressourcen beansprucht.

Die Probleme mit Verzögerungen bei der Sammlung und Speicherung in Zabbix werden durch Caching gelöst: verschiedene Arten von Caches, Caching in der Datenbank. Für das dritte Problem ist Caching jedoch nicht geeignet, weshalb in Zabbix TimescaleDB eingesetzt wird. Darüber wird sprechen Andrei Guschin — Ingenieur im technischen Support . Andrei ist seit über 6 Jahren im Zabbix-Support tätig und hat direkte Erfahrung mit der Leistung.
Wie funktioniert TimescaleDB, welche Leistung kann sie im Vergleich zu gewöhnlichem PostgreSQL bieten? Welche Rolle spielt Zabbix für die Datenbank TimescaleDB? Wie startet man von Grund auf und wie migriert man von PostgreSQL und welche Konfiguration bietet die beste Leistung? All dies kommt im weiteren Verlauf.

Leistungsherausforderungen
Jedes Überwachungssystem sieht sich bestimmten Leistungsherausforderungen gegenüber. Ich werde über drei von ihnen sprechen: Datensammlung und -verarbeitung, Speicherung, Bereinigung der Historie.
Schnelle Datensammlung und -verarbeitung. Ein gutes Überwachungssystem sollte alle Daten schnell erfassen und sie gemäß den Triggerbedingungen — nach eigenen Kriterien — verarbeiten. Nach der Verarbeitung sollte das System diese Daten auch zügig in der Datenbank speichern, um sie später nutzen zu können.
Speicherung der Historie. Ein gutes Überwachungssystem sollte die Historie in der Datenbank speichern und einen benutzerfreundlichen Zugriff auf die Metriken ermöglichen. Die Historie ist notwendig, um sie in Berichten, Grafiken, Triggern, Schwellenwerten und berechneten Datenelementen für Benachrichtigungen zu verwenden.
Bereinigung der Historie. Manchmal kommt der Tag, an dem Sie keine Metriken mehr speichern müssen. Warum benötigen Sie Daten, die vor 5 Jahren, einem oder zwei Monaten gesammelt wurden? Einige Knoten wurden entfernt, einige Hosts oder Metriken sind nicht mehr erforderlich, weil sie veraltet sind und nicht mehr gesammelt werden. Ein gutes Überwachungssystem sollte historische Daten speichern und diese gelegentlich löschen, um das Datenbankwachstum zu begrenzen.
Die Reinigung von veralteten Daten ist eine kritische Frage, die sich stark auf die Leistung der Datenbank auswirkt.
Caching in Zabbix
In Zabbix werden der erste und der zweite Aufruf durch Caching gelöst. Für das Sammeln und Verarbeiten von Daten wird der Arbeitsspeicher verwendet. Zum Speichern gibt es Historien in Triggern, Grafiken und berechneten Datenelementen. Auf der Datenbankseite ist ein gewisses Caching für grundlegende Abfragen vorhanden, beispielsweise für Grafiken.
Caching auf der Seite des Zabbix-Servers ist:
- ConfigurationCache;
- ValueCache;
- HistoryCache;
- TrendsCache.
Betrachten wir diese näher.
ConfigurationCache
Dies ist der Hauptcache, in dem wir Metriken, Hosts, Datenelemente, Trigger speichern — alles, was für die Vorverarbeitung und das Sammeln von Daten erforderlich ist.

All dies wird im ConfigurationCache gespeichert, um unnötige Datenbankanfragen zu vermeiden. Nach dem Start des Servers aktualisieren wir diesen Cache, erstellen und aktualisieren regelmäßig die Konfigurationen.
Datensammlung
Das Schema ist ziemlich groß, aber das Wesentliche ist Sammler. Dies sind verschiedene „Poller“ — Sammelprozesse. Sie sind für verschiedene Arten der Datensammlung verantwortlich: Sie sammeln Daten über SNMP, IPMI, und leiten dies alles zur Vorverarbeitung weiter.
Die Sammler sind mit einer orangefarbenen Linie umrandet.
In Zabbix gibt es berechnete aggregierte Datenelemente, die benötigt werden, um Prüfungen zu aggregieren. Wenn wir sie haben, holen wir die Daten für sie direkt aus dem ValueCache.
PreProcessing HistoryCache
Alle Sammler nutzen den ConfigurationCache, um Aufgaben zu erhalten. Danach leiten sie diese zur Vorverarbeitung weiter.

Die Vorverarbeitung nutzt den ConfigurationCache, um Schritte der Vorverarbeitung zu erhalten. Sie verarbeitet diese Daten auf verschiedene Weise.
Nach der Datenverarbeitung durch die Vorverarbeitung speichern wir sie im HistoryCache, um sie zu verarbeiten. Damit endet das Sammeln von Daten und wir gehen zum Hauptprozess in Zabbix über — history syncer, da dies eine monolithische Architektur ist.
Hinweis: Die Vorverarbeitung ist eine recht aufwendige Operation. Ab Version 4.2 wurde sie auf den Proxy ausgelagert. Wenn Sie ein sehr großes Zabbix mit vielen Datenelementen und einer hohen Abfragfrequenz haben, erleichtert dies die Arbeit erheblich.
ValueCache, Verlauf und Trends Cache
Der History Syncer ist der Hauptprozess, der jedes Datenelement atomar verarbeitet, das heißt, jeden Wert.
Der History Syncer nimmt Werte aus dem HistoryCache und überprüft in der Konfiguration das Vorhandensein von Triggern für Berechnungen. Wenn sie vorhanden sind, berechnet er.
Der History Syncer erstellt ein Ereignis, eine Eskalation, um Benachrichtigungen zu erstellen, falls es in der Konfiguration erforderlich ist, und protokolliert sie. Wenn Triggers für die anschließende Verarbeitung vorhanden sind, merkt sich dieser Wert im ValueCache, um nicht auf die Verlaufstabelle zuzugreifen. So wird der ValueCache mit den Daten gefüllt, die zur Berechnung der Trigger und berechneten Elemente erforderlich sind.
Der History Syncer schreibt alle Daten in die Datenbank, und diese in die Festplatte. Der Verarbeitungsprozess endet damit.

Caching in der Datenbank
Auf der Seite der Datenbank gibt es verschiedene Caches, wenn Sie Grafiken oder Berichte über Ereignisse anzeigen möchten:
Innodb_buffer_poolauf der MySQL-Seite;shared_buffersauf der PostgreSQL-Seite;effective_cache_sizeauf der Oracle-Seite;shared_poolauf der DB2-Seite.
Es gibt noch viele andere Caches, aber dies sind die wichtigsten für alle Datenbanken. Sie ermöglichen es, die Daten, die häufig für Abfragen erforderlich sind, im Arbeitsspeicher zu halten. Sie haben ihre eigenen Technologien dafür.
Die Leistung der Datenbank ist kritisch wichtig.
Der Zabbix-Server sammelt ständig Daten und protokolliert sie. Bei einem Neustart liest er ebenfalls aus dem Verlauf, um den ValueCache zu füllen. Skripte und Berichte verwenden Zabbix API, die auf der Grundlage der Weboberfläche basiert. Die Zabbix API greift auf die Datenbank zu und erhält die erforderlichen Daten für Grafiken, Berichte, Ereignislisten und aktuelle Probleme.

Zur Visualisierung — Grafana. Bei unseren Nutzern ist dies eine beliebte Lösung. Sie kann direkt Anfragen über die Zabbix API an die Datenbank senden und schafft damit eine gewisse Konkurrenz beim Abrufen von Daten. Daher ist eine feinere und bessere Konfiguration der Datenbank erforderlich, um der schnellen Ausgabe von Ergebnissen und Tests gerecht zu werden.
Housekeeper
Der dritte Leistungsaufruf in Zabbix ist die Bereinigung des Verlaufs mithilfe von Housekeeper. Er beachtet alle Einstellungen — in den Datenelementen ist angegeben, wie lange die Dynamik der Veränderungen (Trends) in Tagen aufbewahrt werden soll.
TrendsCache berechnen wir in Echtzeit. Wenn Daten eingehen, aggregieren wir sie über eine Stunde und speichern sie in Tabellen für die Dynamik der Veränderungen von Trends.
Der Housekeeper wird gestartet und entfernt Informationen aus der Datenbank mit gewöhnlichen «selects». Das ist nicht immer effizient, was man an den Leistungsdiagrammen interner Prozesse erkennen kann.

Das rote Diagramm zeigt, dass der History Syncer ständig beschäftigt ist. Das orange Diagramm oben zeigt den Housekeeper, der ständig gestartet wird. Er wartet darauf, dass die Datenbank alle Zeilen entfernt, die er festgelegt hat.
Wann sollte man den Housekeeper deaktivieren? Zum Beispiel, wenn es eine «Item ID» gibt und die letzten 5.000 Zeilen über einen bestimmten Zeitraum gelöscht werden sollen. Natürlich geschieht dies über Indizes. In der Regel ist der Datensatz jedoch sehr groß, und die Datenbank liest dennoch von der Festplatte und hebt in den Cache. Dies ist immer eine sehr teure Operation für die Datenbank und kann je nach Größe der Datenbank zu Leistungsproblemen führen.

Man kann den Housekeeper einfach deaktivieren. Im Web-Interface gibt es eine Einstellung in «Administration general» für den Housekeeper. Wir deaktivieren das interne Housekeeping für die interne Trendhistorie, und er verwaltet dies nicht mehr.
Der Housekeeper wurde deaktiviert, die Diagramme haben sich stabilisiert – welche Probleme könnten in diesem Fall auftreten und was könnte bei der Lösung des dritten Leistungsaufrufs helfen?
Partitionierung
In der Regel wird die Partitionierung auf verschiedene Weise in jeder relationalen Datenbank konfiguriert, die ich aufgelistet habe. Jede hat ihre eigene Technologie, aber sie sind im Allgemeinen ähnlich. Die Erstellung einer neuen Partition führt oft zu bestimmten Problemen.
In der Regel werden Partitionen je nach «setup» – der Menge an Daten, die an einem Tag erzeugt werden – konfiguriert. Normalerweise wird die Partitionierung für einen Tag festgelegt, das ist das Minimum. Für die Trends einer neuen Partition – für 1 Monat.
Die Werte können sich im Falle eines sehr großen «setup» ändern. Wenn das kleine «setup» bis zu 5.000 nvps (neue Werte pro Sekunde) beträgt, beträgt der Durchschnitt zwischen 5.000 und 25.000, und groß ist über 25.000 nvps. Dies sind große und sehr große Installationen, die eine sorgfältige Konfiguration der Datenbank erfordern.
Bei sehr großen Installationen kann ein Zeitraum von einem Tag nicht optimal sein. Ich habe bei MySQL Partitionen von 40 GB und mehr pro Tag gesehen. Dies ist eine sehr große Datenmenge, die zu Problemen führen kann, und sie muss verkleinert werden.
Was bringt die Partitionierung?
Partitionierung von Tabellen. Oft sind dies separate Dateien auf der Festplatte. Der Anfrageplan wählt optimaler eine Partition aus. Normalerweise wird Partitionierung nach Bereich verwendet – das gilt auch für Zabbix. Wir verwenden dort „timestamp“ – die Zeit seit der Epoche. Bei uns sind das gewöhnliche Zahlen. Sie geben den Beginn und das Ende des Tages an – das ist die Partition.
Schnelles Löschen — DELETE. Es wird eine Datei/Subtabelle ausgewählt und nicht eine Zeilenabfrage zum Löschen.
Er beschleunigt die Datenauswahl merklich SELECT — verwendet eine oder mehrere Partitionen und nicht die gesamte Tabelle. Wenn Sie nach Daten von vor zwei Tagen fragen, werden sie schneller aus der DB abgerufen, da nur eine Datei in den Cache geladen und nicht eine große Tabelle ausgegeben werden muss.
Oft beschleunigt es auch viele DBs INSERT — Einfügungen in die Child-Tabelle.
TimescaleDB
Für v 4.2 haben wir auf TimescaleDB geachtet. Dies ist eine Erweiterung für PostgreSQL mit nativem Interface. Die Erweiterung funktioniert effizient mit Zeitreihendaten, ohne die Vorteile relationaler DBs zu verlieren. TimescaleDB partitioniert auch automatisch.
In TimescaleDB gibt es das Konzept Hypertabelle (hypertable), die Sie erstellen. Darin befinden sich Chunks — Partitionen. Chunks sind automatisch verwaltete Fragmente der Hypertabelle, die andere Fragmente nicht beeinflussen. Jeder Chunk hat seinen eigenen Zeitbereich.

TimescaleDB vs PostgreSQL
TimescaleDB arbeitet wirklich effizient. Die Hersteller der Erweiterung behaupten, dass sie einen genaueren Algorithmus zur Anfragebearbeitung verwenden, insbesondere für <code>inserts<\/code>. Wenn die Größe der Dataset-Einfügungen wächst, bleibt die Leistung konstant.

Nach 200 Millionen Zeilen beginnt PostgreSQL normalerweise erheblich zu sinken und verliert die Leistung bis auf 0. TimescaleDB ermöglicht die effiziente Einfügung von „inserts“ bei jeder Datenmenge.
Installation
Die Installation von TimescaleDB ist für alle Pakete recht einfach. In alles ausführlich beschrieben – es basiert auf den offiziellen PostgreSQL-Paketen. TimescaleDB kann auch manuell zusammengestellt und kompiliert werden.
Für die Zabbix-DB aktivieren wir einfach die Erweiterung:
echo "CREATE EXTENSION IF NOT EXISTS timescaledb CASCADE;" | sudo -u postgres psql zabbix Sie aktivieren die Erweiterung und erstellen sie für die Zabbix-DB. Der letzte Schritt ist die Erstellung der Hypertabelle.
Migration von Geschichte-Tabellen zu TimescaleDB
Dafür gibt es eine spezielle Funktion create_hypertable:
WÄHLEN Sie create_hypertable('history', 'clock', chunk_time_interval => 86400, migrate_data => true);
WÄHLEN Sie create_hypertable('history_unit', 'clock', chunk_time_interval => 86400, migrate_data => true);
WÄHLEN Sie create_hypertable('history_log', 'clock', chunk_time_interval => 86400, migrate_data => true);
WÄHLEN Sie create_hypertable('history_text', 'clock', chunk_time_interval => 86400, migrate_data => true);
WÄHLEN Sie create_hypertable('history_str', 'clock', chunk_time_interval => 86400, migrate_data => true);
WÄHLEN Sie create_hypertable('trends', 'clock', chunk_time_interval => 86400, migrate_data => true);
WÄHLEN Sie create_hypertable('trends_unit', 'clock', chunk_time_interval => 86400, migrate_data => true);
AKTUALISIEREN Sie config SET db_extension='timescaledb', hk_history_global=1, hk_trends_global=1 Die Funktion hat drei Parameter. Der erste — Tabelle in der DB, für die eine Hypertabelle erstellt werden muss. Der zweite — Feld, nach dem eine Erstellung erfolgen soll chunk_time_interval – der Chunk-Zeitintervall für die Partitionen, die verwendet werden sollen. In meinem Fall beträgt das Intervall einen Tag – 86 400.
Der dritte Parameter — Daten migrieren. Wenn Sie setzen true, werden alle aktuellen Daten in die im Voraus erstellten Chunks verschoben. Ich habe selbst verwendet Daten migrieren. Ich hatte etwa 1 TB, was mehr als eine Stunde dauerte. Selbst in einigen Fällen habe ich während der Tests nicht benötigte historische Daten von Zeichentypen gelöscht, um sie nicht zu migrieren.
Der letzte Schritt — UPDATE: in db_extension setzen wir timescaledb, damit die DB versteht, dass diese Erweiterung existiert. Zabbix aktiviert sie und verwendet korrekt die Syntax und Abfragen zur DB – die Funktionen, die für TimescaleDB erforderlich sind.
Hardware-Konfiguration
Ich habe zwei Server verwendet. Der erste — VMware-Maschine. Sie ist recht klein: 20 Intel® Xeon® CPU E5-2630 v 4 @ 2.20GHz, 16 GB RAM und eine SSD mit 200 GB.
Ich habe darauf PostgreSQL 10.8 mit Debian 10.8-1.pgdg90+1 und dem Dateisystem xfs installiert. Ich habe alles minimal konfiguriert, um genau diese Datenbank zu verwenden, abgesehen davon, dass sie selbst von Zabbix verwendet wird.
Auf derselben Maschine lief der Zabbix-Server, PostgreSQL und Lastagenten. Ich hatte 50 aktive Agenten, die LoadableModule, um sehr schnell verschiedene Ergebnisse zu generieren: Zahlen, Zeichenfolgen. Ich habe die DB mit einer großen Menge an Daten gefüllt.
Ursprünglich enthielt die Konfiguration 5 000 Elemente Daten für jeden Host. Fast jedes Element hatte einen Trigger, um es wie echte Installationen erscheinen zu lassen. In einigen Fällen gab es mehr als einen Trigger. Pro Knoten im Netzwerk kamen 3 000-7 000 Trigger.
Das Aktualisierungsintervall der Datenelemente — 4-7 Sekunden. Ich habe die Last dadurch reguliert, dass ich nicht nur 50 Agenten verwendet habe, sondern noch weitere hinzugefügt habe. Außerdem habe ich mit den Datenelementen die Last dynamisch reguliert und das Aktualisierungsintervall auf 4 Sekunden gesenkt.
PostgreSQL. 35 000 nvps
Der erste Start auf dieser Hardware erfolgte mit reinem PostgreSQL — 35.000 Werte pro Sekunde. Wie man sieht, dauert das Einfügen von Daten Bruchteile von Sekunden — alles funktioniert gut und schnell. Das einzige, was passiert, ist, dass die 200 GB SSD-Festplatte schnell voll wird.

Das ist das Standard-Dashboard für die Leistung von Zabbix — Server.

Der erste blaue Graph zeigt die Anzahl der Werte pro Sekunde. Der zweite Graph rechts — die Last der Sammlerprozesse. Der dritte — die Last der internen Sammlerprozesse: History Syncers und Housekeeper, was hier ausreichend Zeit in Anspruch nahm.
Der vierte Graph zeigt die Nutzung des HistoryCache. Das ist ein Puffer vor dem Einfügen in die Datenbank. Der grüne fünfte Graph zeigt die Nutzung des ValueCache, also wie viele Hits der ValueCache für Trigger hat — das sind mehrere Tausend Werte pro Sekunde.
PostgreSQL. 50 000 nvps
Ich habe die Last auf 50.000 Werte pro Sekunde auf derselben Hardware erhöht.

Beim Laden mit Housekeeper wurde das Einfügen von 10.000 Werten in 2-3 Sekunden aufgezeichnet.

Housekeeper beginnt bereits, die Arbeit zu stören.
Im dritten Graphen sieht man, dass die Last der Trapper und History Syncers insgesamt noch bei 60 % liegt. Im vierten Graphen wird der HistoryCache während der Arbeit des Housekeepers bereits aktiv gefüllt. Er hat sich zu 20 % gefüllt — das sind etwa 0,5 GB.
PostgreSQL. 80 000 nvps
Ich habe die Last auf 80.000 Werte pro Sekunde erhöht. Das sind etwa 400.000 Datenelemente und 280.000 Trigger.

Der Insert mit der Last von dreißig History Syncers ist bereits ziemlich hoch.
Zudem habe ich verschiedene Parameter erhöht: History Syncers, Caches.

Auf meiner Hardware erhöhte sich die Last der History Syncers bis zum Maximum. Der HistoryCache füllte sich schnell mit Daten — im Puffer sammelten sich die zu verarbeitenden Daten.
Während der ganzen Zeit habe ich beobachtet, wie der Prozessor, der Arbeitsspeicher und andere Systemparameter genutzt wurden, und habe festgestellt, dass die Disknutzung maximal war.

Ich habe die Nutzung erreicht der maximalen Diskkapazitäten auf dieser Hardware und dieser virtuellen Maschine. Bei solcher Intensität begann PostgreSQL, die Daten ziemlich aktiv abzulehnen, und die Festplatte konnte nicht mehr mit dem Schreiben und Lesen nachkommen.
Zweiter Server
Ich habe einen anderen Server genommen, der bereits 48 Prozessoren und 128 GB RAM hatte. Ich habe ihn optimiert – 60 History Syncer installiert, und eine akzeptable Leistung erreicht.

Faktisch ist dies bereits die Leistungsgrenze, wo etwas unternommen werden muss.
TimescaleDB. 80.000 nvps
Mein Hauptziel ist es, die Möglichkeiten von TimescaleDB unter der Last von Zabbix zu überprüfen. 80.000 Werte pro Sekunde sind viel, die Frequenz der Metrikabfrage (außer bei Yandex, natürlich) und ein ziemlich großer „Setup“.

Jeder Graph weist Einbrüche auf – das ist genau die Migration der Daten. Nach den Einbrüchen auf dem Zabbix-Server hat sich das Lastprofil des History Syncer drastisch verändert – es ist um das Dreifache gefallen.
TimescaleDB ermöglicht es, Daten praktisch dreimal schneller einzufügen und weniger HistoryCache zu verwenden.
Dementsprechend werden Ihnen die Daten rechtzeitig zur Verfügung gestellt.
TimescaleDB. 120.000 nvps
Dann habe ich die Anzahl der Datenelemente auf 500.000 erhöht. Die Hauptaufgabe war es, die Möglichkeiten von TimescaleDB zu testen – ich habe einen geschätzten Wert von 125.000 Werten pro Sekunde erhalten.

Das ist ein funktionierender „Setup“, der lange betrieben werden kann. Aber da meine Festplatte nur 1,5 TB groß war, habe ich sie in ein paar Tagen voll erhalten.

Das Wichtigste ist, dass gleichzeitig neue Partitionen von TimescaleDB erstellt wurden.
Für die Leistung ist das völlig unauffällig. Wenn Partitionen in MySQL erstellt werden, ist das zum Beispiel ganz anders. Normalerweise geschieht das nachts, da es die allgemeine Einfügung blockiert, die Arbeit mit Tabellen behindert und die Servicequalität degradieren kann. Im Falle von TimescaleDB ist das nicht der Fall.
Zur Veranschaulichung zeige ich einen Graphen aus vielen in der Community. Das Bild zeigt, dass TimescaleDB aktiviert wurde, wodurch die Last bezüglich der Nutzung von io.weight auf der CPU gesenkt wurde. Die Nutzung interner Prozess-Elemente ist ebenfalls zurückgegangen. Dabei handelt es sich um eine normale virtuelle Maschine auf herkömmlichen Festplatten, nicht SSDs.

Das DBMS Tarantool ist ein attraktives, zukunftsträchtiges Produkt zur Erstellung von hochbelasteten Anwendungen.
TimescaleDB ist eine gute Lösung für kleine „Setups“, die an der Leistung der Festplatte scheitern. Es wird ermöglichen, bis zur Migration der Datenbank auf leistungsfähigere Hardware gut weiterzuarbeiten.
TimescaleDB ist einfach einzurichten, bietet Leistungssteigerungen und funktioniert gut mit Zabbix und hat Vorteile gegenüber PostgreSQL..
Wenn Sie PostgreSQL verwenden und nicht vorhaben, es zu ändern, empfehle ich die Verwendung von PostgreSQL mit der Erweiterung TimescaleDB in Verbindung mit Zabbix.Diese Lösung funktioniert effizient bis zu mittleren „Setups“.
Wenn wir von „hoher Leistung“ sprechen, meinen wir Es dauert nicht lange, um Technologien und Praktiken kennenzulernen, die es den Diensten ermöglichen, Millionen von Nutzern zu bedienen. Die Liste für den 7. und 8. November haben wir bereits vorbereitet, aber können noch vorgeschlagen werden.
Abonnieren Sie unseren und , in dem wir die Highlights der bevorstehenden Konferenz enthüllen und erfahren, wie Sie den größtmöglichen Nutzen daraus ziehen können.
Quelle: habr.com
