Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/cluster_migrateslots.c
Original file line number Diff line number Diff line change
Expand Up @@ -1583,6 +1583,15 @@ int childSnapshotForSyncSlot(rio *aof, slotMigrationJob *job) {
void killSlotMigrationChild(void) {
/* No slot migration child? return. */
if (server.child_type != CHILD_TYPE_SLOT_MIGRATION) return;

/* If we already closed the exit pipe, the child is already exiting.
* Sending SIGUSR1 now might cause a race condition/deadlock in the child,
* especially when compiled with coverage. */
if (server.slot_migration_child_exit_pipe == -1) {
serverLog(LL_NOTICE, "Slot migration child %ld is already exiting, not killing.", (long)server.child_pid);
return;
}

serverLog(LL_NOTICE, "Killing running slot migration child: %ld", (long)server.child_pid);

/* Because we are not using here waitpid (like we have in killAppendOnlyChild
Expand Down Expand Up @@ -2051,15 +2060,19 @@ void proceedWithSlotMigration(slotMigrationJob *job) {
* resulting in premature flush of the output buffer and data
* consistency issues. To prevent this, we defer snapshot until
* there are no pending writes. */
if (hasActiveChildProcess() || job->client->flag.pending_write) {
if (hasActiveChildProcess() || job->client->flag.pending_write ||
job->client->io_write_state != CLIENT_IDLE ||
job->client->io_read_state != CLIENT_IDLE) {
run_with_period(5000) {
serverLog(LL_NOTICE,
"Slot migration %s waiting before snapshotting "
"due to %s.",
job->description,
hasActiveChildProcess()
? "active child process"
: "pending writes in output buffer");
: (job->client->flag.pending_write
? "pending writes in output buffer"
: "pending IO operations"));
}
return;
}
Expand Down
6 changes: 6 additions & 0 deletions src/io_threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

#include "io_threads.h"
#include "cluster_migrateslots.h"
#include "queues.h"
#include <sys/resource.h>

Expand Down Expand Up @@ -545,6 +546,11 @@ int trySendWriteToIOThreads(client *c) {
if (getClientType(c) == CLIENT_TYPE_REPLICA && c->repl_data->repl_state != REPLICA_STATE_ONLINE) return C_ERR;
/* We can't offload debugged clients as the main-thread may read at the same time */
if (c->flag.lua_debug) return C_ERR;
/* Avoid offloading writes to IO thread for the slot migration export job while snapshotting.
* During this phase, replies accumulate in the output buffer but must not be flushed
* as concurrent IO thread writes would race with the main thread processing incoming
* ACKs on the same client's query buffer. */
if (c->slot_migration_job && !clusterSlotMigrationShouldInstallWriteHandler(c)) return C_ERR;

int is_replica = getClientType(c) == CLIENT_TYPE_REPLICA;
clientReplyBlock *block = NULL;
Expand Down
14 changes: 7 additions & 7 deletions tests/unit/cluster/cluster-migrateslots.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ proc do_node_restart {idx} {
}

# Disable replica migration to prevent empty nodes from joining other shards.
start_cluster 3 3 {tags {logreqres:skip external:skip cluster} overrides {cluster-allow-replica-migration no cluster-node-timeout 15000 cluster-databases 16}} {
start_cluster 3 3 {tags {logreqres:skip external:skip cluster network} overrides {cluster-allow-replica-migration no cluster-node-timeout 15000 cluster-databases 16}} {

set node0_id [R 0 CLUSTER MYID]
set node1_id [R 1 CLUSTER MYID]
Expand Down Expand Up @@ -2138,7 +2138,7 @@ start_cluster 3 3 {tags {logreqres:skip external:skip cluster} overrides {cluste
}
}

start_cluster 3 0 {tags {logreqres:skip external:skip cluster}} {
start_cluster 3 0 {tags {logreqres:skip external:skip cluster network}} {
set 16383_slot_tag "{6ZJ}"
set node0_id [R 0 CLUSTER MYID]

Expand Down Expand Up @@ -2174,7 +2174,7 @@ start_cluster 3 0 {tags {logreqres:skip external:skip cluster}} {
}
}

start_cluster 3 6 {tags {logreqres:skip external:skip cluster}} {
start_cluster 3 6 {tags {logreqres:skip external:skip cluster network}} {
set node0_id [R 0 CLUSTER MYID]
set node1_id [R 1 CLUSTER MYID]
set node2_id [R 2 CLUSTER MYID]
Expand Down Expand Up @@ -2230,7 +2230,7 @@ start_cluster 3 6 {tags {logreqres:skip external:skip cluster}} {
}
}

start_cluster 3 0 {tags {logreqres:skip external:skip cluster}} {
start_cluster 3 0 {tags {logreqres:skip external:skip cluster network}} {

set node0_id [R 0 CLUSTER MYID]
set node1_id [R 1 CLUSTER MYID]
Expand Down Expand Up @@ -2295,7 +2295,7 @@ start_cluster 3 0 {tags {logreqres:skip external:skip cluster}} {

}

start_cluster 3 3 {tags {logreqres:skip external:skip cluster aofrw} overrides {appendonly yes auto-aof-rewrite-percentage 0}} {
start_cluster 3 3 {tags {logreqres:skip external:skip cluster aofrw network} overrides {appendonly yes auto-aof-rewrite-percentage 0}} {
set node0_id [R 0 CLUSTER MYID]
set node1_id [R 1 CLUSTER MYID]
set node2_id [R 2 CLUSTER MYID]
Expand Down Expand Up @@ -2445,7 +2445,7 @@ start_cluster 3 3 {tags {logreqres:skip external:skip cluster aofrw} overrides {
}
}

start_cluster 3 0 {tags {logreqres:skip external:skip cluster} overrides {cluster-require-full-coverage no slot-migration-max-failover-repl-bytes 0}} {
start_cluster 3 0 {tags {logreqres:skip external:skip cluster network} overrides {cluster-require-full-coverage no slot-migration-max-failover-repl-bytes 0}} {
test "Slot migration remaining_repl_size on the source node" {
set 16383_slot_tag "{6ZJ}"
set_debug_prevent_pause 1
Expand Down Expand Up @@ -2488,7 +2488,7 @@ start_cluster 3 0 {tags {logreqres:skip external:skip cluster} overrides {cluste
}
}

start_cluster 3 0 {tags {logreqres:skip external:skip cluster} overrides {cluster-require-full-coverage no slot-migration-max-failover-repl-bytes -1}} {
start_cluster 3 0 {tags {logreqres:skip external:skip cluster network} overrides {cluster-require-full-coverage no slot-migration-max-failover-repl-bytes -1}} {
test "slot-migration-max-failover-repl-bytes -1 disables repl bytes limit" {
set 16383_slot_tag "{6ZJ}"

Expand Down
Loading