KeyDB als [potenzielle] Alternative zu Redis

Auf Habr gab es keine Bewertungen über "schnellere Alternativen zu Redis" — KeyDB. Nachdem ich eine ausreichende aktuelle Erfahrung mit seiner Nutzung gesammelt habe, möchte ich diese Lücke schließen.

KeyDB als [potenzielle] Alternative zu Redis

Die Vorgeschichte ist ziemlich banal: Eines Tages wurde bei einem großen Ansturm von Verkehr eine erhebliche Leistungsverschlechterung der Anwendung (insbesondere der Antwortzeit) festgestellt. Zu diesem Zeitpunkt war es leider nicht möglich, eine ordentliche Diagnose des Geschehens durchzuführen, weshalb wir anschließend eine Reihe von Lasttests planten. Nach deren Durchführung konnten wir den Engpass erkennen, der in der Datenbank-Cache von Redis lag. Wie es oft der Fall ist, konnte das Problem nicht sofort und auf die richtige Weise — durch die Entwickler (Änderung der Arbeitslogik) — gelöst werden. Daher wurde die Neugierde und der Wunsch, die Situation auf Umwegen zu bewältigen, geweckt. So entstand dieser Artikel.

Problemstellung

Über Redis im Allgemeinen

Wie vielen bekannt ist, ist Redis eine Einzelfaden-Datenbank. Genauer gesagt ist sie dies im Kontext der Arbeit mit Benutzerdaten. Seit der vierten Version wurden jedoch die dienstlichen, internen Operationen von Redis auf parallele Ausführung umgestellt. Dennoch betraf diese Änderung nur einen kleinen Teil der Last, da die Hauptarbeit auf den Benutzerdaten lastet. Zu diesem Thema wurden unzählige Meinungen geäußert, aber die Redis-Entwickler weigern sich hartnäckig, vollständige Parallelität einzuführen, und weisen darauf hin, wie sehr dies die Anwendung komplizieren und die Kosten erhöhen sowie die Anzahl der Bugs steigern würde. Ihre Position ist wie folgt: Wenn Sie auf das Problem der Einkernigkeit stoßen — haben Sie Probleme mit der Architektur der Anwendung und müssen etwas daran ändern. Unter den Nutzern gibt es jedoch auch "das andere Lager" — von denen, die sich in einem Kern festgefahren haben und behaupten, dass Redis sich selbst einen Flaschenhals schaffen. Bei wirklich großen Lasten wird man früher oder später unvermeidlich mit diesem Problem konfrontiert, was erhebliche Einschränkungen für die Architektur und/oder notwendige Komplikationen innerhalb derselben mit sich bringt.

Ich werde keine Bewertung zu dem einen oder anderen Standpunkt abgeben. Stattdessen teile ich unseren konkreten Fall und wie wir ihn gelöst haben.

Unser Fall

Unser Fall

Bei einem unserer Projekte stießen wir auf das Problem, dass das Entwicklungsteam ein extrem aggressives Caching von Daten aus der Datenbank (PostgreSQL) über Redis eingerichtet hatte. Dies war der einzige Weg, der während plötzlicher Traffic-Spitzen PostgreSQL und damit die Anwendung vor dem Absturz rettete.

Nach einer Reihe von Lasttests führten wir eine Analyse der Situation durch und entdeckten, dass Redis auf einem Kern (wie man so schön sagt, „im Lager“) festhing, wonach eine recht schnelle Verschlechterung der Anwendung folgte. Das „Ersticken“ hatte eine geometrische Progression: Sobald die Leistungsgrenze von Redis erreicht war, hörte alles auf zu funktionieren.

So sah es ungefähr aus:

KeyDB als [potenzielle] Alternative zu Redis

Von New Relic wurde eindeutig ein Problem identifiziert:

KeyDB als [potenzielle] Alternative zu Redis

Und hier sind die Statistiken zur Operation get in Redis:

KeyDB als [potenzielle] Alternative zu Redis

Nachdem wir das Problem in allen Einzelheiten dem Entwicklungsteam mitgeteilt hatten, stellte sich heraus, dass es „aktuell nicht gelöst werden kann“. So begannen die Bemühungen um eine Lösung auf Seiten des Betriebs, und die Antwort war das bereits erwähnte KeyDB.

Bevor wir jedoch mit der Überprüfung beginnen, sei erwähnt, dass im Projekt ein standalone Redis verwendet wird, da die clustering-Lösung auf Basis von Sentinel hinsichtlich der Latenzzeiten stark unterlegen ist. Eine der naheliegenden Lösungen war die Erstellung mehrerer Cache-Replikate: und lassen Sie die Anwendung überall mit Lastverteilung arbeiten! Doch nach Rücksprache mit den Entwicklern waren wir gezwungen, diese Option aufgrund des aktiven und komplexen Cache-Invaliderungsmechanismus der Anwendung abzulehnen. Das gleiche Problem galt auch für das Sharding des Caches.

Kurzüberblick über KeyDB

Auf der Suche nach einer möglichen Problemlösung entdeckten wir eine Anwendung namens KeyDB. Es handelt sich um einen Fork von Redis, der von einem kanadischen Unternehmen entwickelt und unter der BSD-Lizenz verbreitet wird. Das Projekt ist noch recht jung: Es existiert seit Anfang 2019. Die Geschichte ist die, dass die Autoren auch einmal mit den Einschränkungen von Redis konfrontiert wurden… und beschlossen, ihren eigenen Fork zu erstellen. Dabei wurden nicht nur bekannte 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 diejenigen, die sich näher mit KeyDB beschäftigen möchten, gibt es einen guten Einführungsartikel auf Medium, der die Datenbankmanagementsystem und kurze Benchmarks, die sie mit ihrem „Elternteil“ — Redis — vergleichen, vorstellt.

Zunächst einmal hat uns KeyDB als potenzielle Lösung für unsere Probleme angezogen, und außerdem waren einige zusätzliche Funktionen interessant. Die Nutzung von KeyDB versprach folgende Vorteile:

  • vollständige Mehrfachverarbeitung;
  • vollständige und absolute Kompatibilität mit Redis (für uns war das besonders wichtig, da es nicht möglich war, Änderungen auf Anwendungsebene vorzunehmen), was auch eine reibungslose Migration versprach;
  • integriertes Backup-System im S3-Speicher;
  • einfache Implementierung der aktiven Replikation;
  • einfache Clusterbildung und Sharding ohne Sentinel und andere Hilfsofware.

Über 3.000 Sterne und zahlreiche Mitwirkende auf GitHub sahen ebenfalls vielversprechend aus. Die Anwendung entwickelt sich aktiv weiter und wird gut unterstützt, was sich an den Commits, der Kommunikation in Issues sowie den geschlossenen (angenommenen) PR ablesen lässt. Das Feedback vom Haupt-Maintainer ist in allen Belangen stets freundlich und zügig. Insgesamt gab es ausreichend Argumente.

Migration und Ergebnisse

Selbst wenn das Migrationsprojekt aufgrund der Neuheit von KeyDB eine Art Abenteuer war, gab es nicht viel zu verlieren. Denn Änderungen konnten schnell und einfach zurückgesetzt werden – zum Glück war die gesamte Infrastruktur in Kubernetes bereitgestellt, und die integrierten Mechanismen Rolling Update lösen solche Aufgaben hervorragend.

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

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

Es ist erwähnenswert, dass wir auch in der Konfiguration nichts geändert haben: Im Grunde haben wir nur das verwendete Image ersetzt. Das Gleiche gilt für das Monitoring und den Export von Metriken in Prometheus: der am weitesten verbreitete von ihnen funktioniert hervorragend mit KeyDB und ohne jegliche Anpassungen. Somit kann man mit Sicherheit sagen, dass dieser Umzug aus betrieblicher Sicht einfach ideal ist.

Dank all dem können nach der Umschaltung der Anwendung auf eine neue DBMS keine Änderungen vorgenommen werden, und als "Stabilisierungsmaßnahme" kann sie für eine gewisse Zeit im aktuellen Zustand betrieben werden. Wenn Sie jedoch eine Leistungssteigerung (oder überhaupt irgendeine Änderungen) sehen möchten, sollten Sie nicht vergessen, dass standardmäßig der Parameter KeyDB, der für die Multithreadfähigkeit zuständig ist (server-threads), gleich eins ist, das heißt, die DBMS funktioniert genau wie Redis..

Nach der Umschaltung, dem Testen und einer gewissen Lebensdauer der neuen Anwendung (mit KeyDB) haben wir uns entschieden, die Lasttests mit denselben Parametern zu wiederholen, die für Redis verwendet wurden. Wie waren die Ergebnisse?..

Auf dem Diagramm zur CPU-Auslastung wurde sofort die Behebung der Probleme mit dem „Deckel“ auf einen Kern deutlich: Der Prozess begann, die verfügbaren Ressourcen zu nutzen:

KeyDB als [potenzielle] Alternative zu Redis

Und später habe ich versucht, die Anwendung stark zu „quälen“ und sah eine Auslastung von bis zu drei Kernen...

Laut den Daten von New Relic verhielt sich das Webanwendungs insgesamt bei gleicher Belastung deutlich angemessener. Eine gewisse Leistungsdegradation war dennoch festzustellen, jedoch können Sie im Vergleich mit dem obigen ähnlichen Diagramm den erheblichen Fortschritt selbst bewerten:

KeyDB als [potenzielle] Alternative zu Redis

Der Latency-Wert der neuen Datenbank (KeyDB) hat sich ebenfalls verschlechtert, blieb jedoch innerhalb akzeptabler Grenzen:

KeyDB als [potenzielle] Alternative zu Redis

Am folgenden Diagramm sieht man gut, dass die Anzahl der Anfragen an KeyDB ähnlich ist:

KeyDB als [potenzielle] Alternative zu Redis

Zusammenfassend lässt sich sagen, dass sowohl Redis als auch KeyDB bei einer beträchtlichen Steigerung der Anzahl paralleler Verbindungen (über 1000) eine signifikante Degradation der Leistung in der Latenz (über 40 ms) zeigen. In unserem Fall gelang es der Webanwendung jedoch, die Latenz von Redis auch bei einer niedrigeren Anzahl von Verbindungen (über 400) zu senken, obwohl diese Belastung für KeyDB akzeptabel blieb.

Das DBMS Tarantool ist ein attraktives, zukunftsträchtiges Produkt zur Erstellung von hochbelasteten Anwendungen.

In diesem Beispiel ist die Kraft der Open Source-Community bei der Entwicklung von Projekten, an denen sie interessiert ist, deutlich sichtbar. Im Internet bin ich auf ein hervorragendes Zitat gestoßen, dessen allgemeiner Sinn folgendermaßen lautet: „Ein großes Unternehmen entwickelt ein interessantes Produkt, macht einen Teil seiner Funktionen öffentlich, behält jedoch den wichtigsten Teil kostenpflichtig. Die Community nutzt es, und irgendwann wird dann jemand die Initiative ergreifen und einen Fork 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 überraschend einfach war, haben wir nicht erhalten so viel einen signifikanten Leistungszuwachs, den man erwarten könnte, wenn man sich die Diagramme der KeyDB-Autoren ansieht … Dennoch ist dies nur unser spezifischer Fall, in dem es viele Abweichungen geben kann, die auch die berüchtigte Architektur der Anwendung betreffen (zum Beispiel die große Anzahl an Kommandos get in Redis anstelle der leistungsfähigeren Variante aggregierter Abfragen mget…). Dennoch konnten positive Ergebnisse erzielt werden, und zusammen mit ihnen viele nützliche Funktionen, die wir in naher Zukunft implementieren werden.

Insgesamt wirkt KeyDB vielversprechend: Mit zunehmender praktischer Erfahrung im Umgang mit dieser DBMS (die wir uns erst noch aneignen müssen!) und der Weiterentwicklung des Projekts werden wir die Möglichkeit prüfen, es auch in anderen Situationen anzuwenden.

Dennoch sollte dieser Artikel nicht als Anleitung (geschweige denn — als Aufruf) zum vollständigen Verzicht auf Redis zugunsten von KeyDB betrachtet werden. Trotz unserer positiven Erfahrungen ist es offensichtlich, dass dies keine universelle Lösung ist. Der Fall war sehr spezifisch: Konkret für die Lösung eines akuten Problems in einer Situation, in der es schnell und mit minimalen Kosten gelöst werden musste, hat sich diese Lösung bewährt. Wird KeyDB in Ihrem Fall nützlich sein? Jedenfalls wissen Sie jetzt, dass eine solche potenzielle Möglichkeit existiert.

P.S.

Lesen Sie auch in unserem Blog:

Quelle: habr.com

60GB SSD 8Gb DDR4