So hören Sie auf, sich Sorgen zu machen und beginnen, ohne Monolithen zu leben

So hören Sie auf, sich Sorgen zu machen und beginnen, ohne Monolithen zu leben

Wir alle lieben Geschichten. Wir sitzen gerne am Feuer und reden über unsere vergangenen Siege, Schlachten oder einfach über unsere Arbeitserfahrung.

Heute ist genau so ein Tag. Und selbst wenn Sie gerade nicht am Feuer sind, haben wir eine Geschichte für Sie. Die Geschichte, wie wir begannen, mit Speicher auf Tarantool zu arbeiten.

Es war einmal, dass unser Unternehmen ein paar „Monolithen“ und eine „Decke“ für alle hatte, der sich diese Monolithen langsam aber sicher näherten und den Flug unseres Unternehmens, unsere Entwicklung einschränkten. Und es gab ein klares Verständnis: Eines Tages werden wir diese Obergrenze hart erreichen.

Es ist heute die vorherrschende Ideologie, alles und jeden zu trennen, von der Ausrüstung bis zur Geschäftslogik. Dadurch verfügen wir beispielsweise über zwei DCs, die auf Netzwerkebene praktisch unabhängig sind. Und dann war alles ganz anders.

Heutzutage gibt es viele Tools und Tools zum Vornehmen von Änderungen in Form von CI/CD, K8S usw. In der „monolithischen“ Zeit brauchten wir nicht so viele Fremdwörter. Es genügte lediglich die Korrektur der „Speicherung“ in der Datenbank.

Aber die Zeit verging und die Anzahl der Anfragen wuchs mit ihr, sodass die RPS manchmal unsere Möglichkeiten überstiegen. Mit dem Markteintritt der GUS-Staaten sank die Auslastung des Datenbankprozessors des ersten Monolithen nicht unter 90 % und der RPS blieb auf dem Niveau von 2400. Dabei handelte es sich nicht nur um kleine Selektoren, sondern um heftige Abfragen mit a Eine Reihe von Prüfungen und JOINs, die vor dem Hintergrund großer E/A-Vorgänge fast für die Hälfte der Daten ausgeführt werden könnten.

Als vollwertige Black Friday-Verkäufe auftauchten – und Wildberries war einer der ersten, der sie in Russland veranstaltete – wurde die Situation völlig traurig. Schließlich erhöht sich die Belastung an solchen Tagen um das Dreifache.
Oh, diese „monolithischen Zeiten“! Ich bin sicher, dass Sie etwas Ähnliches erlebt haben und immer noch nicht verstehen können, wie Ihnen das passieren konnte.

Was können Sie tun – Mode ist der Technologie inhärent. Vor etwa 5 Jahren mussten wir einen dieser Mods in Form einer bestehenden Site auf .NET und MS SQL Server überdenken, die die gesamte Logik der Site selbst sorgfältig speicherte. Ich habe es so sorgfältig aufbewahrt, dass das Sägen eines solchen Monolithen ein langes und gar nicht so leichtes Vergnügen war.
Ein kleiner Exkurs.

Auf verschiedenen Veranstaltungen sage ich: „Wenn du keinen Monolithen gesehen hast, dann bist du nicht gewachsen!“ Ich bin an Ihrer Meinung zu diesem Thema interessiert, schreiben Sie sie bitte in die Kommentare.

Und da war ein Donner

Kehren wir zu unserem „Lagerfeuer“ zurück. Um die Last der „monolithischen“ Funktionalität zu verteilen, haben wir uns entschieden, das System in Microservices zu unterteilen, die auf Open-Source-Technologien basieren. Denn zumindest sind sie günstiger zu skalieren. Und wir hatten zu 100 % Verständnis dafür, dass wir skalieren mussten (und zwar sehr viel). Denn schon damals gelang der Eintritt in die Märkte der Nachbarländer und die Zahl der Anmeldungen sowie der Bestellungen begann noch stärker zu wachsen.

Nachdem wir die ersten Kandidaten für die Abkehr vom Monolithen hin zu Microservices analysiert hatten, stellten wir fest, dass 80 % des darin geschriebenen Textes aus Back-Office-Systemen und das Lesen aus dem Front-Office stammt. Dies betraf zunächst einige für uns wichtige Subsysteme – Benutzerdaten und ein System zur Berechnung der Endkosten der Ware auf Basis von Informationen über zusätzliche Kundenrabatte und Coupons.

Eingerückt. Nun ist es beängstigend, sich das vorzustellen, aber zusätzlich zu den oben genannten Subsystemen wurden auch Produktkataloge, ein Benutzer-Warenkorb, ein Produktsuchsystem, ein Filtersystem für Produktkataloge und verschiedene Arten von Empfehlungssystemen aus unserem Monolithen entfernt. Für den Betrieb jedes einzelnen von ihnen gibt es separate Klassen eng zugeschnittener Systeme, aber einst lebten sie alle in einem „Haus“.

Wir hatten sofort vor, Daten über unsere Kunden in das Shard-System zu übertragen. Die Entfernung der Funktionalität zur Berechnung der Endkosten der Waren erforderte eine gute Skalierbarkeit beim Lesen, da sie die größte RPS-Last verursachte und für die Datenbank am schwierigsten zu implementieren war (am Berechnungsprozess sind viele Daten beteiligt).

Als Ergebnis haben wir ein Schema entwickelt, das gut zu Tarantool passt.

Für den Betrieb von Microservices wurden damals Schemata für die Arbeit mit mehreren Rechenzentren auf virtuellen und Hardwaremaschinen gewählt. Wie in den Abbildungen dargestellt, wurden die Replikationsoptionen von Tarantool sowohl im Master-Master- als auch im Master-Slave-Modus angewendet.

So hören Sie auf, sich Sorgen zu machen und beginnen, ohne Monolithen zu leben
Die Architektur. Option 1. Benutzerservice

Derzeit gibt es 24 Shards, von denen jeder über zwei Instanzen verfügt (eine für jeden DC), alle im Master-Master-Modus.

Auf der Datenbank befinden sich Anwendungen, die auf Datenbankreplikate zugreifen. Anwendungen funktionieren mit Tarantool über unsere benutzerdefinierte Bibliothek, die die Tarantool Go-Treiberschnittstelle implementiert. Sie sieht alle Repliken und kann mit dem Meister beim Lesen und Schreiben zusammenarbeiten. Im Wesentlichen implementiert es das Replikatsatzmodell, das Logik für die Auswahl von Replikaten, die Durchführung von Wiederholungsversuchen, einen Leistungsschalter und eine Ratenbegrenzung hinzufügt.

In diesem Fall ist es möglich, die Replikatauswahlrichtlinie im Kontext von Shards zu konfigurieren. Zum Beispiel Roundrobin.

So hören Sie auf, sich Sorgen zu machen und beginnen, ohne Monolithen zu leben
Die Architektur. Option 2. Service zur Berechnung der Endkosten der Ware

Gingen vor ein paar Monaten noch die meisten Anfragen zur Endkostenberechnung von Waren an einen neuen Dienst, der im Prinzip ohne Datenbanken auskommt, wurde vor einiger Zeit alles zu 100 % von einem Dienst mit Tarantool unter der Haube abgewickelt.

Die Dienstdatenbank besteht aus 4 Mastern, in denen der Synchronizer Daten sammelt, und jeder dieser Replikationsmaster verteilt Daten an schreibgeschützte Replikate. Jeder Meister verfügt über etwa 15 solcher Repliken.

Wenn entweder im ersten oder im zweiten Schema ein DC nicht verfügbar ist, kann die Anwendung Daten im zweiten empfangen.

Es ist erwähnenswert, dass die Replikation in Tarantool recht flexibel ist und zur Laufzeit konfiguriert werden kann. In anderen Systemen traten Schwierigkeiten auf. Beispielsweise erfordert das Ändern der Parameter max_wal_senders und max_replication_slots in PostgreSQL einen Neustart des Assistenten, was in einigen Fällen zum Abbruch der Verbindungen zwischen der Anwendung und dem DBMS führen kann.

Suchen und finden!

Warum haben wir es nicht „wie normale Menschen“ gemacht, sondern einen untypischen Weg gewählt? Es kommt darauf an, was als normal gilt. Viele Leute bilden im Allgemeinen einen Cluster aus Mongo und verteilen ihn auf drei geografisch verteilte DCs.

Zu diesem Zeitpunkt hatten wir bereits zwei Redis-Projekte. Der erste war ein Cache und der zweite war ein dauerhafter Speicher für nicht allzu kritische Daten. Es war ziemlich schwierig mit ihm, teilweise durch unsere Schuld. Manchmal befanden sich ziemlich große Mengen im Schlüssel, und von Zeit zu Zeit wurde die Website unwohl. Wir haben dieses System in der Master-Slave-Version verwendet. Und es gab viele Fälle, in denen etwas mit dem Master passierte und die Replikation abstürzte.

Das heißt, Redis eignet sich für zustandslose Aufgaben, nicht für zustandsbehaftete. Im Prinzip ließen sich damit die meisten Probleme lösen, allerdings nur, wenn es sich um Schlüsselwertlösungen mit einem Indexpaar handelte. Aber Redis war damals ziemlich traurig über die Beharrlichkeit und Replikation. Darüber hinaus gab es Leistungsbeschwerden.

Wir haben über MySQL und PostgreSQL nachgedacht. Aber das erste hat sich bei uns irgendwie nicht durchgesetzt, und das zweite ist an sich ein ziemlich anspruchsvolles Produkt, und es wäre unangemessen, einfache Dienste darauf aufzubauen.
Wir haben RIAK, Cassandra und sogar eine Diagrammdatenbank ausprobiert. Dabei handelt es sich allesamt um eher Nischenlösungen, die nicht für die Rolle eines allgemeinen Universaltools zur Erstellung von Dienstleistungen geeignet waren.

Letztendlich haben wir uns für Tarantool entschieden.

Wir haben uns damit beschäftigt, als es in Version 1.6 war. Uns interessierte dabei die Symbiose von Schlüsselwert und der Funktionalität einer relationalen Datenbank. Es gibt Sekundärindizes, Transaktionen und Leerzeichen, diese sind wie Tabellen, aber nicht einfach, man kann darin unterschiedlich viele Spalten speichern. Aber das Killerfeature von Tarantool waren Sekundärindizes in Kombination mit Schlüsselwerten und Transaktionalität.

Eine Rolle spielte auch die reaktionsschnelle russischsprachige Community, die bereit war, im Chat zu helfen. Wir nutzen dies aktiv und leben direkt im Chat. Und vergessen Sie nicht die anständige Beharrlichkeit ohne offensichtliche Fehler und Fehler. Wenn Sie sich unsere Geschichte mit Tarantool ansehen, hatten wir viele Probleme und Fehler bei der Replikation, aber wir haben aufgrund der Replikation nie Daten verloren!

Die Umsetzung hatte einen holprigen Start

Zu dieser Zeit war unser Hauptentwicklungsstack .NET, zu dem es keinen Connector für Tarantool gab. Wir haben sofort angefangen, etwas in Go zu machen. Bei Lua hat es auch gut geklappt. Das Hauptproblem war damals das Debuggen: In .NET ist damit alles super, aber danach war es schwierig, in die Welt des eingebetteten Lua einzutauchen, wenn man außer Protokollen kein Debugging hat. Darüber hinaus brach die Replikation aus irgendeinem Grund regelmäßig zusammen, sodass ich mich mit der Struktur der Tarantool-Engine befassen musste. Der Chat hat dabei geholfen, und in geringerem Maße auch die Dokumentation; manchmal haben wir uns den Code angeschaut. Damals war die Dokumentation mittelmäßig.

So gelang es mir im Laufe mehrerer Monate, mich zurechtzufinden und durch die Arbeit mit Tarantool anständige Ergebnisse zu erzielen. Wir haben Referenzentwicklungen in Git zusammengestellt, die bei der Bildung neuer Microservices geholfen haben. Als sich beispielsweise die Aufgabe ergab, einen weiteren Microservice zu erstellen, schaute sich der Entwickler den Quellcode der Referenzlösung im Repository an und die Erstellung eines neuen Microservices dauerte nicht länger als eine Woche.

Es waren besondere Zeiten. Herkömmlicherweise könnte man dann zum Administrator am Nebentisch gehen und fragen: „Geben Sie mir eine virtuelle Maschine.“ Etwa dreißig Minuten später war das Auto bereits bei Ihnen. Sie haben sich verbunden, alles installiert und der Datenverkehr wurde an Sie gesendet.

Heute funktioniert das nicht mehr: Sie müssen dem Dienst Überwachung und Protokollierung hinzufügen, die Funktionalität durch Tests abdecken, eine virtuelle Maschine bestellen oder an Kuber liefern usw. Im Allgemeinen ist es auf diese Weise besser, obwohl es länger dauert und mühsamer ist.

Teile und herrsche. Was ist mit Lua los?

Es gab ein ernstes Dilemma: Einige Teams waren nicht in der Lage, Änderungen an einem Dienst mit viel Logik in Lua zuverlässig auszurollen. Dies ging häufig damit einher, dass der Dienst nicht funktionierte.

Das heißt, die Entwickler bereiten eine Art Änderung vor. Tarantool beginnt mit der Migration, aber das Replikat enthält immer noch den alten Code. Irgendein DDL oder etwas anderes gelangt dort über die Replikation an und der Code fällt einfach auseinander, weil er nicht berücksichtigt wird. Als Ergebnis wurde der Update-Vorgang für die Administratoren auf einem A4-Blatt dargelegt: Replikation stoppen, dies aktualisieren, Replikation einschalten, hier ausschalten, dort aktualisieren. Alptraum!

Aus diesem Grund versuchen wir jetzt meistens, in Lua nichts zu tun. Verwenden Sie einfach iproto (ein Binärprotokoll für die Interaktion mit dem Server) und fertig. Vielleicht ist das ein Mangel an Wissen bei den Entwicklern, aber aus dieser Sicht ist das System komplex.

Wir folgen diesem Drehbuch nicht immer blind. Heute gibt es kein Schwarz und Weiß mehr: Entweder ist alles in Lua oder alles ist in Go. Wir verstehen bereits, wie wir sie kombinieren können, damit wir später keine Migrationsprobleme haben.

Wo ist Tarantool jetzt?
Tarantool wird im Dienst zur Berechnung der Endkosten der Waren unter Berücksichtigung von Rabattgutscheinen, auch „Promoter“ genannt, verwendet. Wie ich bereits sagte, geht er jetzt in den Ruhestand: Er wird durch einen neuen Katalogdienst mit vorberechneten Preisen ersetzt, aber vor sechs Monaten wurden alle Berechnungen in Promotizer durchgeführt. Zuvor war die Hälfte seiner Logik in Lua geschrieben. Vor zwei Jahren wurde der Dienst in eine Speichereinrichtung umgewandelt und die Logik in Go neu geschrieben, da sich die Mechanik der Rabatte ein wenig geändert hatte und es dem Dienst an Leistung mangelte.

Einer der wichtigsten Dienste ist das Benutzerprofil. Das heißt, alle Wildberries-Benutzer werden in Tarantool gespeichert, und es gibt etwa 50 Millionen davon. Ein System, das nach Benutzer-IDs aufgeteilt und auf mehrere DCs verteilt ist, die mit Go-Diensten verbunden sind.
Laut RPS war Promoter einst führend und erreichte 6 Anfragen. Irgendwann hatten wir 50-60 Exemplare. Derzeit sind Benutzerprofile mit etwa 12 führend bei RPS. Dieser Dienst verwendet benutzerdefiniertes Sharding, unterteilt nach Bereichen von Benutzer-IDs. Der Dienst bedient mehr als 20 Maschinen, aber das ist zu viel; wir planen, die zugewiesenen Ressourcen zu reduzieren, da die Kapazität von 4-5 Maschinen dafür ausreicht.

Der Sitzungsdienst ist unser erster Dienst auf vshard und Cartridge. Das Einrichten von vshard und das Aktualisieren von Cartridge erforderten von uns einige Anstrengungen, aber am Ende hat alles geklappt.

Der Dienst zur Anzeige verschiedener Banner auf der Website und in der mobilen Anwendung war einer der ersten, der direkt auf Tarantool veröffentlicht wurde. Dieser Dienst zeichnet sich dadurch aus, dass er 6-7 Jahre alt ist, immer noch in Betrieb ist und nie neu gestartet wurde. Es wurde eine Master-Master-Replikation verwendet. Es ist nie etwas kaputt gegangen.

Es gibt ein Beispiel für die Verwendung von Tarantool für die Schnellreferenzfunktion in einem Lagersystem, um in einigen Fällen Informationen schnell noch einmal zu überprüfen. Wir haben versucht, hierfür Redis zu verwenden, aber die Daten im Speicher beanspruchten mehr Platz als Tarantool.

Auch die Dienste einer Warteliste, Kundenabonnements, aktueller Modestories und aufgeschobener Ware funktionieren mit Tarantool. Der letzte Dienst im Speicher belegt etwa 120 GB. Dies ist der umfassendste Service der oben genannten.

Abschluss

Dank Sekundärindizes kombiniert mit Schlüsselwert und Transaktionalität eignet sich Tarantool gut für Microservices-basierte Architekturen. Beim Ausrollen von Änderungen an Diensten mit viel Logik in Lua stießen wir jedoch auf Schwierigkeiten – die Dienste funktionierten oft nicht mehr. Wir konnten dies nicht überwinden und kamen mit der Zeit zu unterschiedlichen Kombinationen von Lua und Go: Wir wissen, wo wir eine Sprache und wo wir eine andere verwenden müssen.

Was gibt es sonst noch zum Thema zu lesen?

Source: habr.com

Kommentar hinzufügen