From 34f7c653d54e428bed3a6fc686f9612ccbbdd348 Mon Sep 17 00:00:00 2001 From: antirez Date: Tue, 3 Mar 2020 14:58:11 +0100 Subject: [PATCH] Remove RDB files used for replication in persistence-less instances. Former-commit-id: b323645227a3e2cc5928e649586221aba508b10d --- src/replication.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++- src/server.cpp | 8 ++++++++ src/server.h | 1 + 3 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/replication.cpp b/src/replication.cpp index 1edbb9b06..3d0cafc56 100644 --- a/src/replication.cpp +++ b/src/replication.cpp @@ -53,6 +53,11 @@ void putSlaveOnline(client *replica); int cancelReplicationHandshake(redisMaster *mi); static void propagateMasterStaleKeys(); +/* We take a global flag to remember if this instance generated an RDB + * because of replication, so that we can remove the RDB file in case + * the instance is configured to have no persistence. */ +int RDBGeneratedByReplication = 0; + /* --------------------------- Utility functions ---------------------------- */ /* Return the pointer to a string representing the replica ip:listening_port @@ -789,6 +794,10 @@ int startBgsaveForReplication(int mincapa) { retval = C_ERR; } + /* If we succeeded to start a BGSAVE with disk target, let's remember + * this fact, so that we can later delete the file if needed. */ + if (retval == C_OK && !socket_target) RDBGeneratedByReplication = 1; + /* If we failed to BGSAVE, remove the slaves waiting for a full * resynchronization from the list of slaves, inform them with * an error about what happened, close the connection ASAP. */ @@ -1132,6 +1141,36 @@ void putSlaveOnline(client *replica) { } } +/* We call this function periodically to remove an RDB file that was + * generated because of replication, in an instance that is otherwise + * without any persistence. We don't want instances without persistence + * to take RDB files around, this violates certain policies in certain + * environments. */ +void removeRDBUsedToSyncReplicas(void) { + if (allPersistenceDisabled() && RDBGeneratedByReplication) { + client *slave; + listNode *ln; + listIter li; + + int delrdb = 1; + listRewind(server.slaves,&li); + while((ln = listNext(&li))) { + slave = ln->value; + if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START || + slave->replstate == SLAVE_STATE_WAIT_BGSAVE_END || + slave->replstate == SLAVE_STATE_SEND_BULK) + { + delrdb = 0; + break; /* No need to check the other replicas. */ + } + } + if (delrdb) { + RDBGeneratedByReplication = 0; + unlink(server.rdb_filename); + } + } +} + void sendBulkToSlave(connection *conn) { client *replica = (client*)connGetPrivateData(conn); serverAssert(FCorrectThread(replica)); @@ -1144,7 +1183,8 @@ void sendBulkToSlave(connection *conn) { if (replica->replpreamble) { nwritten = connWrite(conn,replica->replpreamble,sdslen(replica->replpreamble)); if (nwritten == -1) { - serverLog(LL_VERBOSE,"Write error sending RDB preamble to replica: %s", + serverLog(LL_VERBOSE, + "Write error sending RDB preamble to replica: %s", connGetLastError(conn)); freeClient(replica); return; @@ -1985,12 +2025,14 @@ void readSyncBulkPayload(connection *conn) { "Failed trying to load the MASTER synchronization " "DB from disk"); cancelReplicationHandshake(mi); + if (allPersistenceDisabled()) unlink(g_pserver->rdb_filename); /* Note that there's no point in restarting the AOF on sync failure, it'll be restarted when sync succeeds or replica promoted. */ return; } /* Cleanup. */ + if (allPersistenceDisabled()) unlink(server.rdb_filename); if (fUpdate) unlink(mi->repl_transfer_tmpfile); zfree(mi->repl_transfer_tmpfile); @@ -3684,6 +3726,11 @@ void replicationCron(void) { propagateMasterStaleKeys(); + + /* Remove the RDB file used for replication if Redis is not running + * with any persistence. */ + removeRDBUsedToSyncReplicas(); + /* Refresh the number of slaves with lag <= min-slaves-max-lag. */ refreshGoodSlavesCount(); replication_cron_loops++; /* Incremented with frequency 1 HZ. */ diff --git a/src/server.cpp b/src/server.cpp index 874d391c6..30f4f4099 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1483,12 +1483,20 @@ void updateDictResizePolicy(void) { dictDisableResize(); } +/* Return true if there are no active children processes doing RDB saving, + * AOF rewriting, or some side process spawned by a loaded module. */ int hasActiveChildProcess() { return g_pserver->rdb_child_pid != -1 || g_pserver->aof_child_pid != -1 || g_pserver->module_child_pid != -1; } +/* Return true if this instance has persistence completely turned off: + * both RDB and AOF are disabled. */ +int allPersistenceDisabled(void) { + return server.saveparamslen == 0 && server.aof_state == AOF_OFF; +} + /* ======================= Cron: called every 100 ms ======================== */ /* Add a sample to the operations per second array of samples. */ diff --git a/src/server.h b/src/server.h index b8a11e888..b9bd9b7c4 100644 --- a/src/server.h +++ b/src/server.h @@ -2357,6 +2357,7 @@ void loadingProgress(off_t pos); void stopLoading(int success); void startSaving(int rdbflags); void stopSaving(int success); +int allPersistenceDisabled(void); #define DISK_ERROR_TYPE_AOF 1 /* Don't accept writes: AOF errors. */ #define DISK_ERROR_TYPE_RDB 2 /* Don't accept writes: RDB errors. */