1. Warum Redis verwenden? Der Blogger glaubt, dass die Hauptüberlegungen für die Verwendung von Redis in Projekten Leistung und Parallelität sind. Natürlich verfügt Redis auch über andere Funktionen wie verteilte Sperren. Wenn es sich jedoch nur um andere Funktionen wie verteilte Sperren handelt, gibt es stattdessen andere Middleware (z. B. zookpeer usw.), und es ist nicht erforderlich, Redis zu verwenden. Daher wird diese Frage hauptsächlich aus zwei Perspektiven beantwortet: Leistung und Parallelität.
Antwort: Wie unten gezeigt, ist es in zwei Punkte unterteilt
(1) Leistung
Wenn Sie auf SQL stoßen, das eine lange Ausführungszeit erfordert und sich die Ergebnisse nicht häufig ändern, empfehlen wir, die Ergebnisse im zu speichern Cache. Auf diese Weise werden nachfolgende Anfragen aus dem Cache gelesen, sodass schnell auf Anfragen reagiert werden kann.
Exkurs: Ich möchte plötzlich über diesen Standard der schnellen Reaktion sprechen. Tatsächlich gibt es je nach Interaktionseffekt keinen festen Standard für diese Reaktionszeit. Aber jemand hat mir einmal gesagt: „In einer idealen Welt müssen unsere Seitensprünge in einem Augenblick gelöst werden, und In-Page-Vorgänge müssen in einem Augenblick gelöst werden. Um die beste Benutzererfahrung zu bieten, müssen Vorgänge, die mehr als dauern.“ Eine Sekunde sollte bereitgestellt werden. Fortschrittsanzeigen ermöglichen jederzeit eine Unterbrechung oder einen Abbruch. „Wie lang ist also ein Augenblick, ein Moment oder ein Fingerschnippen?
Laut den „Maha Sangha Vinaya“-AufzeichnungenEin Moment ist ein Gedanke, zwanzig Gedanken sind ein Moment, zwanzig Momente sind eine Fingerbewegung, zwanzig Fingerbewegungen sind ein Luo Su, zwanzig Luo Su sind ein Moment , ein Tag und eine Nacht. Es sind dreißig Momente. Nach sorgfältiger Berechnung ist ein Augenblick also 0,36 Sekunden, ein Augenblick 0,018 Sekunden und ein Fingerschnippen 7,2 Sekunden lang.(2) Parallelität
Wie in der folgenden Abbildung gezeigt, greifen bei großer Parallelität alle Anforderungen direkt auf die Datenbank zu und die Datenbank weist eine Verbindungsausnahme auf. In diesem Fall ist die Verwendung von Redis-Puffervorgängen erforderlich, damit die Anforderung zuerst auf Redis zugreift, anstatt direkt auf die Datenbank zuzugreifen.2. Was sind die Nachteile der Verwendung von Redis? Analyse: Grundsätzlich muss man verstehen, dass bei der Verwendung von Redis einige Probleme auftreten nur ein paar gängige. Antwort: Hauptsächlich vier Fragen Wettbewerbsproblem
Diese vier Probleme kommen meiner Meinung nach in Projekten relativ häufig vor. Die konkreten Lösungen werden später angegeben.
Sie können sich auf Folgendes beziehen: „Cache-Lawine, Cache-Penetration, Cache-Aufwärmen, Cache-Aktualisierung, Cache-Downgrade und andere Probleme!“ 》
3. Warum ist Single-Threaded Redis so schnell?Analyse: Diese Frage ist eigentlich eine Untersuchung des internen Mechanismus von Redis. Laut der Interviewerfahrung des Bloggers verstehen viele Menschen das Single-Threaded-Arbeitsmodell von Redis tatsächlich nicht. Daher sollte dieses Problem noch überprüft werden.
Antwort: Hauptsächlich die folgenden drei Punkte
(1) Reiner Speicherbetrieb(2) Single-Thread-Betrieb, Vermeidung häufiger Kontextwechsel
(3) Verwendung eines nicht blockierenden E/A-Multiplexing-Mechanismus Exkurs : Wir wollen nun ausführlich über den I/O-Multiplexing-Mechanismus sprechen, da dieser Begriff so beliebt ist, dass die meisten Menschen nicht verstehen, was er bedeutet. Der Blogger nannte eine Analogie: Xiaoqu eröffnete einen Expressladen in City S, der für Expresslieferdienste in der Stadt verantwortlich ist. Aufgrund begrenzter Mittel beauftragte Xiaoqu zunächst eine Gruppe von Kurieren, stellte jedoch später fest, dass die Mittel nicht ausreichten und er nur ein Auto für die Expresszustellung kaufen konnte.
Geschäftsmethode 1Immer wenn ein Kunde einen Kurier ausliefert, beauftragt Xiaoqu einen Kurier, die Sache im Auge zu behalten, und dann fährt der Kurier los, um den Kurier auszuliefern. Langsam entdeckte Xiaoqu die folgenden Probleme mit dieser Geschäftsmethode: Dutzende Kuriere verbrachten im Grunde ihre Zeit damit, sich Autos zu schnappen. Die meisten Kuriere waren untätig, jeder kann Expresslieferungen liefern Lieferung, es gibt immer mehr Kuriere. Xiaoqu stellte fest, dass der Express-Lieferladen immer überfüllter wird und es keine Möglichkeit gibt, neue Kuriere einzustellen. Unter den Kurieren nimmt die Koordination zwischen Unternehmen viel Zeit in Anspruch Basierend auf den oben genannten Mängeln hat Xiaoqu aus der Erfahrung gelernt und die folgende Geschäftsmethode vorgeschlagen:
Geschäftsmethode zwei
Xiaoqu stellt nur einen Kurier ein. Xiaoqu markiert die vom Kunden gesendete Expresslieferung entsprechend dem Lieferort und platziert sie an derselben Stelle. Am Ende holte der Kurier die Pakete einzeln ab, fuhr dann zur Lieferung des Pakets und kam nach der Lieferung zurück, um das nächste Paket abzuholen.
Vergleich
Ist beim Vergleich der beiden oben genannten Geschäftsmethoden offensichtlich, dass die zweite effizienter und besser ist? In der obigen Metapher: Jeder Kurier -----> Jeder ThreadJeder Kurier ------- ---- --------->Jeder Socket (E/A-Stream)
Kunden-Expresszustellungsanfrage-------------->Anfrage des Kunden
Xiaoqus Geschäftsmethode-------------> ;Code Läuft auf dem Server
Ein Auto -------->Anzahl der CPU-Kerne
Wir haben also die folgende Schlussfolgerung
1. Die erste Geschäftsmethode ist das traditionelle Parallelitätsmodell. Jeder E/A-Stream (Express) wird von einem neuen Thread (Courier) verwaltet.
2. Die zweite Verwaltungsmethode ist I/O-Multiplexing. Es gibt nur einen einzigen Thread (einen Kurier), der mehrere I/O-Streams verwaltet, indem er den Status jedes I/O-Streams (den Lieferort jedes Kuriers) verfolgt.
Das Folgende ist eine Analogie zum echten Redis-Thread-Modell, wie im Bild gezeigt
Beziehen Sie sich auf das Bild oben, in einfachen Worten ist es so. Während des Betriebs erstellt unser Redis-Client Sockets mit verschiedenen Ereignistypen. Auf der Serverseite gibt es ein I/0-Multiplexing-Programm, das es in eine Warteschlange stellt. Anschließend entnimmt der Dateiereignis-Dispatcher die Datei der Reihe nach aus der Warteschlange und leitet sie an verschiedene Ereignisprozessoren weiter.
Es ist zu beachten, dass Redis für diesen E/A-Multiplexing-Mechanismus auch Multiplexing-Funktionsbibliotheken wie select, epoll, evport, kqueue usw. bereitstellt. Sie können sich selbst darüber informieren.
4. Redis-Datentypen und Nutzungsszenarien für jeden Datentyp
Analyse: Halten Sie diese Frage für sehr grundlegend? Laut Interviewerfahrung können jedoch mindestens 80 % der Menschen diese Frage nicht beantworten. Es wird empfohlen, dass Sie es nach der Verwendung im Projekt analog auswendig lernen können, um eine tiefere Erfahrung zu sammeln, anstatt es auswendig zu lernen. Grundsätzlich wird ein qualifizierter Programmierer alle fünf Typen verwenden.
Antwort: Es gibt insgesamt fünf Typen
(1) String
Dies ist tatsächlich sehr häufig und umfasst die grundlegendsten Get/Set-Operationen. Der Wert kann eine Zeichenfolge oder eine Zahl sein. Im Allgemeinen werden einige komplexe Zählfunktionen zwischengespeichert.
(2) Hash
Der Wert hier speichert ein strukturiertes Objekt, und es ist bequemer, ein bestimmtes Feld darin zu bedienen. Wenn Blogger eine einmalige Anmeldung durchführen, verwenden sie diese Datenstruktur zum Speichern von Benutzerinformationen, verwenden cookieId als Schlüssel und legen 30 Minuten als Cache-Ablaufzeit fest, wodurch ein sitzungsähnlicher Effekt sehr gut simuliert werden kann.
(3) list
Mit der Datenstruktur von List können Sie einfache Nachrichtenwarteschlangenfunktionen ausführen. Darüber hinaus können wir auch den Befehl lrange verwenden, um die Redis-basierte Paging-Funktion zu implementieren. Diese Methode bietet eine hervorragende Leistung und Benutzererfahrung.
(4)set
Weil set eine Sammlung eindeutiger Werte ist. Daher kann die globale Deduplizierungsfunktion implementiert werden. Warum nicht das mit der JVM gelieferte Set für die Deduplizierung verwenden? Da unsere Systeme im Allgemeinen in Clustern bereitgestellt werden, ist es mühsam, das mit der JVM gelieferte Set zu verwenden. Ist es zu mühsam, einen öffentlichen Dienst nur für die globale Deduplizierung einzurichten?
Darüber hinaus können Sie durch die Verwendung von Operationen wie Schnittmenge, Vereinigung und Differenz allgemeine Präferenzen, alle Präferenzen, Ihre eigenen einzigartigen Präferenzen und andere Funktionen berechnen.
(5) sortierter Satz
sortierter Satz verfügt über eine zusätzliche Gewichtsparameterbewertung, und die Elemente im Satz können entsprechend der Bewertung angeordnet werden. Sie können einen Ranking-Antrag stellen und TOP N-Operationen durchführen. Darüber hinaus wird in einem Artikel mit dem Titel „Analysis of Distributed Delayed Task Schemes“ erwähnt, dass sortierte Sätze zur Implementierung verzögerter Aufgaben verwendet werden können. Die letzte Anwendung besteht darin, Bereichssuchen durchzuführen.
5. Redis-Ablaufstrategie und Speichereliminierungsmechanismus
Die Bedeutung dieses Problems ist offensichtlich und es ist ersichtlich, ob Redis verwendet wird. Wenn Sie beispielsweise nur 5 GB Daten in Redis speichern können, Sie aber 10 GB Daten schreiben, werden 5 GB der Daten gelöscht. Wie haben Sie es gelöscht? Haben Sie über dieses Problem nachgedacht? Außerdem ist für Ihre Daten eine Ablaufzeit festgelegt, aber wenn die Zeit abgelaufen ist, ist die Speichernutzung immer noch relativ hoch.
Antwort:
Redis verwendet eine Strategie für regelmäßiges Löschen und verzögertes Löschen.
Warum nicht eine geplante Löschstrategie verwenden?
Geplantes Löschen, einen Timer verwenden, um den Schlüssel zu überwachen und ihn automatisch zu löschen, wenn er abläuft. Obwohl der Speicher rechtzeitig freigegeben wird, verbraucht er viele CPU-Ressourcen. Da sich die CPU bei vielen gleichzeitigen Anforderungen auf die Anforderungsverarbeitung und nicht auf Schlüsselwert-Löschvorgänge konzentrieren muss, haben wir die Übernahme dieser Strategie aufgegeben 100 ms, um zu sehen, ob ein abgelaufener Schlüssel vorhanden ist. Wenn es einen abgelaufenen Schlüssel gibt, löschen Sie ihn. Es ist zu beachten, dass Redis nicht alle 100 ms alle Schlüssel überprüft, sondern sie zufällig auswählt und überprüft (wenn alle Schlüssel alle 100 ms überprüft werden, bleibt Redis dann nicht hängen)? Wenn Sie nur eine periodische Löschstrategie verwenden, werden viele Schlüssel nach Ablauf der Ablaufzeit nicht gelöscht.
Daher ist das verzögerte Löschen praktisch. Das heißt, wenn Sie einen Schlüssel erhalten, prüft Redis, ob der Schlüssel abgelaufen ist. Wenn eine Ablaufzeit festgelegt ist? Wenn es abläuft, wird es zu diesem Zeitpunkt gelöscht. Gibt es kein anderes Problem, wenn wir reguläres Löschen + verzögertes Löschen übernehmen?
Nein, wenn der Schlüssel beim regulären Löschen nicht gelöscht wird. Dann haben Sie den Schlüssel nicht sofort angefordert, was bedeutet, dass die verzögerte Löschung nicht wirksam wurde. Auf diese Weise wird die Erinnerung an Redis immer höher. Dann sollte der Speicherbeseitigungsmechanismus übernommen werden.
Es gibt eine Konfigurationszeile in redis.conf
# maxmemory-policy volatile-lru
Diese Konfiguration ist mit der Speichereliminierungsstrategie konfiguriert (was, Sie haben sie nicht konfiguriert? Denken Sie über sich selbst nach)
1) noeviction: Wenn im Speicher nicht genügend Speicherplatz für die neu geschriebenen Daten vorhanden ist, meldet der neue Schreibvorgang einen Fehler. Niemand sollte es benutzen.
Wenn der Speicherplatz nicht ausreicht, um neue Daten zu speichern, entfernt der allkeys-lru-Algorithmus den zuletzt verwendeten Schlüssel aus dem Schlüsselraum. Empfohlen, wird derzeit in Projekten verwendet.
3) allkeys-random: Wenn der Speicher nicht ausreicht, um die neu geschriebenen Daten aufzunehmen, wird ein Schlüssel zufällig aus dem Schlüsselraum entfernt. Niemand sollte ihn verwenden. Wenn Sie ihn nicht löschen möchten, verwenden Sie zumindest den Schlüssel und löschen Sie ihn nach dem Zufallsprinzip.
4) volatile-lru: Wenn der Speicher nicht ausreicht, um neu geschriebene Daten aufzunehmen, entfernen Sie im Schlüsselbereich mit festgelegter Ablaufzeit den zuletzt verwendeten Schlüssel. Im Allgemeinen wird diese Methode nur verwendet, wenn Redis sowohl als Cache als auch als persistenter Speicher verwendet wird. Nicht empfohlen
5) flüchtig-zufällig: Wenn der Speicher nicht ausreicht, um neu geschriebene Daten aufzunehmen, wird ein Schlüssel zufällig mit einer festgelegten Ablaufzeit aus dem Schlüsselraum entfernt. Immer noch nicht empfohlen
6) volatile-ttl: Wenn der Speicher nicht ausreicht, um neu geschriebene Daten aufzunehmen, werden im Schlüsselraum mit festgelegter Ablaufzeit zuerst Schlüssel mit einer früheren Ablaufzeit entfernt. Nicht empfohlen
ps: Wenn der Ablaufschlüssel nicht festgelegt ist und die Voraussetzungen nicht erfüllt sind, ist das Verhalten der Strategien volatile-lru, volatile-random und volatile-ttl im Grunde dasselbe wie noeviction (kein Löschen).
6. Konsistenzprobleme bei Redis und Datenbanken
In verteilten Systemen sind Konsistenzprobleme häufige Probleme. Dieses Problem kann weiter in letztendliche Konsistenz und starke Konsistenz unterschieden werden. Wenn Datenbank und Cache doppelt geschrieben werden, kommt es zwangsläufig zu Inkonsistenzen. Um diese Frage zu beantworten, müssen Sie zunächst eine Prämisse verstehen. Das heißt, wenn strenge Konsistenzanforderungen für die Daten bestehen, können diese nicht zwischengespeichert werden. Alles, was wir tun, kann nur letztendliche Konsistenz garantieren. Die von uns vorgeschlagene Lösung kann die Wahrscheinlichkeit inkonsistenter Ereignisse tatsächlich nur verringern, sie jedoch nicht vollständig beseitigen. Daher können Daten mit hohen Konsistenzanforderungen nicht zwischengespeichert werden.
Hier finden Sie eine kurze Einführung in die detaillierte Analyse im Artikel „Analyse des Double-Write-Konsistenzschemas für verteilte Datenbanken und Caches“. Übernehmen Sie zunächst eine korrekte Aktualisierungsstrategie, aktualisieren Sie zuerst die Datenbank und löschen Sie dann den Cache. Stellen Sie eine Sicherungsmaßnahme bereit, z. B. die Verwendung einer Nachrichtenwarteschlange, für den Fall, dass das Löschen des Caches fehlschlägt.
7. Wie man mit Cache-Penetrations- und Cache-Lawinenproblemen umgeht
Um ehrlich zu sein, stoßen kleine und mittlere traditionelle Softwareunternehmen selten auf diese beiden Probleme. Wenn es große gleichzeitige Projekte gibt, wird der Datenverkehr etwa Millionen betragen. Diese beiden Themen müssen eingehend geprüft werden.
Antwort: Wie unten gezeigt
Cache-Penetration, das heißt, der Hacker fordert absichtlich Daten an, die nicht im Cache vorhanden sind, was dazu führt, dass alle Anforderungen an die Datenbank gesendet werden, was zu einer abnormalen Datenbankverbindung führt.
Lösung:
Wenn der Cache ausfällt, verwenden Sie eine Mutex-Sperre, erwerben Sie zuerst die Sperre und fordern Sie dann die Datenbank an, sobald die Sperre erworben wurde. Wenn die Sperre nicht erhalten wird, wird sie für einen bestimmten Zeitraum in den Ruhezustand versetzt und erneut versucht.
(2) Übernehmen Sie eine asynchrone Aktualisierungsstrategie und kehren Sie direkt zurück, unabhängig davon, ob der Schlüssel einen Wert hat. Speichern Sie eine Cache-Ablaufzeit im Wert value. Sobald der Cache abläuft, wird asynchron ein Thread gestartet, um die Datenbank zu lesen und den Cache zu aktualisieren. Der Cache-Vorwärmvorgang (Laden des Caches vor dem Starten des Projekts) ist erforderlich.
Stellen Sie einen Abfangmechanismus bereit, der schnell feststellen kann, ob die Anfrage gültig ist. Verwenden Sie beispielsweise Bloom-Filter, um intern eine Reihe legaler und gültiger Schlüssel zu verwalten. Stellen Sie schnell fest, ob der in der Anfrage enthaltene Schlüssel legal und gültig ist. Wenn es illegal ist, kehren Sie direkt zurück.
Cache-Lawine, das heißt, der Cache fällt gleichzeitig in einem großen Bereich aus. Zu diesem Zeitpunkt kommt es zu einer weiteren Anforderungswelle, und infolgedessen werden alle Anforderungen an die Datenbank gesendet, was zu Ausnahmen bei der Datenbankverbindung führt.
Lösung:
(1) Fügen Sie einen zufälligen Wert zur Cache-Ablaufzeit hinzu, um kollektive Fehler zu vermeiden.
(2) Verwenden Sie eine Mutex-Sperre, aber der Durchsatz dieser Lösung sinkt erheblich.
(3) Doppelter Cache. Wir haben zwei Caches, Cache A und Cache B. Die Ablaufzeit von Cache A beträgt 20 Minuten, für Cache B gibt es keine Ablaufzeit. Führen Sie den Cache-Aufwärmvorgang selbst durch. Teilen Sie dann die folgenden Punkte auf:
Ich lese die Datenbank aus Cache A und kehre direkt zurück, wenn welche vorhanden sind.
II A hat keine Daten, lese Daten direkt aus B, kehre direkt zurück und starte asynchron einen Aktualisierungsthread .
III Der Update-Thread aktualisiert Cache A und Cache B gleichzeitig.
8. So lösen Sie das Problem des gleichzeitigen Schlüsselwettbewerbs in Redis
Analyse: Dieses Problem besteht grob darin, dass mehrere Subsysteme gleichzeitig einen Schlüssel festlegen. Worauf sollten wir zu diesem Zeitpunkt achten? Haben Sie jemals darüber nachgedacht? Nachdem der Blogger vorab die Baidu-Suchergebnisse überprüft hatte, stellte er fest, dass in fast allen Antworten die Verwendung des Redis-Transaktionsmechanismus empfohlen wurde. Der Blogger rät von der Verwendung des Redis-Transaktionsmechanismus ab. Da unsere Produktionsumgebung im Grunde eine Redis-Cluster-Umgebung ist, werden Daten-Sharding-Vorgänge durchgeführt. Wenn eine einzelne Aufgabe mehrere Schlüsselvorgänge umfasst, werden diese Schlüssel nicht unbedingt auf demselben Redis-Server gespeichert. Daher ist der Transaktionsmechanismus von Redis sehr nutzlos.
Antwort: Wie unten gezeigt
(1) Wenn Sie diesen Schlüssel betätigen, ist die Reihenfolge nicht erforderlich
In diesem Fall bereiten Sie ein verteiltes Schloss vor, jeder greift nach dem Schloss und führt nach dem Greifen einfach den eingestellten Vorgang aus das Schloss, relativ einfach.
(2) Wenn Sie diese Taste betätigen, ist die Reihenfolge erforderlich
Angenommen, es gibt einen Schlüssel1, System A muss Schlüssel1 auf WertA setzen, System B muss Schlüssel1 auf WertB setzen, System C muss Schlüssel1 auf WertC setzen.
Erwartung Entsprechend dem Wert von Schlüssel1 ändert er sich in der Reihenfolge von WertA-->WertB-->WertC. Zu diesem Zeitpunkt müssen wir beim Schreiben von Daten in die Datenbank einen Zeitstempel speichern. Nehmen Sie an, dass der Zeitstempel wie folgt lautet:
System A-Taste 1 {WertA 3:00}
System B-Taste 1 {WertB 3:05}
System C-Taste 1 {WertC 3:10}
Stellen Sie sich vor, System B erhält Bei der ersten Sperre wird der Wert von key1 auf {valueB 3:05} gesetzt. Wenn System A die Sperre erhält und feststellt, dass der Zeitstempel von valueA, den es speichert, früher ist als der im Cache gespeicherte Zeitstempel, führt System A den Set-Vorgang nicht aus. Und so weiter.
Andere Methoden, wie die Verwendung einer Warteschlange und die Umwandlung der Set-Methode in seriellen Zugriff, können ebenfalls verwendet werden. Kurz gesagt: Seien Sie flexibel.
Das obige ist der detaillierte Inhalt vonWas sind die acht klassischen Probleme von Redis?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!