KeyDB als [potenzieller] Ersatz für Redis

Auf Habr gab es keine Berichte über eine "schnellere Alternative zu Redis" — KeyDB. Nach ausreichend frischen Erfahrungen mit seiner Nutzung möchte ich diese Lücke schließen.

KeyDB als [potenzieller] Ersatz für Redis

Die Vorgeschichte ist recht banal: Bei einem plötzlichen Anstieg des Traffics wurde eine erhebliche Leistungseinbuße der Anwendung (insbesondere der Antwortzeiten) festgestellt. Zu diesem Zeitpunkt war es bedauerlicherweise nicht möglich, eine ordentliche Diagnose des Geschehens durchzuführen, weshalb im Anschluss eine Reihe von Lasttests eingeplant wurde. Nach deren Durchführung konnte der Engpass identifiziert werden, der durch den Redis-Datenbankcache verursacht wurde. Wie oft der Fall, konnte das Problem nicht sofort und auf die richtige Weise — durch die Entwickler (Änderung der Arbeitslogik) — gelöst werden. Daher setzte die Neugier ein und der Wunsch, die Situation auf Umwegen zu verbessern. So entstand dieser Artikel.

Problemstellung

Über Redis im Allgemeinen

Wie vielen bekannt ist, ist Redis eine Single-Thread-Datenbank. Genauer gesagt ist sie dies im Kontext des Umgangs mit Benutzerdaten. Seit der vierten Version betrifft dies auch interne Operationen von Redis. übersetzt für parallele Ausführung. Dennoch betraf diese Änderung nur einen kleinen Teil der Last, da die Hauptarbeit auf den Benutzerdaten lastet.

Zahlreiche Artikel wurden zu diesem Thema verfasst, aber die Entwickler von Redis weigern sich beharrlich, volle Parallelität einzuführen, und weisen darauf hin, wie sehr dies die Anwendung komplizieren und die Verwaltungskosten erhöhen sowie die Anzahl der Bugs steigern würde. Ihre Position ist, dass, wenn Sie auf ein Ein-Kern-Problem stoßen, Ihre Anwendungsarchitektur nicht optimal ist und Sie etwas daran ändern müssen. Es gibt jedoch auch eine "andere Lager" unter den Nutzern – jene, die auf einen Kern angewiesen sind und behaupten, dass Redis sich selbst ein Flaschenhals schafft. Bei wirklich großen Lasten wird man früher oder später unweigerlich mit diesem Problem konfrontiert, was erhebliche Einschränkungen für die Architektur und/oder deren notwendige Komplikationen zur Folge hat.

Ich werde keines der beiden Meinungen bewerten. Stattdessen teile ich unseren spezifischen Fall und wie wir ihn gelöst haben.

Unser Fall

In einem unserer Projekte standen wir vor der Herausforderung, dass das Entwicklungsteam eine extrem aggressive Datenbank-Cache-Konfiguration (PostgreSQL) über Redis eingerichtet hatte. Dies war der einzige Weg, um während starker Verkehrsspitzen die PostgreSQL-Datenbank und damit die Anwendung zu retten.

Nach einer Reihe von Lasttests haben wir die Situation analysiert und festgestellt, dass Redis an einem Kern „hing“ (wie man sagt, „in der Warteschlange“), was zu einer recht schnellen Verschlechterung der Anwendungsleistung führte. Das „Abstürzen“ geschah in geometrischer Progression: Sobald das Leistungsmaximum von Redis erreicht war, funktionierte nichts mehr.

Das sah etwa so aus:

KeyDB als [potenzieller] Ersatz für Redis

Von New Relic wurde das Problem eindeutig identifiziert:

KeyDB als [potenzieller] Ersatz für Redis

Und hier ist die Statistik zur Operation get in Redis:

KeyDB als [potenzieller] Ersatz für Redis

Nachdem das Problem in allen Einzelheiten dem Entwicklungsteam geschildert wurde, stellte sich heraus, dass „das Problem im Moment nicht gelöst werden kann“. So begann die Suche nach einer Lösung auf der Seite des Betriebs, und die Antwort war bereits erwähnte KeyDB.

Bevor wir jedoch mit der Überprüfung beginnen, sollte erwähnt werden, dass in diesem Projekt ein eigenständiges Redis verwendet wird, da die Clusterlösung auf Basis von Sentinel in Bezug auf Latenzen deutlich nachteilig ist. Eine naheliegende Lösung wäre gewesen, mehrere Cache-Replikate zu erstellen: so könnte die Anwendung überall mit Lastenverteilung agieren! Nach Rücksprache mit den Entwicklern waren wir jedoch gezwungen, diesen Ansatz aufgrund des aktiven und komplexen Cache-Invalidierungsmechanismus der Anwendung abzulehnen. Das gleiche Problem galt auch für das Sharding des Caches.

Kurze Übersicht über KeyDB

Auf der Suche nach einer möglichen Lösung des Problems stießen wir auf eine Anwendung namens KeyDB. Dies ist ein Fork von Redis, der von der kanadischen Firma entwickelt und unter der freien BSD-Lizenz veröffentlicht wird. Das Projekt ist noch recht jung: es existiert seit Anfang 2019. Die Geschichte ist die, dass die Autoren ebenfalls einmal mit den Einschränkungen von Redis konfrontiert waren… und sich entschieden, ihren eigenen Fork zu erstellen. Dabei wurden nicht nur die bekannten Probleme gelöst, sondern es wurden auch zusätzliche Funktionen hinzugefügt, die nur in der Enterprise-Version von Redis verfügbar sind.

Für alle, die sich ausführlicher mit KeyDB beschäftigen möchten, gibt es einen guten einführenden Artikel auf Medium, das eine DBMS darstellt und kurze Benchmarks bietet, die es mit seinem „Elternteil“ – Redis – vergleichen.

Zunächst einmal hat uns KeyDB als potenzielle Lösung für unsere Probleme angezogen, und wir waren auch an einigen zusätzlichen Funktionen interessiert. Die Nutzung von KeyDB versprach folgende Vorteile:

  • vollständige Multi-Threading-Funktionalität;
  • vollständige und absolute Kompatibilität mit Redis (für uns war das besonders wichtig, da es nicht möglich war, Anpassungen auf der Anwendungsseite vorzunehmen), was auch einen reibungslosen Migrationsprozess versprach;
  • eingebauter Backup-Mechanismus für S3-Speicher;
  • einfache Active-Replikation;
  • einfache Clusterbildung und Sharding ohne Sentinel oder andere unterstützende Software.

Über 3.000 Sterne und zahlreiche Mitwirkende auf GitHub sahen ebenfalls vielversprechend aus. Die Anwendung wird aktiv entwickelt und gepflegt, was sich deutlich an den Commits, der Kommunikation in den Issues sowie an den geschlossenen (angenommenen) PRs zeigt. Das Feedback des Hauptmaintainers ist stets freundlich und schnell. Insgesamt gab es ausreichend Argumente.

Migration und Ergebnisse

Obwohl das Migrationsprojekt eine gewisse Abenteuerlust mit sich brachte (aufgrund der Neuheit von KeyDB), hatten wir nicht viel zu verlieren. Die Änderungen konnten zum Glück schnell und einfach zurückgesetzt werden – schließlich ist die gesamte Infrastruktur in Kubernetes aufgesetzt, und die integrierten Mechanismen Rolling Update lösen solche Aufgaben hervorragend.

Wir haben Helm-Vorlagen vorbereitet, die Anwendung in der Testumgebung auf die neue Datenbank umgeschaltet und alles an die QA-Abteilung des Kunden übergeben.

Das Testing begann und dauerte etwa eine Woche, in die wir nicht im Detail eingetaucht sind. Uns ist nur bekannt, dass der Kunde die Standardfunktionen von Redis mit dem PHP-Treiber phpredisüberprüft hat, sowie QA-Tests der Benutzeroberfläche durchgeführt wurden. Danach erhielt wir das grüne Licht: Es wurden keine Nebenwirkungen bei der Nutzung der neuen Software festgestellt. Das heißt, aus der Sicht der Anwendung hat sich überhaupt nichts verändert..

Es ist erwähnenswert, dass wir auch in der Konfiguration nichts geändert haben: Wir haben lediglich das verwendete Image ersetzt. Dasselbe gilt für das Monitoring und den Export von Metriken nach Prometheus: der am weitesten verbreitete unter ihnen funktioniert hervorragend mit KeyDB und ohne jegliche Anpassungen. Daher kann man mit Zuversicht sagen, dass der Umstieg aus betrieblicher Sicht einfach ideal ist.

Dank all dem kann nach der Umstellung der Anwendung auf die neue DBMS zunächst alles beibehalten werden, und als 'Stabilisierungsmaßnahme' kann es eine Zeit lang im aktuellen Zustand betrieben werden. Wenn Sie jedoch eine Leistungssteigerung (oder überhaupt irgendwelche Änderungen) sehen möchten, sollten Sie nicht vergessen, dass standardmäßig verwendet der KeyDB-Parameter, der für das Multithreading verantwortlich ist (server-threads), auf eins gesetzt ist, was bedeutet, dass die DBMS genau wie Redis funktioniert..

Nach der Umstellung, dem Test und einer gewissen Betriebszeit der neuen Anwendung (mit KeyDB) haben wir beschlossen, das Lasttest mit denselben Parametern zu wiederholen, die für Redis verwendet wurden. Wie waren die Ergebnisse davon?..

Auf dem CPU-Verbrauchsdiagramm war sofort eine Beseitigung der Probleme mit dem 'Engpass' auf einem Kern zu erkennen: Der Prozess begann, die verfügbaren Ressourcen zu nutzen:

KeyDB als [potenzieller] Ersatz für Redis

Und anschließend habe ich versucht, die Anwendung stark zu 'beanspruchen' und beobachtet, dass der Verbrauch bis zu drei Kernen reichte...

Laut New Relic zeigt die Webanwendung bei gleicher Last deutlich bessere Ergebnisse. Es gab zwar eine gewisse Verschlechterung der Leistung, aber im Vergleich zu dem ähnlichen Diagramm oben können Sie selbst den erheblichen Fortschritt beurteilen:

KeyDB als [potenzieller] Ersatz für Redis

Der Latenzwert der neuen Datenbank (KeyDB) hat sich ebenfalls verschlechtert, blieb jedoch innerhalb akzeptabler Werte:

KeyDB als [potenzieller] Ersatz für Redis

Das folgende Diagramm zeigt deutlich, dass die Anzahl der Anfragen an die KeyDB ähnlich ist:

KeyDB als [potenzieller] Ersatz für Redis

Zusammenfassend lässt sich sagen, dass sowohl Redis als auch KeyDB eine signifikante Leistungseinbuße bei der Latenz (über 40 ms) bei einem deutlichen Anstieg der parallelen Verbindungen (über 1000) zeigen. In unserem Fall konnte die Webanwendung die Latenz von Redis auch bei einer niedrigeren Anzahl an Verbindungen (über 400) spürbar reduzieren, während KeyDB mit dieser Last weiterhin gut zurechtkam.

Fazit

In diesem Beispiel wird die Kraft der Open Source-Community bei der Entwicklung von Projekten, die sie interessiert, deutlich sichtbar. Im Internet bin ich auf einen hervorragenden Spruch gestoßen, dessen allgemeiner Sinn folgendermaßen lautet: „Ein großes Unternehmen entwickelt ein interessantes Produkt, macht einen Teil seiner Funktionen öffentlich, behält aber den wichtigsten Teil kostenpflichtig. Die Community nutzt es, und irgendwann entscheidet sich jemand, einen Fork zu erstellen, in dem genau diese kostenpflichtigen Funktionen umgesetzt und für alle geöffnet werden.“ KeyDB ist genau so ein Fall.

Wenn wir über die Migration sprechen, die erstaunlicherweise reibungslos verlief, haben wir nicht so einen signifikanten Anstieg der Leistung erhalten, den man erwarten könnte, wenn man sich die Grafiken der KeyDB-Autoren ansieht… Das ist jedoch lediglich unser spezifischer Fall, der viele Abweichungen aufweisen kann, die unter anderem die berüchtigte Architektur der Anwendung betreffen (zum Beispiel die große Anzahl an Befehlen get in Redis statt der leistungsfähigeren aggregierten Anfragen mget… Dennoch konnten positive Ergebnisse erzielt werden, sowie viele nützliche Funktionen, die wir in der nahen Zukunft implementieren werden.

Insgesamt zeigt KeyDB vielversprechende Ansätze: Mit zunehmender praktischer Erfahrung in der Nutzung dieser Datenbank (die wir noch sammeln müssen!) und der Entwicklung des Projekts werden wir die Möglichkeit dessen Einsatzes in anderen Szenarien in Betracht ziehen.

Es sollte jedoch nicht als Anleitung (und erst recht nicht als Aufruf) zur vollständigen Ablösung von Redis zugunsten von KeyDB angesehen werden. Trotz unserer positiven Erfahrungen ist klar, dass dies kein Allheilmittel ist. Der Fall war sehr spezifisch: Für die sofortige Lösung eines Problems, bei dem Schnelligkeit und minimale Kosten erforderlich waren, hat sich diese Lösung als sinnvoll erwiesen. Wird KeyDB in Ihrem Fall hilfreich sein? Jedenfalls wissen Sie jetzt, dass eine solche Möglichkeit besteht.

P.S.

Lesen Sie auch in unserem Blog:

Quelle: habr.com

Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen 🔥 Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen | ProHoster