Wie wir den Cache in der Tarantool-Datenbank implementiert haben

Guten Tag!

Ich möchte Ihnen eine Geschichte über die Implementierung des Cache in der Tarantool-Datenbank und meine Arbeitsfunktionen mitteilen.
Ich arbeite als Java-Entwickler in einem Telekommunikationsunternehmen. Die Hauptaufgabe: die Implementierung der Geschäftslogik für die Plattform, die das Unternehmen vom Anbieter gekauft hat. Von den ersten Merkmalen ist dies Seifenarbeit und das fast vollständige Fehlen von Caching, außer im JVM-Speicher. All dies ist natürlich gut, bis die Anzahl der Anwendungsinstanzen zwei Dutzend überschreitet ...

Im Laufe der Arbeit und der Entstehung eines Verständnisses der Funktionen der Plattform wurde versucht, das Caching durchzuführen. Zu diesem Zeitpunkt war MongoDB bereits gestartet, und als Ergebnis haben wir keine besonderen positiven Ergebnisse wie im Test erhalten.

Bei einer weiteren Suche nach Alternativen und Ratschlägen meines guten Freundes mr_elzor wurde beschlossen, die Tarantool-Datenbank auszuprobieren.

In einer flüchtigen Studie tauchten in Lua nur Zweifel auf, da ich nicht vom Wort "vollständig" darauf geschrieben hatte. Aber er schob alle Zweifel beiseite und machte sich an die Installation. Ich denke, dass nur wenige Menschen an geschlossenen Netzwerken und Firewalls interessiert sind, aber ich rate Ihnen, zu versuchen, sie zu umgehen und alles aus öffentlichen Quellen zu beziehen.

Testserver mit Konfiguration: 8 CPU, 16 GB RAM, 100 GB Festplatte, Debian 9.4.

Die Installation erfolgte gemäß den Anweisungen auf der Website. Und so bekam ich eine Beispieloption. Es entstand sofort die Idee einer visuellen Oberfläche, mit der die Unterstützung bequem funktionieren würde. Während einer Schnellsuche habe ich tarantool-admin gefunden und konfiguriert. Arbeitet bei Docker und deckt Support-Aufgaben zumindest vorerst zu 100% ab.

Aber lassen Sie uns über interessanter sprechen.

Der nächste Gedanke war, meine Version in der Master-Slave-Konfiguration auf demselben Server zu konfigurieren, da die Dokumentation nur Beispiele mit zwei verschiedenen Servern enthält.

Nachdem ich einige Zeit damit verbracht habe, Lua zu verstehen und die Konfiguration zu beschreiben, starte ich den Assistenten.

# systemctl start tarantool@master Job for tarantool@master.service failed because the control process exited with error code. See "systemctl status tarantool@master.service" and "journalctl -xe" for details. 

Ich gerate sofort in einen Stupor und verstehe nicht, warum der Fehler vorliegt, aber ich sehe, dass er sich im Status "Laden" befindet.

 # systemctl status tarantool@master ● tarantool@master.service - Tarantool Database Server Loaded: loaded (/lib/systemd/system/tarantool@.service; enabled; vendor preset: enabled) Active: activating (start) since Tue 2019-02-19 17:03:24 MSK; 17s ago Docs: man:tarantool(1) Process: 20111 ExecStop=/usr/bin/tarantoolctl stop master (code=exited, status=0/SUCCESS) Main PID: 20120 (tarantool) Status: "loading" Tasks: 5 (limit: 4915) CGroup: /system.slice/system-tarantool.slice/tarantool@master.service └─20120 tarantool master.lua <loading> Feb 19 17:03:24 tarantuldb-tst4 systemd[1]: Starting Tarantool Database Server... Feb 19 17:03:24 tarantuldb-tst4 tarantoolctl[20120]: Starting instance master... Feb 19 17:03:24 tarantuldb-tst4 tarantoolctl[20120]: Run console at unix/:/var/run/tarantool/master.control Feb 19 17:03:24 tarantuldb-tst4 tarantoolctl[20120]: started 

Ich laufe Sklave:

 # systemctl start tarantool@slave2 Job for tarantool@slave2.service failed because the control process exited with error code. See "systemctl status tarantool@slave2.service" and "journalctl -xe" for details. 

Und ich sehe den gleichen Fehler. Hier fange ich im Allgemeinen an, mich zu belasten und nicht zu verstehen, was passiert, da es in der Dokumentation überhaupt nichts darüber gibt ... Aber wenn ich den Status überprüfe, sehe ich, dass er überhaupt nicht gestartet wurde, obwohl er besagt, dass der Status "läuft":

 # systemctl status tarantool@slave2 ● tarantool@slave2.service - Tarantool Database Server Loaded: loaded (/lib/systemd/system/tarantool@.service; enabled; vendor preset: enabled) Active: failed (Result: exit-code) since Tue 2019-02-19 17:04:52 MSK; 27s ago Docs: man:tarantool(1) Process: 20258 ExecStop=/usr/bin/tarantoolctl stop slave2 (code=exited, status=0/SUCCESS) Process: 20247 ExecStart=/usr/bin/tarantoolctl start slave2 (code=exited, status=1/FAILURE) Main PID: 20247 (code=exited, status=1/FAILURE) Status: "running" Feb 19 17:04:52 tarantuldb-tst4 systemd[1]: tarantool@slave2.service: Unit entered failed state. Feb 19 17:04:52 tarantuldb-tst4 systemd[1]: tarantool@slave2.service: Failed with result 'exit-code'. Feb 19 17:04:52 tarantuldb-tst4 systemd[1]: tarantool@slave2.service: Service hold-off time over, scheduling restart. Feb 19 17:04:52 tarantuldb-tst4 systemd[1]: Stopped Tarantool Database Server. Feb 19 17:04:52 tarantuldb-tst4 systemd[1]: tarantool@slave2.service: Start request repeated too quickly. Feb 19 17:04:52 tarantuldb-tst4 systemd[1]: Failed to start Tarantool Database Server. Feb 19 17:04:52 tarantuldb-tst4 systemd[1]: tarantool@slave2.service: Unit entered failed state. Feb 19 17:04:52 tarantuldb-tst4 systemd[1]: tarantool@slave2.service: Failed with result 'exit-code'. 

Gleichzeitig begann der Meister zu arbeiten:

 # ps -ef | grep taran taranto+ 20158 1 0 17:04 ? 00:00:00 tarantool master.lua <running> root 20268 2921 0 17:06 pts/1 00:00:00 grep taran 

Ein Neustart des Slaves hilft nicht. Ich frage mich warum?

Ich halte den Meister auf. Führen Sie die Aktionen in umgekehrter Reihenfolge aus.

Ich sehe, dass der Sklave versucht zu starten.

 # ps -ef | grep taran taranto+ 20399 1 0 17:09 ? 00:00:00 tarantool slave2.lua <loading> 

Ich starte den Assistenten und sehe, dass er nicht gestiegen ist und im Allgemeinen in den Waisenstatus gewechselt ist, während der Sklave im Allgemeinen gefallen ist.

 # ps -ef | grep taran taranto+ 20428 1 0 17:09 ? 00:00:00 tarantool master.lua <orphan> 

Es wird noch interessanter.

Ich sehe in den Protokollen auf Slave, dass er sogar den Master gesehen und versucht hat zu synchronisieren.

 2019-02-19 17:13:45.113 [20751] iproto/101/main D> binary: binding to 0.0.0.0:3302... 2019-02-19 17:13:45.113 [20751] iproto/101/main I> binary: bound to 0.0.0.0:3302 2019-02-19 17:13:45.113 [20751] iproto/101/main D> binary: listening on 0.0.0.0:3302... 2019-02-19 17:13:45.113 [20751] iproto D> cpipe_flush_cb: locking &endpoint->mutex 2019-02-19 17:13:45.113 [20751] iproto D> cpipe_flush_cb: unlocking &endpoint->mutex 2019-02-19 17:13:45.113 [20751] main D> cbus_endpoint_fetch: locking &endpoint->mutex 2019-02-19 17:13:45.113 [20751] main D> cbus_endpoint_fetch: unlocking &endpoint->mutex 2019-02-19 17:13:45.113 [20751] main/101/slave2 I> connecting to 1 replicas 2019-02-19 17:13:45.113 [20751] main/106/applier/replicator@tarantuldb-t D> => CONNECT 2019-02-19 17:13:45.114 [20751] main/106/applier/replicator@tarantuldb-t I> remote master 825af7c3-f8df-4db0-8559-a866b8310077 at 10.78.221.74:3301 running Tarantool 1.10.2 2019-02-19 17:13:45.114 [20751] main/106/applier/replicator@tarantuldb-t D> => CONNECTED 2019-02-19 17:13:45.114 [20751] main/101/slave2 I> connected to 1 replicas 2019-02-19 17:13:45.114 [20751] coio V> loading vylog 14 2019-02-19 17:13:45.114 [20751] coio V> done loading vylog 2019-02-19 17:13:45.114 [20751] main/101/slave2 I> recovery start 2019-02-19 17:13:45.114 [20751] main/101/slave2 I> recovering from `/var/lib/tarantool/cache_slave2/00000000000000000014.snap' 2019-02-19 17:13:45.114 [20751] main/101/slave2 D> memtx_tuple_new(47) = 0x7f99a4000080 2019-02-19 17:13:45.114 [20751] main/101/slave2 I> cluster uuid 4035b563-67f8-4e85-95cc-e03429f1fa4d 2019-02-19 17:13:45.114 [20751] main/101/slave2 D> memtx_tuple_new(11) = 0x7f99a4004080 2019-02-19 17:13:45.114 [20751] main/101/slave2 D> memtx_tuple_new(17) = 0x7f99a4008068 

Und der Versuch war erfolgreich:

 2019-02-19 17:13:45.118 [20751] main/101/slave2 D> memtx_tuple_new(40) = 0x7f99a40004c0 2019-02-19 17:13:45.118 [20751] main/101/slave2 I> assigned id 1 to replica 825af7c3-f8df-4db0-8559-a866b8310077 2019-02-19 17:13:45.118 [20751] main/101/slave2 D> memtx_tuple_new(40) = 0x7f99a4000500 2019-02-19 17:13:45.118 [20751] main/101/slave2 I> assigned id 2 to replica 403c0323-5a9b-480d-9e71-5ba22d4ccf1b 2019-02-19 17:13:45.118 [20751] main/101/slave2 I> recover from `/var/lib/tarantool/slave2/00000000000000000014.xlog' 2019-02-19 17:13:45.118 [20751] main/101/slave2 I> done `/var/lib/tarantool/slave2/00000000000000000014.xlog' 

Es fing sogar an:

 2019-02-19 17:13:45.119 [20751] main/101/slave2 D> systemd: sending message 'STATUS=running' 

Aber aus unbekannten Gründen verlor er die Verbindung und fiel:

 2019-02-19 17:13:45.129 [20751] main/101/slave2 D> SystemError at /build/tarantool-1.10.2.146/src/coio_task.c:416 2019-02-19 17:13:45.129 [20751] main/101/slave2 tarantoolctl:532 E> Start failed: /usr/local/share/lua/5.1/http/server.lua:1146: Can't create tcp_server: Input/output error 

Der Versuch, den Slave erneut zu starten, hilft nicht.

Löschen Sie nun die von den Instanzen erstellten Dateien. In meinem Fall lösche ich alles aus dem Verzeichnis / var / lib / tarantool.

Ich starte zuerst den Sklaven und erst dann den Meister. Und siehe da ...

 # ps -ef | grep tara taranto+ 20922 1 0 17:20 ? 00:00:00 tarantool slave2.lua <running> taranto+ 20933 1 1 17:21 ? 00:00:00 tarantool master.lua <running> 

Ich habe keine Erklärung für dieses Verhalten gefunden, außer als "Funktion dieser Software".
Diese Situation tritt jedes Mal auf, wenn Ihr Server vollständig neu gestartet wurde.

Bei einer weiteren Analyse der Architektur dieser Software stellt sich heraus, dass nur eine vCPU für eine Instanz verwendet werden soll und viele weitere Ressourcen frei bleiben.

In der Ideologie von n vCPU können wir den Master und n-2 Slaves zum Lesen anheben.

Da auf dem Testserver 8 vCPU der Master und 6 Instanzen zum Lesen ausgelöst werden können.
Ich kopiere die Datei für den Slave, korrigiere die Ports und führe sie aus, d.h. ein paar weitere Slaves werden hinzugefügt.

Wichtig! Wenn Sie eine weitere Instanz hinzufügen, müssen Sie diese im Assistenten registrieren.
Sie müssen jedoch zuerst einen neuen Slave starten und erst dann den Master neu starten.

Beispiel


Ich hatte bereits eine Konfiguration mit einem Assistenten und zwei Slaves.

Ich beschloss, einen dritten Sklaven hinzuzufügen.

Ich habe es beim Master registriert und den Master zuerst neu gestartet, und das habe ich gesehen:

 # ps -ef | grep tara taranto+ 20922 1 0 Feb19 ? 00:00:29 tarantool slave2.lua <running> taranto+ 20965 1 0 Feb19 ? 00:00:29 tarantool slave3.lua <running> taranto+ 21519 1 0 09:16 ? 00:00:00 tarantool master.lua <orphan> 

Das heißt, Unser Meister wurde ein Einzelgänger, und die Replikation fiel auseinander.

Das Starten eines neuen Slaves hilft nicht mehr und führt zu einem Fehler:

 # systemctl restart tarantool@slave4 Job for tarantool@slave4.service failed because the control process exited with error code. See "systemctl status tarantool@slave4.service" and "journalctl -xe" for details. 

Und in den Protokollen sah ich einen kleinen informativen Eintrag:

 2019-02-20 09:20:10.616 [21601] main/101/slave4 I> bootstrapping replica from 3c77eb9d-2fa1-4a27-885f-e72defa5cd96 at 10.78.221.74:3301 2019-02-20 09:20:10.617 [21601] main/106/applier/replicator@tarantuldb-t I> can't join/subscribe 2019-02-20 09:20:10.617 [21601] main/106/applier/replicator@tarantuldb-t xrow.c:896 E> ER_READONLY: Can't modify data because this instance is in read-only mode. 2019-02-20 09:20:10.617 [21601] main/106/applier/replicator@tarantuldb-t D> => STOPPED 2019-02-20 09:20:10.617 [21601] main/101/slave4 xrow.c:896 E> ER_READONLY: Can't modify data because this instance is in read-only mode. 2019-02-20 09:20:10.617 [21601] main/101/slave4 F> can't initialize storage: Can't modify data because this instance is in read-only mode. 

Wir stoppen den Assistenten und starten einen neuen Sklaven. Wie beim ersten Start wird auch ein Fehler auftreten, aber wir werden sehen, dass es sich um den Ladestatus handelt.

 # ps -ef | grep tara taranto+ 20922 1 0 Feb19 ? 00:00:29 tarantool slave2.lua <running> taranto+ 20965 1 0 Feb19 ? 00:00:30 tarantool slave3.lua <running> taranto+ 21659 1 0 09:23 ? 00:00:00 tarantool slave4.lua <loading> 

Wenn Sie jedoch den Master starten, stürzt der neue Slave ab und der Master geht nicht in den laufenden Status über.

 # ps -ef | grep tara taranto+ 20922 1 0 Feb19 ? 00:00:29 tarantool slave2.lua <running> taranto+ 20965 1 0 Feb19 ? 00:00:30 tarantool slave3.lua <running> taranto+ 21670 1 0 09:23 ? 00:00:00 tarantool master.lua <orphan> 

In dieser Situation gibt es nur einen Ausweg. Wie ich bereits geschrieben habe, lösche ich Dateien, die von Instanzen erstellt wurden, und führe zuerst Slaves und dann Master aus.

 # ps -ef | grep tarantool taranto+ 21892 1 0 09:30 ? 00:00:00 tarantool slave4.lua <running> taranto+ 21907 1 0 09:30 ? 00:00:00 tarantool slave3.lua <running> taranto+ 21922 1 0 09:30 ? 00:00:00 tarantool slave2.lua <running> taranto+ 21931 1 0 09:30 ? 00:00:00 tarantool master.lua <running> 

Alles begann erfolgreich.

Auf diese Weise habe ich durch Ausprobieren herausgefunden, wie die Replikation richtig konfiguriert und gestartet werden kann.

Als Ergebnis wurde die folgende Konfiguration zusammengestellt:

2 Server.
2 Meister. Hot Reserve.
12 Sklaven. Alle sind aktiv.

In der Logik von tarantool wurde http.server verwendet, um den zusätzlichen Adapter nicht zu blockieren (Hersteller, Plattform und Seife beachten) oder die Bibliothek an jedem Geschäftsprozess zu befestigen.

Um eine Diskrepanz zwischen den Mastern auf dem Balancer (NetScaler, HAProxy oder einem anderen Ihrer Favoriten) zu vermeiden, legen wir die Reserveregel fest, d. H. Einfüge-, Aktualisierungs- und Löschvorgänge gehen nur zum ersten aktiven Master.

Zu diesem Zeitpunkt repliziert der zweite einfach die Datensätze des ersten. Die Slaves selbst sind aus der Konfiguration mit dem ersten angegebenen Master verbunden, was wir in dieser Situation benötigen.

Auf lua wurden CRUD-Operationen für den Schlüsselwert implementiert. Im Moment reicht dies aus, um das Problem zu lösen.

In Anbetracht der Merkmale der Arbeit mit Seife wurde ein Proxy-Geschäftsprozess implementiert, in dem die Logik der Arbeit mit einer Vogelspinne über http festgelegt wurde.

Wenn die Schlüsseldaten vorhanden sind, werden sie sofort zurückgegeben. Wenn nicht, wird eine Anforderung an das Mastersystem gesendet und in der Tarantool-Datenbank gespeichert.

Infolgedessen verarbeitet ein Geschäftsprozess in Tests bis zu 4.000 Anforderungen. In diesem Fall beträgt die Reaktionszeit der Vogelspinne ~ 1 ms. Die durchschnittliche Reaktionszeit beträgt bis zu 3 ms.

Hier einige Informationen aus den Tests:



Es gab 50 Geschäftsprozesse, die zu 4 Mastersystemen gehen und Daten in ihrem Speicher zwischenspeichern. Duplizierung von Informationen in vollem Wachstum bei jeder Instanz. Angesichts der Tatsache, dass Java die Erinnerung bereits liebt ... ist die Aussicht nicht die beste.

Jetzt


50 Geschäftsprozesse fordern Informationen über den Cache an. Jetzt werden Informationen von 4 Instanzen des Assistenten an einem Ort gespeichert und nicht bei jeder Instanz im Speicher zwischengespeichert. Es war möglich, die Belastung des Mastersystems erheblich zu reduzieren, es gibt keine doppelten Informationen und der Speicherverbrauch bei Instanzen mit Geschäftslogik ist gesunken.

Ein Beispiel für die Größe des Informationsspeichers im Tarantelspeicher:



Am Ende des Tages können sich diese Zahlen verdoppeln, aber es gibt keinen „Leistungsabfall“.

Im Kampf erstellt die aktuelle Version 2k - 2,5k Anforderungen pro Sekunde realer Last. Die durchschnittliche Reaktionszeit ähnelt Tests bis zu 3 ms.

Wenn Sie sich htop auf einem der Server mit tarantool ansehen, werden wir feststellen, dass sie "abkühlen":



Zusammenfassung


Trotz aller Feinheiten und Nuancen der Tarantool-Datenbank können Sie eine hervorragende Leistung erzielen.

Ich hoffe, dass sich dieses Projekt entwickelt und diese unangenehmen Momente gelöst werden.

Source: https://habr.com/ru/post/de441686/


All Articles