Garnet Cluster Replikation
Garnet Cluster unterstützt asynchrone Replikation nach einem einfachen Leader-Follower (d.h. Primär-Replikat)-Modell. Dies ermöglicht es dem Replikat, exakte Kopien des Primärservers zu sein. Replikation kann genutzt werden, um Leseanfragen zu skalieren und die Auswirkungen von Primärausfällen zu mindern, indem Replikate zu Primärservern befördert werden. Auf dieser Seite geben wir einen Überblick über das Replikationsprotokoll und diskutieren die verschiedenen persistenten/konsistenten Optionen, die dem Cluster-Betreiber zur Verfügung stehen.
Garnet Replikationseigenschaften
Garnet Cluster implementiert Replikation durch Log-Shipping. Primärserver verwenden die Append-Only-File (AOF), um Insert/Update-Operationen aufzuzeichnen. Eine dedizierte Hintergrundaufgabe durchläuft die Log-Seiten und überträgt sie in großen Mengen an das entsprechende Replikat. Replikate durchlaufen die empfangenen Log-Seiten, spielen alle Insert/Update-Operationen in der richtigen Reihenfolge ab und generieren ihre eigene AOF. Primärserver können im Allgemeinen willkürliche Checkpoints erstellen. Wenn der Primärserver einen Checkpoint erstellt, fügt er einen Checkpoint-Marker in die AOF ein. Als Nebeneffekt davon wird bei jedem angeschlossenen Replikat, das die entsprechenden Datensätze empfängt, ein eigener Checkpoint ausgelöst. Aus diesem Grund wird eine exakte Version der Daten aus dem folgenden Tripel identifiziert.
[replication-id, checkpoint-version, replication-offset]
Das Ermöglichen von eigenen Checkpoints durch Replikate beschleunigt den Wiederherstellungsprozess, da Replikate im Normalfall von ihrem eigenen Checkpoint wiederherstellen und ihre AOF wiedergeben können, bevor sie sich mit ihrem Primärserver verbinden und die Synchronisierung fortsetzen. In seltenen Fällen muss das Replikat eine vollständige Synchronisierung durchführen, indem es den neuesten Checkpoint vom Primärserver abruft. Teilweise Synchronisierung beinhaltet die Wiederherstellung von einem lokalen Checkpoint (falls vorhanden) und die Wiedergabe des AOF-Logs des Primärservers nur nach dem entsprechenden Checkpoint Covered Replication Offset (CCRO). Vollständige Synchronisierung beinhaltet das Abrufen des neuesten Primär-Checkpoints und die Wiederherstellung von diesem, bevor neue AOF-Log-Datensätze akzeptiert werden.
Das Replikat entscheidet, ob es eine der beiden Synchronisierungsarten durchführt, wie folgt:
- Wenn sich die Primär-Replikations-ID von der Replikat-Replikations-ID unterscheidet, muss eine vollständige Synchronisierung erfolgen.
- Wenn sich die Primär-Checkpoint-Version von der Replikat-Checkpoint-Version unterscheidet, muss eine vollständige Synchronisierung erfolgen.
- Wenn keine der oben genannten Bedingungen zutrifft, kann sich das Replikat von einem lokalen Checkpoint erholen und dann die Wiedergabe von den fehlenden AOF-Offsets fortsetzen.
Replikationsleistung vs. Durabilitätsoptionen
Bei normaler Auslastung wächst das AOF-Log mit jeder Insert/Update-Operation weiter, bis ein Checkpoint erstellt wird. Neu hinzugefügte AOF-Log-Datensätze befinden sich zunächst im Speicher und werden dann auf die Festplatte geleert, während neue Datensätze hinzugefügt werden. Bei schreibintensiven Workloads kann dies die Abfrageleistung auf dem Primärserver erheblich beeinträchtigen. Darüber hinaus können neu konfigurierte Replikate, die dem Cluster hinzugefügt werden, längere Synchronisierungszeiten haben, da sie die AOF-Log-Datensätze ab dem entsprechenden CCRO wiedergeben müssen.
Der Cluster-Betreiber kann zwischen verschiedenen Replikationsoptionen wählen, um einen Kompromiss zwischen Leistung und Durabilität zu erzielen. Eine Zusammenfassung dieser Optionen ist unten aufgeführt.
- Fast AOF Truncation (FAT) Diese Option zwingt den Primärserver, die AOF aggressiv zu kürzen, damit sie nicht auf die Festplatte ausweicht. Sie kann in Kombination mit der aof-memory-Option verwendet werden, die die maximale AOF-Speicherpuffergröße bestimmt. Wenn sich ein Replikat mit eingeschaltetem FAT an einen Primärserver anhängt, ist die AOF nicht garantiert gekürzt, was zu Datenverlusten bei Schreibvorgängen führen kann. Um dieses Problem zu beheben, sollte FAT mit ODC verwendet werden.
- On Demand Checkpoint (ODC) Diese Option zwingt den Primärserver, einen Checkpoint zu erstellen, wenn kein Checkpoint verfügbar ist, wenn ein Replikat versucht, sich anzuhängen und wiederherzustellen. Wenn ein Checkpoint verfügbar ist oder verfügbar war und der CCRO nicht gekürzt wurde, sperrt der Primärserver ihn, um eine Kürzung zu verhindern, während ein Replikat wiederherstellt. In diesem Fall kann das AOF-Log auf die Festplatte ausweichen, wenn der AOF-Speicherpuffer voll wird. Im Normalbetrieb wird die AOF gekürzt und es erfolgt kein Ausweichen auf die Festplatte.
Mit den oben genannten Optionen garantieren wir, dass keine Schreibvorgänge verloren gehen, während sich ein Replikat anhängt und die Replikation hochperformant bleibt. Aufgrund der asynchronen Natur der Replikation können die Replikate jedoch, wenn ein Primärserver unerwartet ausfällt, die neuesten AOF-Log-Datensätze möglicherweise nicht empfangen, was zu Datenverlusten führt.
Erstellen eines Garnet Clusters mit Replikation
Der Prozess der Einrichtung eines Clusters mit Replikation ähnelt der Einrichtung eines regulären Clusters, wobei auch die aof-Option aktiviert wird. Dies sollte für jede Instanz im Cluster erfolgen.
GarnetServer.exe --cluster --checkpointdir='data/' --aof
Die AOF-Log-Datei wird im Ordner checkpointdir gespeichert, der standardmäßig der Arbeitsordner ist. Standardmäßig übernimmt jede Garnet-Instanz die Rolle eines leeren Primärservers. Der Cluster-Betreiber muss zunächst die Slots einem Teil dieser Primärserver zuweisen. Die restlichen Instanzen können durch Verwendung des Befehls CLUSTER REPLICATE in Replikate umgewandelt werden. Ein Beispiel für die Einrichtung eines Clusters mit einem einzelnen Primärserver und 2 Replikaten ist unten gezeigt.
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7000 cluster myid
"15373cf386c5090a5f8a25f819c96b04a756381c"
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7000 cluster addslotsrange 0 16383
OK
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7000 cluster set-config-epoch 1
OK
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7001 cluster set-config-epoch 2
OK
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7002 cluster set-config-epoch 3
OK
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7000 cluster meet 192.168.1.26 7001
OK
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7000 cluster meet 192.168.1.26 7002
OK
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7001 cluster replicate 15373cf386c5090a5f8a25f819c96b04a756381c
OK
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7002 cluster replicate 15373cf386c5090a5f8a25f819c96b04a756381c
OK
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7000 cluster nodes
15373cf386c5090a5f8a25f819c96b04a756381c 192.168.1.26:7000@17000,DESKTOP-BT8KHK1 myself,master - 0 0 1 connected 0-16383
5868649e4205bf6ea97e4b7a12f101c3aed96b71 192.168.1.26:7001@17001,DESKTOP-BT8KHK1 slave 15373cf386c5090a5f8a25f819c96b04a756381c 0 0 4 connected
947692ec7fb4a919ae7d0d7e314e9dcbcbd99774 192.168.1.26:7002@17002,DESKTOP-BT8KHK1 slave 15373cf386c5090a5f8a25f819c96b04a756381c 0 0 5 connected
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7001 cluster nodes
5868649e4205bf6ea97e4b7a12f101c3aed96b71 192.168.1.26:7001@17001,DESKTOP-BT8KHK1 myself,slave 15373cf386c5090a5f8a25f819c96b04a756381c 0 0 4 connected
15373cf386c5090a5f8a25f819c96b04a756381c 192.168.1.26:7000@17000,DESKTOP-BT8KHK1 master - 0 0 1 connected 0-16383
947692ec7fb4a919ae7d0d7e314e9dcbcbd99774 192.168.1.26:7002@17002,DESKTOP-BT8KHK1 slave 15373cf386c5090a5f8a25f819c96b04a756381c 0 0 5 connected
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7002 cluster nodes
947692ec7fb4a919ae7d0d7e314e9dcbcbd99774 192.168.1.26:7002@17002,DESKTOP-BT8KHK1 myself,slave 15373cf386c5090a5f8a25f819c96b04a756381c 0 0 5 connected
15373cf386c5090a5f8a25f819c96b04a756381c 192.168.1.26:7000@17000,DESKTOP-BT8KHK1 master - 0 0 1 connected 0-16383
5868649e4205bf6ea97e4b7a12f101c3aed96b71 192.168.1.26:7001@17001,DESKTOP-BT8KHK1 slave 15373cf386c5090a5f8a25f819c96b04a756381c 0 0 4 connected
Es gibt keine Begrenzung für die Anzahl der an einen bestimmten Primärserver angeschlossenen Replikate. Derzeit unterstützen wir keine gekettete Replikation.
Abfragen eines Replikats
Standardmäßig bedienen Replikate nur Leseabfragen, können aber auch so konfiguriert werden, dass sie Schreibanfragen verarbeiten. Diese Option ist verfügbar, indem der Befehl READWRITE einmal vor der Ausführung einer Schreiboperation in einer einzelnen Client-Sitzung ausgegeben wird. Die Ausgabe von READONLY schaltet zurück zum Bedienen von Leseabfragen.
Wenn ein Replikat für die Verarbeitung von schreibgeschützten Anfragen eingestellt ist, antwortet es mit -MOVED auf alle Schreibanfragen und leitet diese an den Primärserver weiter, den es repliziert.
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7001 -c
192.168.1.26:7001> set x 1234
-> Redirected to slot [16287] located at 192.168.1.26:7000
OK
192.168.1.26:7000> set x 1234
OK
192.168.1.26:7000> get x
"1234"
192.168.1.26:7000> exit
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7001 -c
192.168.1.26:7001> get x
"1234"
192.168.1.26:7001> exit
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7002
192.168.1.26:7002> get x
"1234"
Checkpointing & Wiederherstellung
Wie oben erwähnt, können Primärserver willkürliche Checkpoints erstellen und diese Informationen an die Replikate weitergeben. Replikate identifizieren den Checkpoint-Datensatz in der AOF-Datei und lösen selbst einen Checkpoint aus. Das Erstellen eines Checkpoints auf dem Primärserver ist so einfach wie der Aufruf des SAVE oder BGSAVE Befehls. Nach Abschluss der Checkpoint-Operation wird sie in das AOF-Log geschrieben. Die Replikate empfangen diesen Datensatz und lösen ihren eigenen Checkpoint aus.
Ein Beispiel für die Checkpoint-Weitergabe ist unten gezeigt.
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7000
192.168.1.26:7000> lastsave
(integer) 0
192.168.1.26:7000> bgsave
Background saving started
192.168.1.26:7000> lastsave
(integer) 1706555027
192.168.1.26:7000> exit
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7001
192.168.1.26:7001> lastsave
(integer) 1706555029
192.168.1.26:7001> exit
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7002
192.168.1.26:7002> lastsave
(integer) 1706555028
192.168.1.26:7002>
Replikationsinformationen
Der Systemadministrator kann den Fortschritt der Replikation verfolgen, indem er den Abschnitt mit den Replikationsinformationen mithilfe des Befehls info replication abruft. Eine Zusammenfassung der verfügbaren Felder ist unten aufgeführt.
role: Rolle der abgefragten Instanz connected_slaves: Anzahl der mit der Instanz verbundenen Replikate. master_failover_state: Der Zustand eines laufenden Failovers, falls vorhanden. master_replid: Replikations-ID dieser Garnet-Serverinstanz. master_replid2: sekundäre Replikations-ID (derzeit nicht verwendet). master_repl_offset: aktueller AOF-Offset des Primärservers. store_current_safe_aof_address: AOF-Adresse, die vom neuesten Checkpoint abgedeckt wird. store_recovered_safe_aof_address: AOF-Adresse, die vom wiederhergestellten Checkpoint abgedeckt wird. object_store_current_safe_aof_address: AOF-Adresse, die vom neuesten Checkpoint des Objektspeichers abgedeckt wird. object_store_recovered_safe_aof_address: AOF-Adresse, die vom wiederhergestellten Checkpoint des Objektspeichers abgedeckt wird.
192.168.1.26:7000> info replication
# Replication
role:master
connected_slaves:2
master_failover_state:no-failover
master_replid:dd194cb04b18b31373157e22d0ab36df9cc6a04a
master_replid2:
master_repl_offset:136
second_repl_offset:136
store_current_safe_aof_address:0
store_recovered_safe_aof_address:0
object_store_current_safe_aof_address:0
object_store_recovered_safe_aof_address:0
slave0:ip=192.168.1.26,port=7001,state=online,offset=136,lag=0
slave1:ip=192.168.1.26,port=7002,state=online,offset=136,lag=0
192.168.1.26:7000> exit
PS C:\Dev> redis-cli -h 192.168.1.26 -p 7001
192.168.1.26:7001> info replication
# Replication
role:slave
connected_slaves:0
master_failover_state:no-failover
master_replid:dd194cb04b18b31373157e22d0ab36df9cc6a04a
master_replid2:
master_repl_offset:136
second_repl_offset:136
store_current_safe_aof_address:0
store_recovered_safe_aof_address:0
object_store_current_safe_aof_address:0
object_store_recovered_safe_aof_address:0
master_host:192.168.1.26
master_port:7000
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:False
slave_read_repl_offset:136
slave_priority:100
slave_read_only:1
replica_announced:1
192.168.1.26:7001>
Festplattenlose Replikation
Wenn die AOF gekürzt wird, erfordert die vollständige Synchronisierung das Erstellen eines Checkpoints und das Senden dieses Checkpoints an das anhängende Replikat. Dieser Vorgang kann teuer sein, da er mehrere I/O-Operationen auf dem Primär- und Replikatserver beinhaltet. Aus diesem Grund haben wir eine Variante der vollständigen Synchronisierung namens festplattenlose Replikation hinzugefügt. Diese wird mit einem Streaming-Checkpoint implementiert, der es Clients ermöglicht, Lese- und Schreibvorgänge auf dem Primärserver auszuführen, während sich die anhängenden Replikate synchronisieren. Um festplattenlose Replikation zu aktivieren, muss der Server mit den folgenden Flags gestartet werden:
--repl-diskless-sync=true Wird verwendet, um festplattenlose Replikation zu aktivieren.
--repl-diskless-sync-delay=<sekunden>. Wird verwendet, um festzulegen, wie viele Sekunden gewartet werden muss, bevor die vollständige Synchronisierung beginnt, um mehreren Replikaten die Möglichkeit zu geben, sich anzuhängen und den Streaming-Checkpoint zu empfangen.
Es gibt keine zusätzlichen Anforderungen zu den oben genannten Flags, um die festplattenlose Replikation zu nutzen. Die APIs für die Zuordnung von Replikaten bleiben gleich (d.h. CLUSTER REPLICATE, REPLICAOF usw.).
Beachten Sie, dass die festplattenlose Replikation keinen tatsächlichen Checkpoint erstellt. Daher wird bei jeder vollständigen Synchronisierung die AOF nicht automatisch gekürzt (es sei denn, das FAT-Flag wird verwendet). Dies geschieht, um die Durabilität im Falle eines Ausfalls zu gewährleisten, was nicht möglich wäre, wenn die AOF ohne einen persistenten Checkpoint gekürzt würde. Die Speicherversion wird jedoch inkrementiert, um die Konsistenz über verschiedene Instanzen hinweg zu gewährleisten, die möglicherweise zu unterschiedlichen Zeiten vollständig synchronisiert werden. Benutzer können weiterhin SAVE/BGSAVE-Befehle oder --aof-size-limit verwenden, um periodisch einen Checkpoint zu erstellen und die AOF sicher zu kürzen.