Der übersehene Effekt der Datengröße
Besonderer Dank geht an Özgür Karakaya, mit dem ich diesen Blog-Beitrag geschrieben habe.
PDP (Product Detail Page) in Trendyol ist ein Team, das für die Bereitstellung von Informationen zu bestimmten Produkten verantwortlich ist. Diese Informationen umfassen den Preis, die Größe, die Farbe oder andere relevante Informationen eines Produkts, die Kunden vor dem Kauf wissen möchten. Die Informationen können auf zwei verschiedene Arten präsentiert werden, die erste ist in Form einer einzelnen Produktdetailseite, hauptsächlich wenn Sie auf ein Produkt klicken und zu einer Seite navigiert werden, auf der die spezifischen Produktinformationen angezeigt werden. Das Team ist auch dafür verantwortlich, Produktdetaildaten für andere Ansichten auf der Website bereitzustellen, dh Ihre Favoritenliste, empfohlene Produkte und den Checkout. Beide Wege wurden von einem Dienst namens Product Detail API gehandhabt, der von der couchbase NoSQL-Datenbank unterstützt wurde, die einzelne Anfragen (einzelne Produktdetailseite) sowie Anfragen in großen Mengen (Favoritenliste usw.) bediente.
Vor dem Black Friday-Event im Jahr 2021 hatte sich das Team zum Ziel gesetzt, 8 Millionen Anfragen pro Minute für Massenanfragen zu bearbeiten. Ein Problem war, dass der Dienst in Form einer erhöhten Speichernutzung und einer beträchtlichen Anzahl von Fehlern schlecht abschneidet, wenn er einen hohen Durchsatz erhält. Die Herausforderung bestand darin, einen Weg zu finden, den Service zu optimieren.
Hier also die Reise.
Brainstorming & Analyse
Während der Analysephase stellte das PDP-Team fest, dass – bezogen auf die Domäne – Clients, die Massenanfragen senden, nicht alle Felder im Datenbankdokument verwenden. Der erste Optimierungspunkt war die Einführung eines neuen Dokumentenmodells ohne diese unnötigen Felder. Die Vorteile dieser Umstrukturierung sind:
- Optimierung der Datengröße
- Bulk-Content-Domain-Fokus
Unten ist ein Diagramm der bestehenden und neuen Architektur zu diesem Zeitpunkt:
Die gepunkteten äußeren Kästchen definieren die Grenzen eines Dienstes. Beachten Sie, dass in dieser ersten Abbildung ein Dienst für die Abwicklung der gesamten Operationspipeline verantwortlich war. Die Optimierung selbst bestand darin, die Konvertierungspipeline in zwei separate Prozesse aufzuteilen, wie in der zweiten Architektur zu sehen: Der Indexzeit-Konvertierungsprozess und der Masseninhaltsdienst. Letzteres ist ein Lesedienst, der HTTP-Anforderungen verarbeitet. Ersteres stellte sich als ereignisgesteuerter Prozess heraus, der Daten aus ProductContent CB (Source Of Truth) liest, teilweise verarbeitet und sie dann in einem Counchbase-Bucket zur Verwendung durch Letzteres speichert. Aber dazu später mehr.
Unter der vorgeschlagenen neuen Architektur besteht der Hauptgewinn darin, dass der Laufzeitprozess optimiert wird, was wiederum die Antwortzeit des Dienstes verkürzt.
In diesem Blog konzentrieren wir uns auf den Index-Time-Prozess. Weitere Informationen zu „Bulk Content Service“ finden Sie in diesem Beitrag von Enes Turgut
PS Ich verwende den Begriff Laufzeit hier eher locker. Im Kontext dieses Blogs definieren wir die Laufzeit als die Abfolge von Vorgängen, die durch eine eingehende HTTP-Anforderung ausgelöst werden.
Bestehende Lösungen
Bisher hatte sich das Team auf die neue Architektur geeinigt. Jetzt geht es an die Umsetzung. Was wir zu erreichen versuchen, ist eine Couchbase-zu-Couchbase-Konvertierungslösung nahezu in Echtzeit. Couchbase bietet bereits eine Cluster-übergreifende Replikation, allerdings muss die Form der Daten geändert werden, sodass eine normale Replikation offensichtlich nicht der richtige Weg ist. Wäre es nicht großartig, wenn es eine Möglichkeit gäbe, die Daten während des Replikationsprozesses zu manipulieren? Beim Durchstöbern der Couchbase-Dokumentation sind wir auf Couchbase Eventing Service gestoßen. Haben wir gerade den Jackpot geknackt?
Couchbase Vielseitigkeit:
Der Couchbase Eventing Service ist ein Framework, um Änderungen an Daten in Echtzeit zu bearbeiten. Events sind Änderungen an Daten im Couchbase-Cluster
Couchbase Eventing schien gut zu uns zu passen, weil Sie :
- Geben Sie Änderungen an andere Systeme weiter
- Reichern Sie ein Dokument in Echtzeit an
- Benötigt keine Wartung
Kein Jackpot.
Unsere Lösung (Converter für Masseninhaltsdaten)
Inspiriert von CB Elasticsearch Connector .
Der Couchbase Elasticsearch Connector repliziert Ihre Dokumente nahezu in Echtzeit von Couchbase Server zu Elasticsearch. Der Connector verwendet das leistungsstarke Database Change Protocol (DCP), um Benachrichtigungen zu erhalten, wenn sich Dokumente in Couchbase ändern.
Ersetzen Sie Elasticsearch durch Couchbase und Sie bekommen genau das, was wir brauchen. Alles, was wir tun müssen, ist, Dokumentmutationen (Aktualisierungen) aus der DCP-Warteschlange zu akzeptieren, sie zu verarbeiten und sie dann in einen neuen Bucket zu schreiben.
Denken Sie daran, dass die Lösung in der Lage sein muss:
- Skalieren Sie, wenn die Anzahl der Dokumente und Mutationen wächst.
- Führen Sie den End-to-End-Prozess (Annehmen von Nachrichten aus der Warteschlange, Konvertieren des Datenmodells und Schreiben in einen neuen Bucket) nahezu in Echtzeit durch.
- Bearbeiten Sie die vorhandenen und nicht nur die neuen Dokumente, wenn neue Felder zum Dokumentenmodell hinzugefügt oder daraus entfernt werden.
- Stellen Sie einen Mechanismus bereit, um Dokumente im Falle einer schwerwiegenden Datenbeschädigung von Grund auf neu zu generieren.
Nun, hier gibt es einiges zu entpacken, fassen wir zuerst zusammen:
Die obige Architektur zeigt die endgültige Lösung. Letztendlich wird der Product Detail Service einzelne Anfragen bearbeiten, während der Bulk Content Service Anfragen in großen Mengen bearbeiten wird. Die Dienste werden von verschiedenen Couchbase-Quellen unterstützt. Während ProductContent CB die Quelle der Wahrheit darstellt, stellt ProductSummary CB eine zusammengefasste vorverarbeitete Version davon dar. Die Konvertierung wird in Bulk Content Data Converter nahezu in Echtzeit durchgeführt, indem Dokumentmutationen aus der DCP-Warteschlange akzeptiert werden. Jede Dokumentmutation repräsentiert den Status des Dokuments nach der Aktualisierung. Dies ist eine andere Art zu sagen, dass der Konverter automatisch das gesamte aktualisierte Dokument von ProductContent CB erhältbei jedem Update.
Um zu verstehen, wie diese Lösung genau skaliert, sollte man sich die Konfigurationsdatei des Konverters ansehen:
{
"group": {
"name": "v20220909",
"membership": {
"memberNumber": 1,
"totalMembers": n
},
"limit": {
"bytes": "5m",
"actions": 100,
"timeout": "1m",
"concurrency": 2
},
"version": 1,
"ignoreDelete": false
},
"dcp": {
"sourceConfig": {
"hosts": ["source_couchbase_host"],
"network": "auto",
"bucket": "bucketName",
"metadataBucket": "metadataBucketName",
"scope": "",
"collections": [],
"compression": true,
"flowControlBuffer": "16m",
"persistencePollingInterval": "100ms"
},
"targetConfig": {
"hosts": ["taget_couchbase_host"],
"bucket": "targetBucketName"
}
}
}
Ein weiterer wichtiger Bestandteil der Konfiguration ist group.name , der die Verbrauchergruppe darstellt, in der ein Offset gespeichert ist, denken Sie an Kafka-Verbrauchergruppen. Das Ändern dieser Konfiguration setzt den Offset-Index zurück, was bedeutet, dass der gesamte Datenbankstatus über die DCP-Warteschlange gesendet wird. Dies ist besonders praktisch, wenn eine Aktualisierung des Dokumentenmodells erforderlich ist, das Hinzufügen oder Entfernen neuer Felder aus dem Ziel-Bucket eine vollständige Aktualisierung aller gespeicherten Dokumente erfordert, einschließlich der Dokumente, die sonst normalerweise nicht einfach im Ziel-Bucket aktualisiert worden wären weil in den Quelldokumenten keine Mutationen aufgetreten wären. Es kann auch als vollständiger Datenbankregenerierungsmechanismus im Falle einer schwerwiegenden Datenbeschädigung fungieren.
Weitere Informationen zur Konfiguration finden Sie unter dem Dokumentationslink .
Ein weiterer Optimierungspunkt bestand darin, die Größe des Zieldokuments zu reduzieren, indem Abkürzungen oder einzelne Zeichen als JSON-Knoten verwendet wurden. Von Domänenexperten und PMs wird nicht erwartet, dass sie dieses Dokument verstehen, und deshalb können wir mit solchen bösen Hacks davonkommen. Unten ist ein Beispiel für das Dokument:
Und zum 31. Oktober lautet das Ergebnis…
Mit diesem einfachen Hack konnten wir die Bucket-Größe von 2,92 TB auf 595 GB reduzieren! Eine umwerfende Größenreduzierung von ca. 80 %!
Man muss auch bemerkt haben, dass die Dokumentenanzahl in der Ziel-DB um ca. 12 Millionen reduziert ist. Der Grund dafür ist, dass wir nicht vorrätige Produkte ausgeschlossen haben, die seit 12 Monaten nicht aktualisiert wurden. Im Quell-Bucket benötigen wir diese Dokumente möglicherweise immer noch, aber es wäre nicht sinnvoll, sie hier zu haben, daher der Unterschied in der Anzahl.
Leistungsüberwachung
Bisher haben wir die Lösung zum Laufen gebracht. Aber wie genau können wir feststellen, ob es leistungsfähig genug ist? Was ist, wenn es hypothetisch die Konvertierung durchführt, aber beispielsweise 2 Sekunden hinterherhinkt? Das wäre eine absolute Katastrophe! Eine solche letztendliche Konsistenz wird bis zur Benutzeroberfläche der Website durchsickern und die Benutzererfahrung stark beeinträchtigen. Das manuelle Auslösen einer Änderung in der Produktionsdatenbank ist nicht möglich und sollte nicht der erste Weg zum Testen sein. Ein systematischer Ansatz ist erforderlich, um die Ursache der Verzögerung zu lokalisieren, falls sie auftritt. Tritt die Verzögerung aufgrund einer Überlastung in der DCP-Warteschlange auf? Oder liegt es daran, dass der Konverter einen Fehler hat?
Um diese Fragen zu beantworten, haben wir drei Metriken eingeführt, wie in der folgenden Abbildung dargestellt:
Das Quelldokument enthält den Zeitstempel der letzten Aktualisierung, wir nennen das LMD (Last Modified Date). Sobald eine Mutation vom Konverter empfangen wird, kann die „ Warten in der DCP-Warteschlange“ -Zeit einfach berechnet werden, indem LMD von time.now() subtrahiert wird . Metriken werden dann Prometheus ausgesetzt, wie in den folgenden Diagrammen gezeigt:
Einschränkungen:
Erinnern Sie sich, als ich vorhin sagte, dass es beim Skalieren nur darum geht, die Gesamtzahl der Konverter zu erhöhen? Nun, das kommt mit einem kleinen Vorbehalt: Die Konfiguration der Lösung ist ein bisschen fest mit der Infrastruktur verbunden, mit der sie spricht; Die automatische Neuverteilung der Verbraucher in der DCP-Warteschlange und die Verteilung der Verbraucher auf vBuckets sind fest mit der statischen Konfiguration verbunden, die der Verbraucher beim Start hat. Um dies zu ändern, muss die Konfigurationsdatei selbst geändert werden, was eine neue Bereitstellung erfordert. Darüber hinaus benötigt jeder Verbraucher seine eigene statische Konfigurationsdatei, was bedeutet, dass jeder Verbraucher – in der Kubernetes-Terminologie – über seine eigenen Ressourcendateien für die Bereitstellung verfügen muss. Bei Trendyol verwenden wir häufig ArgoCD mit Kustomize, um unsere Bereitstellungen zu verwalten. Das Skalieren der Lösung erfordert das Hinzufügen – in ArgoCD-Terminologie – eines neuen ApplicationSet.
Bisher bewältigt unsere Waage mit 8 Verbrauchern die große Last jedoch nahezu in Echtzeit. Aber wenn der Quell-Bucket größer wird und die Anzahl der Mutationen zunimmt, müssen die Verbraucher manuell neu konfiguriert werden.
Interne Nutzung anderer Teams
Das PDP-Team war von dem entwickelten CB-zu-CB-Steckverbinder überzeugt und beschloss, ihn anderen Teams innerhalb von Trendyol vorzustellen. Das Team erhielt viele positive Rückmeldungen, und ehe wir uns versahen, beschloss das Suchteam, das Projekt zu forken und es in seiner Domäne zu verwenden, wo es Domänenereignisse in einer Couchbase-Datenbank speichert und den CB-zu-CB-Konnektor verwendet, um ein weiteres Dokumentmodell zu generieren zur späteren Verwendung. Eine solche Übernahme von intern entwickelten Lösungen inspiriert uns alle, voranzukommen und unseren Einsatz von Technologie weiter zu verbessern und zu verfeinern.
Bewerben Sie sich hier auf unsere offenen Stellen !

![Was ist überhaupt eine verknüpfte Liste? [Teil 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































