Wir alle lieben Geschichten. Wir sitzen gerne am Feuer und sprechen über unsere vergangenen Siege, Schlachten oder einfach nur über unsere Arbeitserfahrung.
Heute ist so ein Tag. Und selbst wenn Sie jetzt nicht am Feuer sind, aber wir haben eine Geschichte für Sie. Die Geschichte, wie wir angefangen haben, mit Speicher in Tarantool zu arbeiten.
Es war einmal in unserem Unternehmen ein paar "Monolithen" und eine "Decke" für alle, denen sich diese Monolithen langsam aber sicher näherten, was den Flug unseres Unternehmens und unsere Entwicklung einschränkte. Und es gab ein eindeutiges Verständnis: Eines Tages werden wir hart gegen diese Decke sein.
Jetzt dominieren wir die Ideologie, alles und jeden zu teilen, von der Ausrüstung bis zur Geschäftslogik. Als Ergebnis haben wir beispielsweise zwei DCs, die auf Netzwerkebene praktisch unabhängig sind. Und dann war alles ganz anders.
Heutzutage gibt es eine Reihe von Tools und Tools, um Änderungen in Form von CI / CD, K8S usw. vorzunehmen. In der "monolithischen" Zeit brauchten wir nicht so viele Fremdwörter. Es war genug, nur den "Speicher" in der Datenbank zu reparieren.
Aber die Zeit verging und die Anzahl der Anfragen ging weiter, was manchmal dazu führte, dass RPS über unsere Möglichkeiten hinausging. Mit dem Markteintritt der GUS-Staaten sank die Belastung des Datenbankprozessors des ersten Monolithen nicht unter 90%, und der RPS blieb auf dem Niveau von 2400. Und dies waren nicht nur kleine Selektoren, sondern umfangreiche Abfragen mit einer Reihe von Schecks und JOINs, die fast durchlaufen werden konnten Die Hälfte der Daten auf dem Hintergrund eines großen E / A.
Als vollwertige Verkäufe für Black Friday auf die Bühne kamen - und Wildberries begann, sie als eine der ersten in Russland zu halten - wurde die Situation völlig traurig. Immerhin verdreifacht sich die Belastung an solchen Tagen.
Oh, diese "monolithischen Zeiten"! Ich bin sicher, dass Sie auch auf etwas Ähnliches gestoßen sind und immer noch nicht verstehen können, wie Ihnen das passieren könnte.
Was können Sie tun? Mode ist der Technologie inhärent. Vor 5 Jahren mussten wir einen dieser Mods in Form einer vorhandenen Site auf .NET und MS SQL-Server überdenken, wobei die gesamte Logik der Site selbst sorgfältig beibehalten wurde. Er hielt es so sorgfältig, dass sich das Schneiden eines solchen Monolithen als langes und ziemlich schwieriges Vergnügen herausstellte.
Ein kleiner Exkurs.
Bei verschiedenen Veranstaltungen sage ich: "Wenn Sie den Monolithen nicht gesehen haben, sind Sie nicht gewachsen!" Ich bin an Ihrer Meinung zu diesem Thema interessiert, schreiben Sie sie bitte in die Kommentare.
Ein Geräusch des Donners
Kehren wir zu unserem "Lagerfeuer" zurück. Um die Last der "monolithischen" Funktionalität zu verteilen, haben wir beschlossen, das System auf der Grundlage von OpenSource-Technologien in Microservices zu unterteilen. Zumindest sind sie billiger zu skalieren. Und das Verständnis, dass wir skalieren müssten (und viel), war 100%. In der Tat stellte sich bereits zu diesem Zeitpunkt heraus, dass es in die Märkte der Nachbarländer eintrat, und die Anzahl der Registrierungen sowie die Anzahl der Bestellungen begann noch weiter zu wachsen.
Nachdem wir die ersten Antragsteller analysiert hatten, die den Monolithen in Microservices belassen wollten, stellten wir fest, dass in 80% von ihnen 99% von Backoffice-Systemen schreiben und von Front-End-Systemen lesen. Dies betraf zunächst einige wichtige Subsysteme für uns - Benutzerdaten und das System zur Berechnung der endgültigen Kosten von Waren auf der Grundlage von Informationen über zusätzliche Kundenrabatte und Gutscheine.
Einzug. Jetzt ist es beängstigend, sich das vorzustellen, aber zusätzlich zu den oben genannten Subsystemen wurden auch Produktkataloge, ein Benutzerkorb, ein Produktsuchsystem, ein Filtersystem für Produktkataloge und verschiedene Empfehlungssysteme aus unserem Monolithen herausgenommen. Für den Betrieb eines jeden von ihnen gibt es separate Klassen eng geschärfter Systeme, aber zu einer Zeit lebten sie alle in einem "kleinen Haus".
Wir wollten Daten über unsere Kunden auf ein Sharded-System übertragen. Das Entfernen der Funktionalität zur Berechnung der endgültigen Kosten von Waren erforderte eine gute Leseskalierbarkeit, da dies die größte RPS-Last verursachte und für die Datenbank am schwierigsten zu implementieren war (viele Daten sind in den Berechnungsprozess involviert).
Als Ergebnis haben wir ein Schema, das gut mit Tarantool funktioniert.
Zu dieser Zeit wurden für den Betrieb von Mikrodiensten Schemata für die Arbeit mit mehreren Rechenzentren auf virtuellen Maschinen und Hardwaremaschinen ausgewählt. Wie in den Abbildungen gezeigt, wurden Tarantool-Replikationsoptionen sowohl im Master-Master- als auch im Master-Slave-Modus angewendet.
Die Architektur. Option 1. Benutzerdienst
Derzeit gibt es 24 Shards mit jeweils 2 Instanzen (eine für jeden DC), alle im Master-Master-Modus.
Über der Datenbank befinden sich Anwendungen, die auf Datenbankreplikate zugreifen. Anwendungen arbeiten mit Tarantool über unsere benutzerdefinierte Bibliothek, die die Tarantool Go-Treiberoberfläche implementiert. Sie sieht alle Repliken und kann mit dem Meister zum Lesen und Schreiben zusammenarbeiten. Tatsächlich implementiert es das Replikatsatzmodell, das die Logik für die Auswahl von Replikaten, die Durchführung von Wiederholungsversuchen, einen Leistungsschalter und eine Ratenbegrenzung hinzufügt.
Gleichzeitig ist es möglich, die Richtlinie zur Auswahl eines Replikats im Kontext eines Shards zu konfigurieren. Zum Beispiel Roundrobin.
Die Architektur. Option 2. Service zur Berechnung der Endkosten von Waren
Vor einigen Monaten gingen die meisten Anfragen zur Berechnung der Endkosten von Waren an einen neuen Service, der im Prinzip ohne Datenbanken funktioniert, aber vor einiger Zeit zu 100% vom Service mit Tarantool unter der Haube verarbeitet wurde.
Die Servicedatenbank besteht aus 4 Mastern, in denen der Synchronisierer Daten sammelt, und jeder dieser Replikationsmaster verteilt Daten an schreibgeschützte Replikate. Jeder Master hat ungefähr 15 solcher Zeilen.
Sowohl im ersten als auch im zweiten Schema kann die Anwendung Daten im zweiten empfangen, wenn ein DC nicht verfügbar ist.
Es ist zu beachten, dass die Replikation in Tarantool zur Laufzeit sehr flexibel und konfigurierbar ist. In anderen Systemen gab es Schwierigkeiten. Wenn Sie beispielsweise die Parameter max_wal_senders und max_replication_slots in PostgreSQL ändern, muss der Assistent neu gestartet werden. In einigen Fällen kann dies zu einer Trennung zwischen der Anwendung und dem DBMS führen.
Suche und du wirst finden!
Warum haben wir es nicht "wie normale Menschen" gemacht, sondern einen atypischen Weg gewählt? Es kommt darauf an, was als normal angesehen wird. Viele Leute machen im Allgemeinen einen Cluster aus Mongo und verteilen ihn auf drei geoverteilte DCs.
Zu diesem Zeitpunkt hatten wir bereits zwei Projekte auf Redis. Der erste ist ein Cache und der zweite ist ein dauerhafter Speicher für nicht zu kritische Daten. Es war ziemlich schwierig mit ihm, teilweise durch unsere Schuld. Manchmal waren ziemlich große Mengen im Schlüssel, und von Zeit zu Zeit fühlte sich die Site schlecht an. Wir haben dieses System in der Master-Slave-Version verwendet. Und es gab viele Fälle, in denen dem Master etwas passiert ist und die Replikation unterbrochen wurde.
Das heißt, Redis ist gut für staatenlose Aufgaben, nicht für zustandsbehaftete. Im Prinzip konnten die meisten Probleme gelöst werden, jedoch nur, wenn es sich um Schlüsselwertlösungen mit zwei Indizes handelte. Aber zu der Zeit war Redis ziemlich traurig über Beharrlichkeit und Replikation. Darüber hinaus gab es Beschwerden über die Leistung.
Denken Sie an MySQL und PostgreSQL. Aber der erste hat sich irgendwie nicht bei uns etabliert, und der zweite ist ein ziemlich hoch entwickeltes Produkt für sich, und es wäre unangemessen, einfache Dienste darauf aufzubauen.
Wir haben RIAK, Cassandra und sogar eine Grafikdatenbank ausprobiert. All dies sind Nischenlösungen, die nicht in die Rolle eines allgemeinen universellen Tools zur Erstellung von Diensten passen.
Letztendlich haben wir uns für Tarantool entschieden.
Wir haben ihn kontaktiert, als er in Version 1.6 war. Wir waren daran interessiert an der Symbiose von Schlüsselwert und Funktionalität einer relationalen Datenbank. Es gibt Sekundärindizes, Transaktionen und Leerzeichen, sie sind wie Tabellen, aber nicht einfach, Sie können eine andere Anzahl von Spalten darin speichern. Die Killer-Features von Tarantool waren jedoch Sekundärindizes in Kombination mit Schlüsselwerten und Transaktionen.
Die reaktionsschnelle russischsprachige Community spielte ebenfalls eine Rolle und war bereit, im Chat zu helfen. Wir haben dies aktiv genutzt und direkt im Chat gelebt. Und vergessen Sie nicht eine anständige Ausdauer ohne offensichtliche Fehler und Pfosten. Wenn Sie sich unsere Geschichte mit Tarantool ansehen, hatten wir viele Probleme mit der Replikation, aber wir haben nie Daten aufgrund seiner Schuld verloren!
Die Implementierung begann hart
Zu dieser Zeit war unser Hauptentwicklungsstapel .NET, für das es keinen Konnektor für Tarantool gab. Wir haben sofort angefangen, etwas in Go zu machen. Lua hat auch ziemlich gut gearbeitet. Das Hauptproblem war zu dieser Zeit das Debuggen: In .NET ist damit alles großartig, und danach war es schwierig, in die Welt der eingebetteten Lua einzutauchen, wenn Sie außer Protokollen kein Debuggen haben, war es schwierig. Außerdem fiel die Replikation aus irgendeinem Grund regelmäßig auseinander, sodass ich mich mit der Struktur der Tarantool-Engine befassen musste. Der Chat half dabei in geringerem Maße - die Dokumentation sah manchmal den Code an. Zu dieser Zeit war die Dokumentation so lala.
Innerhalb weniger Monate gelang es mir, die Zapfen zu füllen und bei der Arbeit mit Tarantool anständige Ergebnisse zu erzielen. Wir haben die Referenzentwicklungen in Git formalisiert, die zur Bildung neuer Mikrodienste beigetragen haben. Als beispielsweise die Aufgabe auftrat: Um einen weiteren Microservice zu erstellen, sah sich der Entwickler den Quellcode der Referenzlösung im Repository an, und es dauerte nicht länger als eine Woche, um einen neuen zu erstellen.
Dies waren besondere Zeiten. Herkömmlicherweise war es dann möglich, sich an den Administrator am Nebentisch zu wenden und zu fragen: "Geben Sie mir eine virtuelle Maschine." 30 Minuten später hatten Sie bereits das Auto. Sie haben selbst eine Verbindung hergestellt, alles installiert und Verkehr dazu erhalten.
Heute wird es nicht mehr so funktionieren: Sie müssen die Überwachung beenden, sich beim Dienst anmelden, die Funktionalität mit Tests abdecken, eine virtuelle Maschine bestellen oder an Kuber liefern usw. Im Allgemeinen wird es besser sein, wenn auch länger und mühsamer.
Teile und herrsche. Was ist mit Lua?
Es gab ein ernstes Dilemma: Einige Teams konnten Änderungen in einem Dienst mit viel Lua-Logik nicht zuverlässig einführen. Dies ging häufig mit der Inoperabilität des Dienstes einher.
Das heißt, die Entwickler bereiten eine Art Änderung vor. Tarantool startet die Migration und das Replikat enthält weiterhin den alten Code. Einige DDLs, etwas anderes, kommen dort durch Replikation an, und der Code fällt einfach auseinander, weil er nicht berücksichtigt wird. Infolgedessen wurde der Aktualisierungsvorgang für die Administratoren auf Blatt A4 geplant: Replikation stoppen, aktualisieren, Replikation aktivieren, hier deaktivieren, dort aktualisieren. Albtraum!
Infolgedessen versuchen wir jetzt meistens, in Lua nichts zu tun. Nur iproto (ein binäres Protokoll für die Kommunikation mit dem Server) verwenden, und das war's. Vielleicht ist dies ein Mangel an Wissen unter den Entwicklern, aber unter diesem Gesichtspunkt ist das System komplex.
Wir folgen diesem Szenario nicht immer blind. Heute haben wir kein Schwarzweiß: Entweder ist alles in Lua oder alles ist in Go. Wir wissen bereits, wie Sie sie kombinieren können, damit Sie später keine Probleme mit der Migration haben.
Wo ist Tarantool jetzt?
Tarantool wird im Service zur Berechnung der endgültigen Kosten von Waren unter Berücksichtigung von Rabattgutscheinen, auch "Promoter" genannt, verwendet. Wie ich bereits sagte, geht es jetzt in den Ruhestand: Es wird durch einen neuen Katalogdienst mit vorberechneten Preisen ersetzt, aber vor sechs Monaten wurden alle Berechnungen im Promoter durchgeführt. Zuvor war die Hälfte seiner Logik in Lua geschrieben. Vor zwei Jahren wurde aus dem Dienst ein Speicher erstellt, und die Logik wurde in Go umgeschrieben, da sich die Mechanik der Rabatte geringfügig änderte und dem Dienst die Leistung fehlte.
Einer der wichtigsten Dienste ist das Benutzerprofil. Das heißt, alle Wildberries-Benutzer werden in Tarantool gespeichert, und es gibt ungefähr 50 Millionen von ihnen. Ein System, das durch die Benutzer-ID gespalten ist und auf mehrere Domänencontroller mit einer Verbindung zu Go-Diensten verteilt ist.
Laut RPS war "Promoter" einst der Anführer und erreichte 6.000 Anfragen. Zu einem Zeitpunkt hatten wir 50-60 Exemplare. Derzeit sind Benutzerprofile mit etwa 12.000 RPS führend. Dieser Dienst verwendet benutzerdefiniertes Sharding mit einer Division nach Benutzer-ID-Bereichen. Der Service bedient mehr als 20 Maschinen, aber das sind zu viele. Wir planen, die zugewiesenen Ressourcen zu reduzieren, da die Kapazität von 4-5 Maschinen ausreicht.
Der Sitzungsservice ist unser erster Service für vshard und Cartridge. Das Einrichten von vshard und das Aktualisieren von Cartridge erforderten einige Arbeit von uns, aber am Ende hat alles geklappt.
Der Dienst zum Anzeigen 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, noch in Betrieb ist und nie neu gestartet wurde. Die Replikation war Master-Master. Nie etwas kaputt gemacht.
Es gibt ein Beispiel für die Verwendung von Tarantool als Kurzreferenzfunktion in einem Lagersystem, um Informationen in einigen Fällen schnell zu überprüfen. Wir haben versucht, Redis dafür zu verwenden, aber die Daten im Speicher beanspruchten mehr Speicherplatz als Tarantool.
Wartelistendienste, Kundenabonnements, trendige Geschichten und Regalwaren funktionieren ebenfalls mit Tarantool. Der letzte Dienst im Speicher beträgt ca. 120 GB. Dies ist der umfangreichste Service der oben genannten.
Fazit
Sekundärindizes in Kombination mit Schlüsselwert- und Transaktionseigenschaften machen Tarantool ideal für Microservice-Architekturen. Wir hatten jedoch Schwierigkeiten, als wir Änderungen an Diensten mit viel Logik in Lua einführten - Dienste funktionierten oft nicht mehr. Wir konnten dies nicht besiegen und kamen im Laufe der Zeit zu verschiedenen Kombinationen von Lua und Go: Wir wissen, wo wir eine Sprache verwenden müssen und wo wir eine andere verwenden müssen.
Was gibt es sonst noch zu diesem Thema zu lesen?
- Wir erstellen von Grund auf eine hoch geladene Anwendung auf Tarantool habr.com/ru/company/mailru/blog/510440
- Die Wahl des zuverlässigen Marktführers in Tarantool Cartridge habr.com/ru/company/mailru/blog/513912
- Tarantool-Telegrammkanal mit Produktneuheiten t.me/tarantool_news
- Besprechen Sie Tarantool im Community-Chat t.me/tarantoolru