Dieser Artikel vermittelt Ihnen relevantes Wissen über Redis. Er stellt hauptsächlich die Implementierung des LRU-Cache-Eliminierungsalgorithmus vor, einschließlich der Implementierung des ungefähren LRU-Algorithmus von Redis, der tatsächlichen Ausführung des ungefähren LRU-Algorithmus usw. Ich hoffe, dass dies der Fall ist sei für alle hilfreich.
Empfohlenes Lernen: Redis-Lerntutorial
LRU, Least Latest Used (Least Latest Used, LRU), klassischer Cache-Algorithmus.
LRU verwendet eine verknüpfte Liste, um den Zugriffsstatus aller Daten im Cache aufrechtzuerhalten, passt die Position der Daten in der verknüpften Liste basierend auf dem Echtzeitzugriff auf die Daten an und verwendet dann die Position der Daten in der verknüpften Liste, um anzugeben, ob auf die Daten kürzlich zugegriffen wurde oder nicht.
LRU setzt den Kopf und das Ende der Kette auf das MRU-Ende bzw. das LRU-Ende:
case2
: Wenn auf die Daten gerade einmal zugegriffen wurde, verschiebt LRU die Daten von ihrer aktuellen Position in der verknüpften Liste an den Anfang die Kette. Verschieben Sie alle anderen Daten vom Kopf der verknüpften Liste an ihre aktuelle Position ein Bit in Richtung Ende.Zusätzlicher Speicherplatz zum Speichern der verknüpften Liste
Beim Zugriff auf Daten Redis wird durch den Overhead der Datenverschiebung und verknüpfter Listenoperationen beeinträchtigt
Ob es darum geht, Speicher zu sparen oder die hohe Leistung von Redis aufrechtzuerhalten, Redis wird nicht streng nach den Grundprinzipien von LRU implementiert, sondern
bietet eine ungefähre LRU-Algorithmus-Implementierung.
Wie ermöglicht der Speichereliminierungsmechanismus von Redis den ungefähren LRU-Algorithmus? Die folgenden Konfigurationsparameter in redis.conf:
maxmemory
, um die Speichereliminierungsstrategie des Redis-Servers festzulegen, einschließlich ungefährer LRU, LFU, Eliminierung nach TTL-Wert und zufälliger Eliminierung usw.
Also, Sobald die Option maxmemory festgelegt ist und maxmemory-policy als allkeys-lru oder volatile-lru konfiguriert ist, ist ungefähr LRU aktiviert. Sowohl allkeys-lru als auch volatile-lru verwenden ungefähre LRU, um Daten zu eliminieren. Der Unterschied ist:
volatile-lru filtert in KV-Paaren mit eingestellter TTL wird eliminiert
Wie implementiert Redis den ungefähren LRU-Algorithmus?
So berechnen Sie den globalen LRU-Uhrwert, um die Aktualität des Datenzugriffs zu beurteilen
Schlüsselwertinitialisierung und Aktualisierung des LRU-Uhrwerts
Was in der Funktion, Der LRU-Uhrwert, der jedem Schlüssel-Wert-Paar entspricht, wird initialisiert und aktualisiert. Die tatsächliche Ausführung des ungefähren LRU-Algorithmus Tatsächlicher Eliminierungsmechanismus Zur Implementierung
2.1 Berechnung des globalen LRU-TaktwertsDer ungefähre LRU-Algorithmus muss weiterhin die Zugriffsaktualität verschiedener Daten unterscheiden, dh Redis muss die neueste Zugriffszeit der Daten kennen. Daher zeichnet die LRU-Uhr den Zeitstempel jedes Zugriffs auf Daten auf.
Redis verwendet eine redisObject-Struktur, um den Zeiger auf V für V in jedem KV-Paar zu speichern. Zusätzlich zum Zeiger, der den Wert aufzeichnet, verwendet redisObject auch 24 Bit, um die LRU-Taktinformationen zu speichern, die der LRU-Mitgliedsvariablen entsprechen. Auf diese Weise zeichnet jedes KV-Paar den Zeitstempel seines letzten Zugriffs in der lru-Variablen auf.
Wie wird der LRU-Taktwert jedes KV-Paares berechnet? Redis Server verwendet eine globale LRU-Uhr auf Instanzebene, und die LRU-Zeit jedes KV-Paares wird entsprechend der globalen LRU-Uhr eingestellt.
Diese globale LRU-Uhr wird in der Mitgliedsvariablen des globalen Redis-Variablenservers gespeichert lruclock:
Daher muss man beachten, dass wenn der Zeitabstand zwischen zwei Zugriffen auf ein Datenstück
Die Funktion getLRUClock dividiert den von LRU_CLOCK_RESOLUTION erhaltenen UNIX-Zeitstempel, um den mit der LRU-Uhrgenauigkeit berechneten UNIX-Zeitstempel zu erhalten, der den aktuellen LRU-Uhrwert darstellt.
getLRUClock führt eine UND-Verknüpfung zwischen dem LRU-Uhrwert und der Makrodefinition LRU_CLOCK_MAX (dem Maximalwert, den die LRU-Uhr darstellen kann) durch.
Standardmäßig ist der globale LRU-Uhrwert ein UNIX-Zeitstempel, der mit einer Genauigkeit von 1 Sekunde berechnet und in initServerConfig initialisiert wird.
Wie wird der globale LRU-Uhrwert aktualisiert, wenn Redis Server ausgeführt wird? Es bezieht sich auf serverCron, das dem regelmäßig laufenden Zeitereignis von Redis Server im ereignisgesteuerten Framework entspricht.
serverCron wird als Rückruffunktion für Zeitereignisse regelmäßig ausgeführt. Sein Häufigkeitswert wird durch das hz-Konfigurationselement
in redis.conf bestimmt. Der Standardwert ist 10, d. h. die serverCron-Funktion wird alle 100 ms ausgeführt (1s/10 = 100ms). In serverCron wird der Wert der globalen LRU-Uhr regelmäßig entsprechend der Ausführungshäufigkeit dieser Funktion durch Aufrufen von getLRUClock aktualisiert:Auf diese Weise kann jedes KV-Paar den neuesten Zugriffszeitstempel von der globalen LRU-Uhr erhalten. In welchen Funktionen wird für jedes KV-Paar die entsprechende redisObject.lru initialisiert und aktualisiert?
2.2 Initialisierung und Aktualisierung des LRU-Uhrwerts des Schlüssel-Wert-Paares
Für ein KV-Paar wird der LRU-Uhrwert zunächst festgelegt, wenn das KV-Paar erstellt wird. Dieser Initialisierungsvorgang wird in der Funktion „createObject“ aufgerufen wird aufgerufen, wenn Redis ein KV-Paar erstellen möchte. Zusätzlich zur Zuweisung von Speicherplatz für redisObject initialisiert createObject auch redisObject.lru gemäß der maxmemory_policy-Konfiguration.maxmemory_policy≠LFU gesetzt, dann ruft createObject LRU_CLOCK auf, um den LRU-Wert festzulegen, der dem LRU-Uhrwert entspricht KV-Paar.
LRU_CLOCK gibt den aktuellen globalen LRU-Uhrwert zurück. Denn sobald ein KV-Paar erstellt wurde, entspricht es einem Zugriff und sein entsprechender LRU-Uhrwert stellt seinen Zugriffszeitstempel dar:lookupKey sucht in der globalen Hash-Tabelle nach dem KV-Paar, auf das zugegriffen werden soll. Wenn das KV-Paar vorhanden ist, aktualisiert lookupKey den LRU-Uhrwert des Schlüssel-Wert-Paares, der dessen Zugriffszeitstempel ist, basierend auf dem Konfigurationswert von maxmemory_policy.
Wenn maxmemory_policy nicht als LFU-Richtlinie konfiguriert ist, ruft die Funktion „lookupKey“ die Funktion „LRU_CLOCK“ auf, um den aktuellen globalen LRU-Uhrwert abzurufen und ihn der LRU-Variablen in der redisObject-Struktur des Schlüssel-Wert-Paares zuzuweisen.
In Auf diese Weise kann jedes KV-Paar nach dem Zugriff den neuesten Zugriffszeitstempel erhalten. Aber Sie sind vielleicht neugierig: Wie werden diese Zugriffszeitstempel letztendlich verwendet, um den LRU-Algorithmus zur Dateneliminierung anzunähern? 2.3 Tatsächliche Ausführung des ungefähren LRU-Algorithmus
Der Grund, warum Redis ungefähres LRU implementiert, besteht darin, den Overhead an Speicherressourcen und Betriebszeit zu reduzieren.
2.3.1 Wann wird die Algorithmusausführung ausgelöst? Die Hauptlogik der ungefähren LRU liegt in performEvictions. performEvictions wird von evictionTimeProc aufgerufen, und die Funktion evictionTimeProc wird von ProcessCommand aufgerufen. processCommand, Redis ruft bei der Verarbeitung jedes Befehls auf:Sobald performEvictions aufgerufen wird und maxmemory-policy auf allkeys-lru oder volatile-lru gesetzt ist, wird die ungefähre LRU-Ausführung ausgelöst.
Die Ausführung kann in die folgenden Schritte unterteilt werden:
Wenn maxmemory nicht überschritten wird
, wird C_OK zurückgegeben und performEvictions wird ebenfalls direkt zurückgegeben.
Wenn getMaxmemoryState die aktuelle Speichernutzung auswertet und feststellt, dass der verwendete Speicher maxmemory überschreitet, berechnet es die Menge an Speicher, die freigegeben werden muss. Die Größe dieses freigegebenen Speichers = die Menge des verwendeten Speichers – maxmemory.
Aber die Menge des verwendeten Speichers beinhaltet nicht die für die Master-Slave-Replikation verwendete Kopierpuffergröße, die von getMaxmemoryState durch Aufruf von freeMemoryGetNotCountedMemory berechnet wird.Wenn die aktuell vom Server genutzte Speichermenge die Obergrenze von maxmemory überschreitet
, führt performEvictions eine While-Schleife aus, um Daten zu löschen und Speicher freizugeben.Für Eliminierungsdaten definiert Redis das Array EvictionPoolLRU, um die zu eliminierenden Kandidaten-KV-Paare zu speichern. Der Elementtyp ist die Struktur evictionPoolEntry, die die Leerlaufzeit, das entsprechende K und andere Informationen der zu eliminierenden KV-Paare speichert:
Wenn Redis Server zur Initialisierung initSever ausführt, ruft er evictionPoolAlloc auf, um Speicherplatz für das EvictionPoolLRU-Array zuzuweisen. Standardmäßig können 16 Kandidaten gespeichert werden KV-Paare scheiden aus.
PerformEvictions aktualisiert den Satz der zu eliminierenden Kandidaten-KV-Paare, das EvictionPoolLRU-Array, während des zyklischen Prozesses der Dateneliminierung.2.3.2.2 Aktualisieren Sie den Satz der zu eliminierenden Kandidaten-KV-Paare.
dictGetSomeKeys abgetastete Hash-Tabelle , durch Das Konfigurationselement maxmemory_policy bestimmt:
Die Anzahl der von dictGetSomeKeys abgetasteten K wird durch das Konfigurationselement „maxmemory-samples“ bestimmt. Der Standardwert ist 5:
Daher gibt dictGetSomeKeys den abgetasteten KV-Paarsatz zurück. evictionPoolPopulate führt eine Schleife basierend auf der tatsächlichen Anzahl der abgetasteten KV-Paare aus: Rufen Sie estimateObjectIdleTime auf, um die Leerlaufzeit jedes KV-Paars im Stichprobensatz zu berechnen:
Dann durchläuft evictionPoolPopulate den Satz der zu eliminierenden Kandidaten-KV-Paare. Das heißt, das EvictionPoolLRU-Array. Versuchen Sie, jedes abgetastete KV-Paar in das EvictionPoolLRU-Array einzufügen, abhängig von einer der folgenden Bedingungen:
kann einen leeren Steckplatz im Array finden, in den noch kein KV-Paar eingefügt wurde
Weil evictionPoolPopulate das EvictionPoolLRU-Array aktualisiert hat und die Ks im Array in der Leerlaufzeit von klein nach groß sortiert werden. Daher durchläuft performEvictions das EvictionPoolLRU-Array einmal und beginnt mit der Auswahl ab dem letzten K im Array. Wenn das ausgewählte K nicht leer ist, wird es als letztes K verwendet, das eliminiert wird.
Der ungefähre LRU-Algorithmus verwendet keine zeitaufwändige und platzraubende verknüpfte Liste, sondern einen zu eliminierenden Datensatz mit fester Größe und wählt zufällig einige K aus, die dem Datensatz hinzugefügt werden sollen jedes Mal eliminiert. Löschen Sie schließlich entsprechend der Länge der Leerlaufzeit von K in der zu eliminierenden Menge das K mit der längsten Leerlaufzeit.
Zusammenfassung
Die Speicherressourcen und die Leistung von Redis sind beide wichtig, daher implementiert Redis den ungefähren LRU-Algorithmus:
Stellen Sie zunächst dieEmpfohlenes Lernen:
Redis-TutorialDas obige ist der detaillierte Inhalt vonBeherrschen Sie die Implementierung des LRU-Cache-Eliminierungsalgorithmus von Redis vollständig. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!