mirror of
https://github.com/redis/redis.git
synced 2026-10-28 08:25:04 +08:00
CLUSTER RESET on a replica: propagate the flush to the AOF and sub-replicas
CLUSTER RESET turns a replica into an empty master: clusterReset() calls replicationUnsetMaster() and then emptyData(). emptyData() only empties memory; nothing is written to the AOF or to the replication stream. So: - The AOF still holds the old dataset. When the node next restarts from it, the old keys come back, although the node was reset to empty (and, being a master now, it may later own slots those keys don't belong to). - Sub-replicas keep their link across replicationUnsetMaster() (the replid is shifted, not reset), so they keep the old dataset too. Fix: after emptyData(), propagate a FLUSHALL (AOF + replication), as FLUSHALL itself would. CLUSTER RESET runs as a command, so it is propagated when the command completes (also inside MULTI/EXEC). Tests: - tests/unit/cluster/cluster-reset-aof.tcl: a replica with an AOF is reset and restarted from its AOF; its dataset must stay empty. Without the fix all its keys come back. - tests/unit/cluster/resharding.tcl: verify that the masters hold exactly the test's keys (sum of DBSIZE), not just that those keys hold the right values, before and after the AOF restart. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
194a599a50
commit
fa40a99cda
2 files changed
+21
No files matched your search
@@ -1092,6 +1092,13 @@ void clusterReset(int hard) {
|
||||
clusterSetNodeAsMaster(myself);
|
||||
replicationUnsetMaster();
|
||||
emptyData(-1,EMPTYDB_NO_FLAGS,NULL);
|
||||
/* emptyData() only empties memory. Propagate a FLUSHALL so that the AOF
|
||||
* (which would otherwise resurrect the old dataset on restart) and any
|
||||
* sub-replicas (which keep their link across replicationUnsetMaster) are
|
||||
* emptied too. */
|
||||
robj *flushall = createStringObject("FLUSHALL",8);
|
||||
alsoPropagate(-1,&flushall,1,PROPAGATE_AOF|PROPAGATE_REPL);
|
||||
decrRefCount(flushall);
|
||||
}
|
||||
|
||||
/* Close slots, reset manual failover state. */
|
||||
|
||||
@@ -111,6 +111,18 @@ test "Cluster consistency during live resharding" {
|
||||
}
|
||||
}
|
||||
|
||||
# The masters must hold exactly our logical content: checking only our keys would
|
||||
# miss leftovers, e.g. an old dataset resurrected by an AOF restart.
|
||||
proc verify_no_extra_keys {expected} {
|
||||
set total 0
|
||||
for {set id 0} {$id < [llength $::servers]} {incr id} {
|
||||
if {[lindex [R $id role] 0] eq {master}} {
|
||||
incr total [R $id dbsize]
|
||||
}
|
||||
}
|
||||
assert_equal $expected $total
|
||||
}
|
||||
|
||||
test "Verify $numkeys keys for consistency with logical content" {
|
||||
# Check that the Redis Cluster content matches our logical content.
|
||||
foreach {key value} [array get content] {
|
||||
@@ -118,6 +130,7 @@ test "Verify $numkeys keys for consistency with logical content" {
|
||||
fail "Key $key expected to hold '$value' but actual content is [$cluster lrange $key 0 -1]"
|
||||
}
|
||||
}
|
||||
verify_no_extra_keys [array size content]
|
||||
}
|
||||
|
||||
test "Terminate and restart all the instances" {
|
||||
@@ -141,6 +154,7 @@ test "Verify $numkeys keys after the restart" {
|
||||
fail "Key $key expected to hold '$value' but actual content is [$cluster lrange $key 0 -1]"
|
||||
}
|
||||
}
|
||||
verify_no_extra_keys [array size content]
|
||||
}
|
||||
|
||||
test "Disable AOF in all the instances" {
|
||||
|
||||
Reference in new issue
Block a user