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 (#16038)
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.
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **Medium Risk**
> Touches cluster reset and replication/AOF propagation paths; incorrect
propagation could affect dataset durability or replica state during
failover/reset scenarios.
>
> **Overview**
> Fixes **CLUSTER RESET** on a replica promoted to master: after
`emptyData()` clears memory only, the change **propagates `FLUSHALL`**
via `alsoPropagate` with **AOF and replication** so restarts from AOF
and chained sub-replicas do not keep the old dataset.
>
> **Tests:** `resharding.tcl` adds **`verify_no_extra_keys`** (total
`DBSIZE` across masters must match the logical key count) in the pre-
and post-AOF-restart consistency checks, so ghost keys from a bad AOF
replay are caught.
>
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
fa40a99cda. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
194a599a50
commit
847ff3503a
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