Heim  >  Artikel  >  Datenbank  >  Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

青灯夜游
青灯夜游nach vorne
2021-10-15 11:15:012357Durchsuche

Dieser Artikel führt Sie in die relevanten Kenntnisse der Redis-Verteilung ein und führt Sie durch Master-Slave-Replikation, Sentinel und Clustering, um Ihr Redis-Level auf ein höheres Niveau zu heben!

Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

1. Master-Slave-Replikation

1. Einführung

Die Master-Slave-Replikation ist der Grundstein der Redis-Verteilung und die Garantie für die hohe Verfügbarkeit von Redis. In Redis wird der replizierte Server als Master-Server (Master) bezeichnet, und der Server, der den Master-Server repliziert, wird als Slave-Server (Slave) bezeichnet. [Verwandte Empfehlungen:

Redis-Video-Tutorial]

Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

Die Konfiguration der Master-Slave-Replikation ist sehr einfach. Es gibt drei Methoden (IP-Hauptserver-IP-Adresse/PORT-Hauptserver-Redis-Dienst-Port):

  • Konfigurationsdatei – Konfigurieren Sie in der Datei redis.conf den Befehl „slaveof ip port“ – Geben Sie den Redis-Client ein, um „slaveof ip port“ auszuführen. Startparameter – ./redis-server --slaveof ip port

  • 2, Die Entwicklung der Master-Slave-Replikation

    Der Master-Slave-Replikationsmechanismus von Redis war zu Beginn nicht so perfekt wie die 6.x-Version, wurde aber von Version zu Version iteriert. Es hat im Allgemeinen drei Versionen von Iterationen durchlaufen:
  • Vor 2.8

2.8~4.0

  • Nach 4.0

  • Mit zunehmender Version verbessert sich der Redis-Master-Slave-Replikationsmechanismus allmählich Im Wesentlichen drehen sie sich um die beiden Vorgänge Synchronisierung (Sync) und Befehlsweitergabe:

  • Synchronisierung (Sync): bezieht sich auf die Aktualisierung des Datenstatus des Slave-Servers auf den aktuellen Datenstatus des Hauptservers, was hauptsächlich in erfolgt Initialisierung oder anschließende vollständige Synchronisierung.

Befehlsweitergabe: Wenn der Datenstatus des Master-Servers geändert wird (Schreiben/Löschen usw.) und der Datenstatus zwischen Master und Slave inkonsistent ist, gibt der Master-Dienst den Befehl zur Datenänderung an den Slave weiter Server, sodass der Master den Zustand zwischen den Slave-Servern wiederherstellen kann, um konsistent zu sein.

  • 2.1 Vor Version 2.8

    2.1.1 Synchronisierung
  • Vor Version 2.8 erfordert die Synchronisierung des Slave-Servers mit dem Master-Server den Abschluss des Synchronisierungsbefehls vom Server zum Master-Server:

Vom Server empfangen Nach dem vom Client gesendeten Befehl „slaveof ip prot“ erstellt der Slave-Server eine Socket-Verbindung zum Master-Server basierend auf ip:port

Nachdem der Socket erfolgreich mit dem Master-Server verbunden wurde, wird der Slave-Server erstellt ordnet dem Master-Server eine dedizierte Socket-Verbindung zu, die für die Verarbeitung von Replikationsarbeiten, die Verarbeitung nachfolgender RDB-Dateien und die vom Master-Server gesendeten weitergegebenen Befehle verwendet wird. Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

  • Replikation starten und Synchronisierungsbefehle vom Server an den Master-Server senden

  • Der Master-Server empfängt den Synchronisierungsbefehl. Führen Sie anschließend den Befehl bgsave aus. Der Unterprozess des Hauptprozesszweigs des Hauptservers generiert eine RDB-Datei und zeichnet gleichzeitig alle Schreibvorgänge nach dem RDB-Snapshot auf wird im Puffer generiert
  • Nachdem der Befehl bgsave ausgeführt wurde, generiert der Hauptserver Die RDB-Datei wird an den Slave-Server gesendet. Nach dem Empfang der RDB-Datei vom Slave-Server löscht dieser zunächst alle seine eigenen Daten. Laden Sie dann die RDB-Datei und aktualisieren Sie ihren eigenen Datenstatus auf den Datenstatus der RDB-Datei des Master-Servers
  • Der Master-Server sendet den Pufferschreibbefehl an den Slave-Server, empfängt den Befehl vom Server und führt ihn aus Es.
  • Der Synchronisierungsschritt der Master-Slave-Replikation ist abgeschlossen
  • 2.1.2 Befehlsweitergabe
  • Nach Abschluss der Synchronisierungsarbeiten muss der Master-Slave die Konsistenz des Datenstatus durch Befehlsweitergabe aufrechterhalten. Wie in der folgenden Abbildung gezeigt, löscht der Master-Dienst nach Abschluss der Synchronisierungsarbeiten zwischen dem aktuellen Master- und Slave-Server K6, nachdem er die DEL K6-Anweisung vom Client erhalten hat. Zu diesem Zeitpunkt ist K6 noch auf dem Slave-Server vorhanden Der Master-Slave-Datenstatus ist inkonsistent. Um den konsistenten Status der Master- und Slave-Server aufrechtzuerhalten, gibt der Master-Server Befehle weiter, die dazu führen, dass sich sein eigener Datenstatus zur Ausführung an den Slave-Server ändert. Wenn der Slave-Server denselben Befehl ebenfalls ausführt, ändert sich der Datenstatus zwischen den Master- und Slave-Server bleiben konsistent.

  • 2.1.3 Mängel
  • Aus dem oben Gesagten können wir keine Mängel in der Master-Slave-Replikation von Versionen vor 2.8 erkennen. Dies liegt daran, dass wir Netzwerkschwankungen nicht berücksichtigt haben. Brüder, die sich mit der Verteilung auskennen, müssen von der CAP-Theorie gehört haben. In der CAP-Theorie muss P (Partitionsnetzwerkpartition) vorhanden sein, und die Redis-Master-Slave-Replikation ist keine Ausnahme. Wenn ein Netzwerkfehler zwischen dem Master- und dem Slave-Server auftritt, führt dies dazu, dass die Kommunikation zwischen dem Slave-Server und dem Master-Server für einen bestimmten Zeitraum ausfällt. Wenn der Slave-Server erneut eine Verbindung zum Master-Server herstellt, ändert sich der Datenstatus des Master-Servers Wenn sich in diesem Zeitraum Änderungen ergeben, kommt es zu Inkonsistenzen im Datenstatus des Master-Slave-Servers zwischen den Servern. In Master-Slave-Replikationsversionen vor Redis 2.8 besteht die Möglichkeit, diese Datenstatusinkonsistenz zu beheben, darin, den Synchronisierungsbefehl erneut zu senden. Obwohl die Synchronisierung sicherstellen kann, dass der Datenstatus der Master- und Slave-Server konsistent ist, ist es offensichtlich, dass die Synchronisierung ein sehr ressourcenintensiver Vorgang ist.

    Befehlsausführung synchronisieren, die vom Master- und Slave-Server benötigten Ressourcen:

    • Der Master-Server führt BGSAVE aus, um RDB-Dateien zu generieren, die viel CPU-, Festplatten-E/A- und Speicherressourcen beanspruchen

    • Die Der Master-Server sendet die generierten RDB-Dateien. Wenn Sie sie an den Slave-Server weitergeben, wird viel Netzwerkbandbreite beansprucht.

    • Der Empfang und das Laden der RDB-Datei vom Server führt dazu, dass der Slave-Server blockiert wird und keine Dienste bereitstellen kann

    • Wie aus den oben genannten drei Punkten ersichtlich ist, führt der Synchronisierungsbefehl nicht nur dazu, dass der Master eine Verringerung der Reaktionsfähigkeit des Servers verursacht, sondern auch dazu, dass der Slave-Server während dieser Zeit die Bereitstellung externer Dienste verweigert.

    2.2 Version 2.8-4.0

    2.2.1 Verbesserungen

    Für Versionen vor 2.8 hat Redis die Datenstatussynchronisierung nach der erneuten Verbindung vom Server nach 2.8 verbessert. Die Verbesserungsrichtung besteht darin, das Auftreten einer vollständigen Neusynchronisierung zu reduzieren und eine teilweise Neusynchronisierung so weit wie möglich zu nutzen. Nach Version 2.8 wird der Befehl psync anstelle des Befehls sync verwendet, um Synchronisierungsvorgänge durchzuführen. Der Befehl psync verfügt sowohl über vollständige als auch inkrementelle Synchronisierungsfunktionen:

      Die vollständige Synchronisierung stimmt mit der vorherigen Version überein (sync)
    • Inkrementell Synchronisierung Für die Replikation nach Trennung und Wiederverbindung werden je nach Situation unterschiedliche Maßnahmen ergriffen. Wenn die Bedingungen dies zulassen, wird nur ein Teil der im Dienst fehlenden Daten gesendet. 2.2.2 So implementieren Sie psync Replikationsrückstand)
    • Server-Lauf-ID (Lauf-ID)

    2.2.2.1 Replikations-Offset
    • Ein Replikations-Offset wird im Master-Server und Slave-Server beibehalten

    • Der Master-Server sendet Daten an Der Slave-Dienst verteilt N Datenbytes und der Replikationsoffset des Masterdienstes erhöht sich um N

    • Der Slave-Server empfängt die vom Master-Server gesendeten Daten, empfängt N Datenbytes und der Slave-Server Der Replikationsoffset erhöht sich um N

    Die normale Synchronisationssituation ist wie folgt:

    • Durch den Vergleich, ob die Replikationsoffsets zwischen dem Master- und dem Slave-Server gleich sind, können Sie feststellen, ob der Datenstatus zwischen dem Master- und dem Slave-Server ist ist Sei konsequent.

      Angenommen, dass A/B zu diesem Zeitpunkt normal weitergegeben wird und der Slave-Server C getrennt ist, dann wird die folgende Situation eintreten:

    • Offensichtlich mit dem Replikationsoffset, nachdem der Slave-Server C getrennt und wieder verbunden wurde Der Master-Server sendet nur die fehlenden 100 Byte Daten vom Server.
    Aber woher weiß der Master-Server, welche Daten auf dem Slave-Server fehlen?

    2.2.2.2 Kopier-Backlog-Puffer

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    Der Kopier-Backlog-Puffer ist eine Warteschlange fester Länge mit einer Standardgröße von 1 MB. Wenn sich der Datenstatus des Master-Servers ändert, synchronisiert der Master-Server die Daten mit dem Slave-Server und speichert eine Kopie im Replikations-Backlog-Puffer.

    Um den Offset anzupassen, speichert der Kopierrückstandspuffer nicht nur den Dateninhalt, sondern zeichnet auch den jedem Byte entsprechenden Offset auf: Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    Wenn der Slave-Server getrennt und wieder verbunden wird, schließlich der Slave Der Server sendet über den Befehl psync seinen eigenen Replikationsoffset (Offset) an den Masterserver. Der Masterserver kann diesen Offset verwenden, um zu bestimmen, ob eine inkrementelle Weitergabe oder eine vollständige Synchronisierung durchgeführt werden soll.

    Wenn sich die Daten bei Offset + 1 noch im Kopierrückstandspuffer befinden, führen Sie einen inkrementellen Synchronisierungsvorgang aus.

    Andernfalls führen Sie einen vollständigen Synchronisierungsvorgang im Einklang mit der Synchronisierung durch.Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

Die Standardpuffergröße für den Kopierrückstand von Redis beträgt 1 MB. Wie wird sie eingestellt, wenn Sie sie anpassen müssen? Natürlich möchten wir so viel wie möglich die inkrementelle Synchronisierung verwenden, aber wir möchten nicht, dass der Puffer zu viel Speicherplatz beansprucht. Dann können wir die Größe des Replikations-Backlog-Puffers S festlegen, indem wir die Wiederverbindungszeit T nach der Trennung des Redis-Slave-Dienstes und die Speichergröße M der vom Redis-Master-Server pro Sekunde empfangenen Schreibbefehle schätzen.

S = 2 * M * T

Beachten Sie, dass die 2-fache Erweiterung hier dazu dient, einen gewissen Spielraum zu lassen, um sicherzustellen, dass die meisten Trennungen und Wiederverbindungen eine inkrementelle Synchronisierung verwenden können. 2.2.2.3 Server, auf dem die ID ausgeführt wird Tatsächlich gibt es eine andere Situation, die nicht berücksichtigt wurde: Wenn der Master-Server ausfällt, wird ein Slave-Server als neuer Master-Server ausgewählt. In diesem Fall können wir ihn durch Vergleich der laufenden ID unterscheiden.

Die Lauf-ID (Lauf-ID) besteht aus 40 zufälligen Hexadezimalzeichenfolgen, die beim Starten des Servers automatisch generiert werden. Sowohl der Master-Dienst als auch der Slave-Server generieren die Lauf-ID.

    Wenn der Slave-Server die des Master-Servers synchronisiert Beim ersten Mal, wenn Daten generiert werden, sendet der Master-Server seine eigene laufende ID an den Slave-Server und der Slave-Server speichert sie in der RDB-Datei
  • Wenn der Slave-Server getrennt und wieder verbunden wird, sendet der Slave-Server Wenn die Server-Lauf-ID übereinstimmt, beweist dies, dass sich der Hauptserver nicht geändert hat. Sie können eine inkrementelle Synchronisierung versuchen. Wenn die Server-Lauf-ID nicht übereinstimmt, führen Sie eine vollständige Synchronisierung durch Synchronisierung
  • 2.2.3 Vollständiger ppsync
  • Vollständig Der psync-Prozess ist sehr komplex und in der Master-Slave-Replikationsversion 2.8-4.0 sehr vollständig. Die vom psync-Befehl gesendeten Parameter lauten wie folgt:

  • psync

Wenn der Slave-Server keinen Master-Server repliziert hat (es ist nicht das erste Mal, dass der Master-Slave repliziert, da sich der Master-Server ändern kann), aber die erste vollständige Kopie des Slave-Servers sendet:

psync ? -1

Der vollständige psync-Prozess ist wie folgt:

Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

SLAVEOF 127.0.0.1 wird vom Server 6379 empfangen. Der Befehl

gibt OK vom Server an den Befehlsinitiator zurück (dies ist ein asynchroner Vorgang, geben Sie zuerst OK zurück und speichern Sie dann die Adress- und Portinformationen)

一次完整的Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    Speichern Die IP-Adresse und die Portinformationen vom Server zum Master-Host und Master-Port.
  • Der Slave-Server initiiert aktiv eine Socket-Verbindung zum Master-Server basierend auf dem Master-Host und dem Master-Port. Gleichzeitig wird der Slave-Dienst aktiviert Verknüpfen Sie einen Dateiereignishandler, der speziell zum Kopieren von Dateien verwendet wird, mit dieser Socket-Verbindung für die spätere Verwendung des Kopierens von RDB-Dateien und anderer Arbeiten. Der Master-Server empfängt die Socket-Verbindungsanforderung vom Slave-Server und erstellt eine entsprechende Socket-Verbindung für die Anforderung. und betrachtet einen Client vom Slave-Server (bei der Master-Slave-Replikation sind der Master-Server und der Slave-Server tatsächlich Clients und Server voneinander)
  • Die Socket-Verbindung wird hergestellt. Der Slave-Server sendet aktiv einen PING-Befehl Wenn der Master-Server innerhalb des angegebenen Timeout-Zeitraums PONG zurückgibt, beweist dies, dass die Socket-Verbindung verfügbar ist. Andernfalls wird die Verbindung getrennt und erneut hergestellt. Wenn der Master-Server ein Kennwort festgelegt hat (Masterauth), sendet der Slave-Server Senden Sie den Befehl AUTH masterauth zur Authentifizierung an den Master-Server. Beachten Sie, dass, wenn der Slave-Server ein Passwort sendet, der Master-Server jedoch kein Passwort festlegt, der Master-Server einen Fehler sendet, bei dem kein Passwort festgelegt ist Der Server sendet einen NOAUTH-Fehler. Wenn die Passwörter nicht übereinstimmen, sendet der Master-Server einen Fehler wegen eines ungültigen Passworts.
  • Der Slave-Server sendet REPLCONF Listening-Port xxxx (xxxx stellt den Port des Slave-Servers dar) an den Master-Server. Nach Erhalt des Befehls speichert der Hauptserver die Daten. Wenn der Client die INFO-Replikation verwendet, um die Master-Slave-Informationen abzufragen, kann er die Daten zurückgeben. Senden Sie den psync-Befehl vom Server Die beiden psync-Situationen im Bild oben
  • Der Master-Server und der Slave-Server sind gegenseitige Clients und führen Datenanfragen/-antworten aus
  • Der Master-Server und der Slave-Server verwenden den Heartbeat-Paketmechanismus, um festzustellen, ob Die Verbindung wird getrennt. Der Slave-Server sendet alle 1 Sekunde einen Befehl an den Master-Server, REPLCONF ACL-Offset (Replikations-Offset des Slave-Servers). Wenn die Offsets nicht gleich sind, kann der Master sicherstellen Der Server ergreift inkrementelle/vollständige Synchronisierungsmaßnahmen, um einen konsistenten Datenstatus zwischen Master und Slave sicherzustellen (die Wahl von inkrementell/vollständig hängt davon ab, ob sich die Daten bei Offset+1 noch im Replikations-Backlog-Puffer befinden)

2.3 Version 4.0

Redis Version 2.8-4.0 bietet noch Raum für Verbesserungen. Kann eine inkrementelle Synchronisierung durchgeführt werden, wenn der Hauptserver gewechselt wird? Daher wurde die Redis 4.0-Version optimiert, um dieses Problem zu lösen, und psync wurde auf psync2.0 aktualisiert. pync2.0 hat die laufende ID des Servers aufgegeben und stattdessen replid und replid2 verwendet. Replid speichert die laufende ID des aktuellen Hauptservers und replid2 speichert die laufende ID des vorherigen Hauptservers.

  • Replikationsoffset

  • Replikationsrückstand

  • Master-Server-Lauf-ID (Replid)

  • Letzter Master-Server-Lauf-ID (Replid2)

Durch Replid und Mit replid2 können wir das Problem der Inkrementierung lösen Synchronisierung beim Wechsel des Hauptservers:

  • Wenn Replid gleich der laufenden ID des aktuellen Hauptservers ist, dann bestimmen Sie die Synchronisierungsmethode inkrementelle/vollständige Synchronisierung

  • Wenn Replid nicht gleich ist, dann bestimmen Sie, ob Replicad2 ist gleich (unabhängig davon, ob sie zum Slave-Server des vorherigen Master-Servers gehören). Wenn sie gleich sind, können Sie immer noch die inkrementelle/vollständige Synchronisierung wählen. Wenn sie nicht gleich sind, können Sie nur eine vollständige Synchronisierung durchführen.

2. Sentinel

1. Die Master-Slave-Replikation legt den Grundstein für die Redis-Verteilung, aber mit der normalen Master-Slave-Replikation kann keine hohe Verfügbarkeit erreicht werden. Im normalen Master-Slave-Replikationsmodus kann das Betriebs- und Wartungspersonal den Master-Server nur manuell wechseln, wenn der Master-Server ausfällt. Offensichtlich ist diese Lösung nicht ratsam. Als Reaktion auf die oben genannte Situation hat Redis offiziell eine Hochverfügbarkeitslösung eingeführt, die Knotenausfällen widerstehen kann – Redis Sentinel. Redis Sentinel: Ein Sentinel-System, das aus einer oder mehreren Sentinel-Instanzen besteht. Es kann eine beliebige Anzahl von Master- und Slave-Servern überwachen. Wenn der überwachte Master-Server ausfällt, wird der Master-Server automatisch offline geschaltet und der Slave-Server wird auf einen neuen Master aktualisiert Server.

Das folgende Beispiel: Wenn der alte Master länger als die vom Benutzer festgelegte Obergrenze der Offline-Zeit offline ist, führt das Sentinel-System einen Failover-Vorgang auf dem alten Master durch. Der Failover-Vorgang umfasst drei Schritte:

    Wählen Sie Daten im Slave aus. Der neueste dient als neuer Master.
  • Sendet neue Replikationsanweisungen an andere Slaves, sodass andere Slave-Server zu Slaves des neuen Masters werden können.
  • Überwachen Sie weiterhin den alten Master und prüfen Sie ggf geht online, setzt den alten Master auf den neuen Master Slave

Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

Dieser Artikel basiert auf der folgenden Ressourcenliste:

IP-AdresseKnotenrollePort Redis Slave/ Sentinel
192.168.211.104 192.168.211.105
6 379/ 26379

2. Sentinel-Initialisierung und Netzwerkverbindung: Es gibt nichts Besonderes an Sentinel. Es handelt sich um einen einfacheren Redis-Server, der beim Start verschiedene Befehlstabellen und Konfigurationsdateien lädt weniger Befehle und einige Sonderfunktionen. Wenn ein Sentinel gestartet wird, muss er die folgenden Schritte durchlaufen:

    Initialisieren Sie den Sentinel-Server Initialisieren Sie mithilfe der vom Benutzer bereitgestellten Sentinel-Konfigurationsdatei die Liste der von Sentinel überwachten Master-Server. Erstellen Sie eine Netzwerkverbindung zum Master-Server. Rufen Sie die Slave-Server-Informationen basierend auf dem Master-Dienst ab und erstellen Sie eine Netzwerkverbindung zu der Slave-Server
  • Sentinel-Informationen basierend auf Publish/Subscribe abrufen, eine Netzwerkverbindung zwischen Sentinel erstellen
  • 2.1 Sentinel-Server initialisieren
  • Sentinel ist im Wesentlichen ein Redis-Server, daher erfordert das Starten von Sentinel das Starten eines Redis-Servers, aber von Sentinel Es ist nicht erforderlich, RDB/AOF-Dateien zu lesen, um den Datenstatus wiederherzustellen.

  • 2.2 Ersetzen Sie gewöhnlichen Redis-Code durch Sentinel-spezifischen Code
  • Sentinel wird für weniger Redis-Befehle verwendet. Die meisten Befehle werden vom Sentinel-Client nicht unterstützt, und Sentinel verfügt über einige spezielle Funktionen, die erfordern, dass Sentinel beim Start Redis verwendet. Der vom Server verwendete Code wird durch Sentinel-spezifischen Code ersetzt. Während dieser Zeit lädt Sentinel eine andere Befehlstabelle als der normale Redis-Server. Sentinel unterstützt keine Befehle wie SET und DBSIZE; die Unterstützung für PING, PSUBSCRIBE, SUBSCRIBE, INFO und andere Befehle bietet Garantien für die Arbeit von Sentinel.

  • 2.3 Sentinel-Status initialisieren
  • Nach dem Laden des eindeutigen Codes von Sentinel initialisiert Sentinel die sentinelState-Struktur, die zum Speichern von Sentinel-bezogenen Statusinformationen verwendet wird, von denen das Master-Wörterbuch am wichtigsten ist.

    struct sentinelState {
       
        //当前纪元,故障转移使用
     uint64_t current_epoch; 
      
        // Sentinel监视的主服务器信息 
        // key -> 主服务器名称 
        // value -> 指向sentinelRedisInstance指针
        dict *masters; 
        // ...
    } sentinel;
  • 2.4 Initialisieren Sie die von Sentinel überwachte Master-Serverliste. Die von Sentinel überwachte Master-Serverliste wird im Master-Wörterbuch von sentinelState gespeichert. Wenn sentinelState erstellt wird, beginnt die Initialisierung der von Sentinel überwachten Master-Server.
  • Der Master-Schlüssel ist der Name des Hauptdienstes.
  • Der Master-Wert ist ein Zeiger auf sentinelRedisInstance. Der Name des Hauptservers wird durch unsere sentinel.conf-Konfigurationsdatei wie folgt angegeben Der Name des Hauptservers ist redis-master (Hier ist die Konfiguration von einem Master und zwei Slaves):
daemonize yes
port 26379
protected-mode no
dir "/usr/local/soft/redis-6.2.4/sentinel-tmp"
sentinel monitor redis-master 192.168.211.104 6379 2
sentinel down-after-milliseconds redis-master 30000
sentinel failover-timeout redis-master 180000
sentinel parallel-syncs redis-master 1

sentinelRedisInstance-Instanz speichert die Informationen des Redis-Servers (der Master-Server, der Slave-Server und die Sentinel-Informationen werden alle in dieser Instanz gespeichert). .

typedef struct sentinelRedisInstance {
 
    // 标识值,标识当前实例的类型和状态。如SRI_MASTER、SRI_SLVAE、SRI_SENTINEL
    int flags;
    
    // 实例名称 主服务器为用户配置实例名称、从服务器和Sentinel为ip:port
    char *name;
    
    // 服务器运行ID
    char *runid;
    
    //配置纪元,故障转移使用
 uint64_t config_epoch; 
    
    // 实例地址
    sentinelAddr *addr;
    
    // 实例判断为主观下线的时长 sentinel down-after-milliseconds redis-master 30000
    mstime_t down_after_period; 
    
    // 实例判断为客观下线所需支持的投票数 sentinel monitor redis-master 192.168.211.104 6379 2
    int quorum;
    
    // 执行故障转移操作时,可以同时对新的主服务器进行同步的从服务器数量 sentinel parallel-syncs redis-master 1
    int parallel-syncs;
    
    // 刷新故障迁移状态的最大时限 sentinel failover-timeout redis-master 180000
 mstime_t failover_timeout;
    
    // ...
} sentinelRedisInstance;

Gemäß der obigen Konfiguration von einem Master und zwei Slaves erhalten Sie die folgende Instanzstruktur:

2.5 Erstellen Sie eine Netzwerkverbindung zum Master-Server

Nachdem die Instanzstruktur initialisiert wurde, beginnt Sentinel damit Erstellen Sie eine Netzwerkverbindung zum Master. In diesem Schritt wird Sentinel zum Client des Masters. Zwischen Sentinel und Master werden eine Befehlsverbindung und eine Abonnementverbindung erstellt:

Die Befehlsverbindung wird verwendet, um Master-Slave-Informationen zu erhalten.

  • Die Abonnementverbindung wird für die Informationsübertragung zwischen Sentinel, jedem Sentinel und dem von ihm überwachten Master verwendet Die Slave-Server abonnieren den Kanal _sentinel_:hello (beachten Sie, dass keine Abonnementverbindungen zwischen Sentinels erstellt werden. Sie erhalten die ersten Informationen anderer Sentinels, indem sie den Kanal _sentinel_:hello abonnieren).

  • Sentinel erstellt einen Befehlsverbindung Nach Abschluss wird alle 10 Sekunden ein INFO-Befehl an den Master gesendet. Über die Antwortinformationen des Masters können zwei Aspekte des Wissens abgerufen werden:

Master-eigene Informationen

Slave-Informationen unter dem MasterFühren Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    2.6 Erstellen Sie eine Netzwerkverbindung zum Slave-Server.
  • Rufen Sie die Slave-Serverinformationen entsprechend dem Master-Dienst ab. Es werden auch Befehlsverbindungen und Abonnementverbindungen zwischen Sentinel und Slave erstellt.

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    当Sentinel和Slave之间创建网络连接之后,Sentinel成为了Slave的客户端,Sentinel也会每隔10秒钟通过INFO指令请求Slave获取服务器信息。 到这一步Sentinel获取到了Master和Slave的相关服务器数据。这其中比较重要的信息如下:

    • 服务器ip和port

    • 服务器运行id run id

    • 服务器角色role

    • 服务器连接状态mater_link_status

    • Slave复制偏移量slave_repl_offset(故障转移中选举新的Master需要使用)

    • Slave优先级slave_priority

    此时实例结构信息如下所示:

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    2.7 创建Sentinel之间的网络连接

    此时是不是还有疑问,Sentinel之间是怎么互相发现对方并且相互通信的,这个就和上面Sentinel与自己监视的主从之间订阅_sentinel_:hello频道有关了。 Sentinel会与自己监视的所有Master和Slave之间订阅_sentinel_:hello频道,并且Sentinel每隔2秒钟向_sentinel_:hello频道发送一条消息,消息内容如下:

    PUBLISH sentinel:hello ",,,,,,,"

    其中s代码Sentinel,m代表Master;ip表示IP地址,port表示端口、runid表示运行id、epoch表示配置纪元。

    多个Sentinel在配置文件中会配置相同的主服务器ip和端口信息,因此多个Sentinel均会订阅_sentinel_:hello频道,通过频道接收到的信息就可获取到其他Sentinel的ip和port,其中有如下两点需要注意:

    • 如果获取到的runid与Sentinel自己的runid相同,说明消息是自己发布的,直接丢弃

    • 如果不相同,则说明接收到的消息是其他Sentinel发布的,此时需要根据ip和port去更新或新增Sentinel实例数据

    Sentinel之间不会创建订阅连接,它们只会创建命令连接:

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    此时实例结构信息如下所示:

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    3、Sentinel工作

    Sentinel最主要的工作就是监视Redis服务器,当Master实例超出预设的时限后切换新的Master实例。这其中有很多细节工作,大致分为检测Master是否主观下线、检测Master是否客观下线、选举领头Sentinel、故障转移四个步骤。

    3.1 检测Master是否主观下线

    Sentinel每隔1秒钟,向sentinelRedisInstance实例中的所有Master、Slave、Sentinel发送PING命令,通过其他服务器的回复来判断其是否仍然在线。

    sentinel down-after-milliseconds redis-master 30000

    在Sentinel的配置文件中,当Sentinel PING的实例在连续down-after-milliseconds配置的时间内返回无效命令,则当前Sentinel认为其主观下线。Sentinel的配置文件中配置的down-after-milliseconds将会对其sentinelRedisInstance实例中的所有Master、Slave、Sentinel都适应。

    无效指令指的是+PONG、-LOADING、-MASTERDOWN之外的其他指令,包括无响应

    如果当前Sentinel检测到Master处于主观下线状态,那么它将会修改其sentinelRedisInstance的flags为SRI_S_DOWN

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    3.2 检测Master是否客观下线

    当前Sentinel认为其下线只能处于主观下线状态,要想判断当前Master是否客观下线,还需要询问其他Sentinel,并且所有认为Master主观下线或者客观下线的总和需要达到quorum配置的值,当前Sentinel才会将Master标志为客观下线。

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    当前Sentinel向sentinelRedisInstance实例中的其他Sentinel发送如下命令:

    SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>
    • ip:被判断为主观下线的Master的IP地址

    • port:被判断为主观下线的Master的端口

    • current_epoch:当前sentinel的配置纪元

    • runid:当前sentinel的运行id,runid

    current_epoch和runid均用于Sentinel的选举,Master下线之后,需要选举一个领头Sentinel来选举一个新的Master,current_epoch和runid在其中发挥着重要作用,这个后续讲解。

    接收到命令的Sentinel,会根据命令中的参数检查主服务器是否下线,检查完成后会返回如下三个参数:

    • down_state:检查结果1代表已下线、0代表未下线

    • leader_runid:返回*代表判断是否下线,返回runid代表选举领头Sentinel

    • leader_epoch:当leader_runid返回runid时,配置纪元会有值,否则一直返回0

    • 当Sentinel检测到Master处于主观下线时,询问其他Sentinel时会发送current_epoch和runid,此时current_epoch=0,runid=*

    • 接收到命令的Sentinel返回其判断Master是否下线时down_state = 1/0,leader_runid = *,leader_epoch=0

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    3.3 选举领头Sentinel

    down_state返回1,证明接收is-master-down-by-addr命令的Sentinel认为该Master也主观下线了,如果down_state返回1的数量(包括本身)大于等于quorum(配置文件中配置的值),那么Master正式被当前Sentinel标记为客观下线。 此时,Sentinel会再次发送如下指令:

    SENTINEL is-master-down-by-addr <ip> <port> <current_epoch> <runid>

    此时的runid将不再是0,而是Sentinel自己的运行id(runid)的值,表示当前Sentinel希望接收到is-master-down-by-addr命令的其他Sentinel将其设置为领头Sentinel。这个设置是先到先得的,Sentinel先接收到谁的设置请求,就将谁设置为领头Sentinel。 发送命令的Sentinel会根据其他Sentinel回复的结果来判断自己是否被该Sentinel设置为领头Sentinel,如果Sentinel被其他Sentinel设置为领头Sentinel的数量超过半数Sentinel(这个数量在sentinelRedisInstance的sentinel字典中可以获取),那么Sentinel会认为自己已经成为领头Sentinel,并开始后续故障转移工作(由于需要半数,且每个Sentinel只会设置一个领头Sentinel,那么只会出现一个领头Sentinel,如果没有一个达到领头Sentinel的要求,Sentinel将会重新选举直到领头Sentinel产生为止)。

    3.4 故障转移

    故障转移将会交给领头sentinel全权负责,领头sentinel需要做如下事情:

    • 从原先master的slave中,选择最佳的slave作为新的master

    • 让其他slave成为新的master的slave

    • 继续监听旧master,如果其上线,则将其设置为新的master的slave

    这其中最难的一步是如果选择最佳的新Master,领头Sentinel会做如下清洗和排序工作:

    • 判断slave是否有下线的,如果有从slave列表中移除

    • 删除5秒内未响应sentinel的INFO命令的slave

    • 删除与下线主服务器断线时间超过down_after_milliseconds * 10 的所有从服务器

    • 根据slave优先级slave_priority,选择优先级最高的slave作为新master

    • 如果优先级相同,根据slave复制偏移量slave_repl_offset,选择偏移量最大的slave作为新master

    • 如果偏移量相同,根据slave服务器运行id run id排序,选择run id最小的slave作为新master

    新的Master产生后,领头sentinel会向已下线主服务器的其他从服务器(不包括新Master)发送SLAVEOF ip port命令,使其成为新master的slave。

    到这里Sentinel的的工作流程就算是结束了,如果新master下线,则循环流程即可!

    三、集群

    1、简介

    Redis集群是Redis提供的分布式数据库方案,集群通过分片(sharding)进行数据共享,Redis集群主要实现了以下目标:

    • 在1000个节点的时候仍能表现得很好并且可扩展性是线性的。

    • 没有合并操作(多个节点不存在相同的键),这样在 Redis 的数据模型中最典型的大数据值中也能有很好的表现。

    • Schreibsicherheit: Das System versucht, alle Schreibvorgänge zu speichern, die von Clients durchgeführt werden, die mit den meisten Knoten verbunden sind. Allerdings kann Redis nicht garantieren, dass Daten überhaupt nicht verloren gehen. Die asynchrone und synchrone Master-Slave-Replikation führt ohnehin zu Datenverlust.

    • Verfügbarkeit: Wenn der Masterknoten nicht verfügbar ist, kann der Slaveknoten den Masterknoten ersetzen.

    Wenn Sie keine Erfahrung mit dem Erlernen von Redis-Clustern haben, wird empfohlen, diese drei Artikel (chinesische Serie) zu lesen: Redis-Cluster-Tutorial

    REDIS-Cluster-Tutorial – Informationen zu Redis auf Chinesisch Station – Redis China User Group (CRUG)

    Redis Cluster Specification

    REDIS Cluster-Spec – Redis Chinese Information Station – Redis China User Group (CRUG)

    Redis3 Master 3 Slave Pseudo-Cluster-Bereitstellung

    CentOS 7 Es sind nur fünf einfache Schritte erforderlich, um den Redis-Cluster (Pseudocluster mit 3 Mastern und 3 Slaves) auf einer einzelnen Maschine zu installieren_Li Zipins Blog – CSDN-Blog

    Der folgende Inhalt basiert auf der Struktur mit drei Mastern und drei Slaves im Abbildung unten:

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    Ressourcenliste:

    Node IP Slotbereich
    Master[0] 192.168.211 :6319 Slots 0 - 5460
    Master[1] 192.168.211.107:6329 Slots 5461 - 10922
    Master[2] 192.168.211.107:6339 Slots 10923 - 16383
    Sklave[0] 192.168.211.107:6369
    Sklave[1] 192.168.211.107:6349
    Sklave[2] 192.168.211.107: 6359

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    2、集群内部

    Redis 集群没有使用一致性hash, 而是引入了 哈希槽的概念。Redis 集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,这种结构很容易添加或者删除节点。集群的每个节点负责一部分hash槽,比如上面资源清单的集群有3个节点,其槽分配如下所示:

    • 节点 Master[0] 包含 0 到 5460 号哈希槽

    • 节点 Master[1] 包含5461 到 10922 号哈希槽

    • 节点 Master[2] 包含10923到 16383 号哈希槽

    深入学习Redis集群之前,需要了解集群中Redis实例的内部结构。当某个Redis服务节点通过cluster_enabled配置为yes开启集群模式之后,Redis服务节点不仅会继续使用单机模式下的服务器组件,还会增加custerState、clusterNode、custerLink等结构用于存储集群模式下的特殊数据。

    如下三个数据承载对象一定要认真看,尤其是结构中的注释,看完之后集群大体上怎么工作的,心里就有数了,嘿嘿嘿;

    2.1 clsuterNode

    clsuterNode用于存储节点信息,比如节点的名字、IP地址、端口信息和配置纪元等等,以下代码列出部分非常重要的属性:

    typedef struct clsuterNode {
    
        // 创建时间
        mstime_t ctime;
        
        // 节点名字,由40位随机16进制的字符组成(与sentinel中讲的服务器运行id相同)
        char name[REDIS_CLUSTER_NAMELEN];
        
        // 节点标识,可以标识节点的角色和状态
        // 角色 -> 主节点或从节点 例如:REDIS_NODE_MASTER(主节点) REDIS_NODE_SLAVE(从节点)
        // 状态 -> 在线或下线 例如:REDIS_NODE_PFAIL(疑似下线) REDIS_NODE_FAIL(下线) 
        int flags;
        
        // 节点配置纪元,用于故障转移,与sentinel中用法类似
        // clusterState中的代表集群的配置纪元
        unit64_t configEpoch;
        
        // 节点IP地址
        char ip[REDIS_IP_STR_LEN];
        
        // 节点端口
        int port;
        
        // 连接节点的信息
        clusterLink *link;
        
        // 一个2048字节的二进制位数组
        // 位数组索引值可能为0或1
        // 数组索引i位置值为0,代表节点不负责处理槽i
        // 数组索引i位置值为1,代表节点负责处理槽i
        unsigned char slots[16384/8];
        
        // 记录当前节点处理槽的数量总和
        int numslots;
        
        // 如果当前节点是从节点
        // 指向当前从节点的主节点
        struct clusterNode *slaveof;
        
        // 如果当前节点是主节点
        // 正在复制当前主节点的从节点数量
        int numslaves;
        
        // 数组——记录正在复制当前主节点的所有从节点
        struct clusterNode **slaves;
        
    } clsuterNode;

    上述代码中可能不太好理解的是slots[16384/8],其实可以简单的理解为一个16384大小的数组,数组索引下标处如果为1表示当前槽属于当前clusterNode处理,如果为0表示不属于当前clusterNode处理。clusterNode能够通过slots来识别,当前节点处理负责处理哪些槽。 初始clsuterNode或者未分配槽的集群中的clsuterNode的slots如下所示:

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    假设集群如上面我给出的资源清单,此时代表Master[0]的clusterNode的slots如下所示:

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    clusterLink是clsuterNode中的一个属性,用于存储连接节点所需的相关信息,比如套接字描述符、输入输出缓冲区等待,以下代码列出部分非常重要的属性:

    typedef struct clusterState {
    
        // 连接创建时间
        mstime_t ctime;
       
        // TCP 套接字描述符
        int fd;
        
        // 输出缓冲区,需要发送给其他节点的消息缓存在这里
        sds sndbuf;
        
        // 输入缓冲区,接收打其他节点的消息缓存在这里
        sds rcvbuf;
        
        // 与当前clsuterNode节点代表的节点建立连接的其他节点保存在这里
        struct clusterNode *node;
    } clusterState;

    2.3 custerState

    每个节点都会有一个custerState结构,这个结构中存储了当前集群的全部数据,比如集群状态、集群中的所有节点信息(主节点、从节点)等等,以下代码列出部分非常重要的属性:

    typedef struct clusterState {
    
        // 当前节点指针,指向一个clusterNode
        clusterNode *myself;
        
        // 集群当前配置纪元,用于故障转移,与sentinel中用法类似
        unit64_t currentEpoch;
        
        // 集群状态 在线/下线
        int state;
        
        // 集群中处理着槽的节点数量总和
        int size;
        
        // 集群节点字典,所有clusterNode包括自己
        dict *node;
        
        // 集群中所有槽的指派信息
        clsuterNode *slots[16384];
        
        // 用于槽的重新分配——记录当前节点正在从其他节点导入的槽
        clusterNode *importing_slots_from[16384];
        
        // 用于槽的重新分配——记录当前节点正在迁移至其他节点的槽
        clusterNode *migrating_slots_to[16384];
        
        // ...
        
    } clusterState;

    在custerState有三个结构需要认真了解的,第一个是slots数组,clusterState中的slots数组与clsuterNode中的slots数组是不一样的,在clusterNode中slots数组记录的是当前clusterNode所负责的槽,而clusterState中的slots数组记录的是整个集群的每个槽由哪个clsuterNode负责,因此集群正常工作的时候clusterState的slots数组每个索引指向负责该槽的clusterNode,集群槽未分配之前指向null。

    如图展示资源清单中的集群clusterState中的slots数组与clsuterNode中的slots数组:

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    Redis集群中使用两个slots数组的原因是出于性能的考虑:

    • 当我们需要获取整个集群中clusterNode分别负责什么槽时,只需要查询clusterState中的slots数组即可。如果没有clusterState的slots数组,则需要遍历所有的clusterNode结构,这样显然要慢一些

    • 此外clusterNode中的slots数组也有存在的必要,因为集群中任意一个节点之间需要知道彼此负责的槽,此时节点之间只需要互相传输clusterNode中的slots数组结构就行。

    第二个需要认真了解的结构是node字典,该结构虽然简单,但是node字典中存储了所有的clusterNode,这也是Redis集群中的单个节点获取其他主节点、从节点信息的主要位置,因此我们也需要注意一下。 第三个需要认真了解的结构是importing_slots_from[16384]数组和migrating_slots_to[16384],这两个数组在集群重新分片时需要使用,需要重点了解,后面再说吧,这里说的话顺序不太对。

    3. Clusterarbeit

    3.1 Wie verteile ich Slots?

    Der Redis-Cluster verfügt über insgesamt 16384 Slots. Wie in der Ressourcenliste oben gezeigt, befinden wir uns in einem Cluster mit drei Mastern und drei Slaves. Das habe ich jedoch nicht gesehen Ich habe es während des Bereitstellungsprozesses der drei Master und drei Slaves oben angegeben. Dies liegt daran, dass der Redis-Cluster die Slots intern für uns aufgeteilt hat , wie sollen wir sie organisieren? Wir können den folgenden Befehl an den Knoten senden, um dem aktuellen Knoten einen oder mehrere Slots zuzuweisen:

    CLUSTER ADDSLOTS

    Wenn wir beispielsweise Master[0] die Slots 0 und 1 zuweisen möchten, müssen wir nur Ich muss an Master [0] denken. Der Knoten kann den folgenden Befehl senden:

    CLUSTER ADDSLOTS 0 1

    Wenn dem Knoten ein Steckplatz zugewiesen wird, wird das Slot-Array von ClusterNode aktualisiert und der Knoten wird aktualisiert Die Slots, für deren Verarbeitung das Slots-Array verantwortlich ist, werden an andere Knoten im Cluster gesendet. Nach dem Empfang der Nachricht aktualisieren andere Knoten das Slots-Array des entsprechenden ClusterNode und das Solts-Array des ClusterState.

    3.2 Wie wird ADDSLOTS im Redis-Cluster implementiert?

    Das ist eigentlich relativ einfach. Wenn wir den Befehl CLUSTER ADDSLOTS an einen Knoten im Redis-Cluster senden, bestätigt der aktuelle Knoten zunächst, ob die dem aktuellen Knoten zugewiesenen Slots nicht anderen Knoten über das Slot-Array in ClusterState zugewiesen sind. Wenn es zugewiesen wurde, wird direkt eine Ausnahme ausgelöst und der Fehler wird an den zugewiesenen Client zurückgegeben. Wenn nicht alle dem aktuellen Knoten zugewiesenen Slots anderen Knoten zugewiesen sind, weist der aktuelle Knoten diese Slots sich selbst zu. Es gibt drei Hauptschritte bei der Zuweisung:

    • Aktualisieren Sie das Slots-Array von ClusterState, verweisen Sie die angegebenen Slot-Slots[i] auf den aktuellen ClusterNode

    • Aktualisieren Sie das Slots-Array von ClusterNode, aktualisieren Sie den Wert an den angegebenen Slots[ i] bis 1

    • Senden Sie Nachrichten an andere Knoten im Cluster und senden Sie das Slots-Array von ClusterNode an andere Knoten. Nach dem Empfang der Nachricht aktualisieren andere Knoten auch das entsprechende Slots-Array von ClusterState und das Slots-Array von ClusterNode

    3.3 Es gibt so viele Knoten im Cluster. Woher weiß der Client, welchen Knoten er anfordern muss?

    Bevor Sie dieses Problem verstehen, müssen Sie zunächst einen Punkt wissen: Wie berechnet der Redis-Cluster, zu welchem ​​Steckplatz der aktuelle Schlüssel gehört? Laut der offiziellen Website verwendet Redis eigentlich keinen konsistenten Hash-Algorithmus, sondern jeder angeforderte Schlüssel wird von CRC16 überprüft und dann Modulo 16384 verwendet, um zu bestimmen, in welchem ​​Slot er platziert werden soll.

    HASH_SLOT = CRC16(key) mod 16384

    Wenn sich der Client zu diesem Zeitpunkt verbindet, um eine Anfrage an einen Knoten zu senden, berechnet der Knoten, der gerade den Befehl empfängt, zunächst den Steckplatz i, zu dem der aktuelle Schlüssel gehört Durch einen Algorithmus bestimmt der aktuelle Knoten, ob der Slot i des ClusterState für sich selbst verantwortlich ist. Wenn er dafür verantwortlich ist, antwortet der aktuelle Knoten auf die Anfrage des Clients Für den aktuellen Knoten werden die folgenden Schritte ausgeführt:

    • Der Knoten gibt einen MOVED-Umleitungsfehler an den Client zurück. Beim MOVED-Umleitungsfehler werden die berechnete IP und der Port des ClusterNode zurückgegeben, der den Schlüssel korrekt verarbeitet an den Client

    • Wenn der Client den vom Knoten zurückgegebenen MOVED-Umleitungsfehler empfängt, wird der Befehl basierend auf der IP und dem Port an den richtigen Knoten weitergeleitet. Der gesamte Prozess ist für den Programmierer transparent und wird gemeinsam vom Knoten abgeschlossen Server und Client des Redis-Clusters.

    3.4 Was passiert, wenn ich den dem Knoten A zugewiesenen Steckplatz dem Knoten B neu zuweisen möchte?

    Diese Frage deckt tatsächlich viele Probleme ab, z. B. das Entfernen bestimmter Knoten im Redis-Cluster, das Hinzufügen von Knoten usw. Sie kann als Verschieben des Hash-Slots von einem Knoten auf einen anderen Knoten zusammengefasst werden. Und das Coolste am Redis-Cluster ist, dass er die Online-Zuweisung (ununterbrochen) unterstützt, was offiziell als Cluster-Online-Rekonfiguration (Live-Rekonfiguration) bezeichnet wird.

    Schauen wir uns die CLUSTER-Anweisungen an, bevor wir sie implementieren. Sobald Sie die Anweisungen verstanden haben, können Sie sie bedienen:

    • CLUSTER ADDSLOTS Slot1 [Slot2] … [SlotN]

    • CLUSTER DELSLOTS Slot1 [. Slot2] … [SlotN]

    • CLUSTER SETSLOT Slot NODE Knoten

    • CLUSTER SETSLOT Slot MIGRATING Knoten

    • CLUSTER SETSLOT Slot IMPORTING Knoten

    CLUSTER 用于槽分配的指令主要有如上这些,ADDSLOTS 和DELSLOTS主要用于槽的快速指派和快速删除,通常我们在集群刚刚建立的时候进行快速分配的时候才使用。CLUSTER SETSLOT slot NODE node也用于直接给指定的节点指派槽。如果集群已经建立我们通常使用最后两个来重分配,其代表的含义如下所示:

    • 当一个槽被设置为 MIGRATING,原来持有该哈希槽的节点仍会接受所有跟这个哈希槽有关的请求,但只有当查询的键还存在原节点时,原节点会处理该请求,否则这个查询会通过一个 -ASK 重定向(-ASK redirection)转发到迁移的目标节点。

    • 当一个槽被设置为 IMPORTING,只有在接受到 ASKING 命令之后节点才会接受所有查询这个哈希槽的请求。如果客户端一直没有发送 ASKING 命令,那么查询都会通过 -MOVED 重定向错误转发到真正处理这个哈希槽的节点那里。

    上面这两句话是不是感觉不太看的懂,这是官方的描述,不太懂的话我来给你通俗的描述,整个流程大致如下步骤:

    • redis-trib(集群管理软件redis-trib会负责Redis集群的槽分配工作),向目标节点(槽导入节点)发送CLUSTER SETSLOT slot IMPORTING node命令,目标节点会做好从源节点(槽导出节点)导入槽的准备工作。

    • redis-trib随即向源节点发送CLUSTER SETSLOT slot MIGRATING node命令,源节点会做好槽导出准备工作

    • redis-trib随即向源节点发送CLUSTER GETKEYSINSLOT slot count命令,源节点接收命令后会返回属于槽slot的键,最多返回count个键

    • redis-trib会根据源节点返回的键向源节点依次发送MIGRATE ip port key 0 timeout命令,如果key在源节点中,将会迁移至目标节点。

    • 迁移完成之后,redis-trib会向集群中的某个节点发送CLUSTER SETSLOT slot NODE node命令,节点接收到命令后会更新clusterNode和clusterState结构,然后节点通过消息传播槽的指派信息,至此集群槽迁移工作完成,且集群中的其他节点也更新了新的槽分配信息。

    3.5 如果客户端访问的key所属的槽正在迁移怎么办?

    优秀的你总会想到这种并发情况,牛皮呀!大佬们!

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    这个问题官方也考虑了,还记得我们在聊clusterState结构的时候么?importing_slots_from和migrating_slots_to就是用来处理这个问题的。

    typedef struct clusterState {
    
        // ...
        
        // 用于槽的重新分配——记录当前节点正在从其他节点导入的槽
        clusterNode *importing_slots_from[16384];
        
        // 用于槽的重新分配——记录当前节点正在迁移至其他节点的槽
        clusterNode *migrating_slots_to[16384];
        
        // ...
        
    } clusterState;
    • 当节点正在导出某个槽,则会在clusterState中的migrating_slots_to数组对应的下标处设置其指向对应的clusterNode,这个clusterNode会指向导入的节点。

    • 当节点正在导入某个槽,则会在clusterState中的importing_slots_from数组对应的下标处设置其指向对应的clusterNode,这个clusterNode会指向导出的节点。

    有了上述两个相互数组,就能判断当前槽是否在迁移了,而且从哪里迁移来,要迁移到哪里去?搞笑不就是这么简单……

    此时,回到问题中,如果客户端请求的key刚好属于正在迁移的槽。那么接收到命令的节点首先会尝试在自己的数据库中查找键key,如果这个槽还没迁移完成,且当前key刚好也还没迁移完成,那就直接响应客户端的请求就行。如果该key已经不在了,此时节点会去查询migrating_slots_to数组对应的索引槽,如果索引处的值不为null,而是指向了某个clusterNode结构,那说明这个key已经被迁移到这个clusterNode了。这个时候节点不会继续在处理指令,而是返回ASKING命令,这个命令也会携带导入槽clusterNode对应的ip和port。客户端在接收到ASKING命令之后就需要将请求转向正确的节点了,不过这里有一点需要注意的地方**(因此我放个表情包在这里,方便读者注意)。**

    Führen Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis

    Wie bereits erwähnt, gibt ein Knoten die MOVED-Anweisung zurück, wenn er feststellt, dass der aktuelle Slot nicht zu seiner eigenen Verarbeitung gehört. Wie geht er also mit dem zu migrierenden Slot um? Dafür ist dieser Redis-Cluster gedacht. Wenn der Knoten erkennt, dass der Slot migriert wird, gibt er einen ASKING-Befehl an den Client zurück. Der Client erhält den ASKING-Befehl, der die Knoten-IP und den Port des ClusterNode enthält, zu dem der Slot migriert wird. Dann sendet der Client zunächst einen ASKING-Befehl an den migrierenden ClusterNode. Der Zweck dieses Befehls muss darin bestehen, dem aktuellen Knoten mitzuteilen, dass Sie eine Ausnahme machen müssen, um diese Anfrage zu bearbeiten, da dieser Slot zu Ihnen migriert wurde und Sie dies nicht können lehne mich direkt ab ( Wenn Redis den ASKING-Befehl nicht erhält, fragt es den ClusterState des Knotens direkt ab, und der zu migrierende Slot wurde nicht auf den ClusterState aktualisiert, sodass er nur MOVED direkt zurückgeben kann, was zu einer weiteren Schleife führt viele Male...), empfangen Der Knoten mit dem ASKING-Befehl führt diese Anforderung einmal zwangsweise aus (nur einmal, und Sie müssen den ASKING-Befehl beim nächsten Mal erneut im Voraus senden).

    4. Cluster-Fehler

    Redis-Cluster-Fehler sind eigentlich ähnlich wie bei Sentinel, wenn der Master-Knoten ausfällt oder nicht innerhalb der angegebenen maximalen Zeit antwortet und ein neuer Master-Knoten wiedergewählt wird die Slave-Knoten. Die Voraussetzung ist natürlich, dass wir für jeden Masterknoten im Redis-Cluster im Voraus einen Slave-Knoten eingerichtet haben, sonst ist er nutzlos ... Die allgemeinen Schritte sind wie folgt:

    • In einem normal funktionierenden Cluster sendet jeder Knoten regelmäßig PING-Befehle an andere Knoten. Wenn der Knoten, der den Befehl empfängt, innerhalb der angegebenen Zeit keine PONG-Nachricht zurücksendet, sendet der aktuelle Knoten Der PING-Befehl an den Knoten, der den Befehl empfängt, ist auf REDIS_NODE_PFAIL gesetzt, es wird jedoch vermutet, dass er offline ist.

    • Der Clusterknoten benachrichtigt andere Knoten, indem er Nachrichten über die Statusinformationen jedes Knotens im Cluster sendet.

    • Wenn mehr als die Hälfte der Masterknoten im Cluster, die für die Verarbeitung von Slots verantwortlich sind, einen bestimmten Masterknoten wie vermutet festlegen offline , dann wird dieser Knoten als offline markiert und der Knoten setzt die Flags des Clusterknotens, der den Befehl empfängt, auf REDIS_NODE_FAIL. Dies zeigt an, dass er offline ist

    • Der Clusterknoten informiert andere Knoten, indem er Nachrichten sendet Cluster Die Statusinformationen jedes Knotens im Offline-Knoten. Zu diesem Zeitpunkt stellt der Slave-Knoten des Offline-Knotens fest, dass sein Master-Knoten als offline markiert wurde, sodass es an der Zeit ist, vorwärts zu gehen Der Slave-Knoten des Offline-Master-Knotens wird einen Slave-Knoten als neuesten Master-Knoten erstellen und den ausgewählten Knoten ausführen, um SLAVEOF niemanden zum neuen Master-Knoten zu zeigen

    • Der neue Master-Knoten widerruft die Slot-Zuweisungen des ursprünglichen Master-Knotens und ändert diese Slots Zuweisungen an sich selbst. Das heißt, die ClusterNode-Struktur und die ClusterState-Struktur zu ändern. Der neue Masterknoten sendet eine PONG-Anweisung an den Cluster. Andere Knoten wissen, dass ein neuer Masterknoten generiert wurde, und aktualisieren die ClusterNode-Struktur und die ClusterState-Struktur

    • der neue Masterknoten Wenn eine neue SLAVEOF-Anweisung an die verbleibenden Slaveknoten des ursprünglichen Masterknotens gesendet wird, wird dieser zu seinem eigenen Slaveknoten

    • Der letzte neue Masterknoten ist für die Antwortarbeit des verantwortlich Slot des ursprünglichen Master-Knotens

    • Ich habe hier sehr viel geschrieben Fuzzy, wenn Sie eine detaillierte Ausgrabung benötigen, müssen Sie diesen Artikel lesen:

    • REDIS Cluster-Spec – Redis Chinese Information Station – Redis China User Group (CRUG )

      http://redis.cn/topics/cluster- spec.html

    Oder Sie können das Buch „Redis Design and Implementation“ von Huang Jianhong lesen. Dieses Buch ist sehr gut, und ich habe auch auf a verwiesen viel Inhalt.

    Weitere Kenntnisse zum Thema Programmierung finden Sie unter:

    Programmiervideos

    ! !

Das obige ist der detaillierte Inhalt vonFühren Sie Sie durch die Master-Slave-Replikation, Sentinel und Clustering in Redis. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:csdn.net. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen