Add module event for repl-diskless-load swapdb (#8153)
When a replica uses the diskless-load swapdb approach, it backs up the old database, then attempts to load a new one, and in case of failure, it restores the backup. this means that modules with global out of keyspace data, must have an option to subscribe to events and backup/restore/discard their global data too.
This commit is contained in:
parent
8a23ca0b28
commit
ab60dcf564
12
src/db.c
12
src/db.c
@ -477,6 +477,10 @@ dbBackup *backupDb(void) {
|
||||
sizeof(server.cluster->slots_keys_count));
|
||||
}
|
||||
|
||||
moduleFireServerEvent(REDISMODULE_EVENT_REPL_BACKUP,
|
||||
REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE,
|
||||
NULL);
|
||||
|
||||
return backup;
|
||||
}
|
||||
|
||||
@ -498,6 +502,10 @@ void discardDbBackup(dbBackup *buckup, int flags, void(callback)(void*)) {
|
||||
/* Release buckup. */
|
||||
zfree(buckup->dbarray);
|
||||
zfree(buckup);
|
||||
|
||||
moduleFireServerEvent(REDISMODULE_EVENT_REPL_BACKUP,
|
||||
REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* Restore the previously created backup (discarding what currently resides
|
||||
@ -526,6 +534,10 @@ void restoreDbBackup(dbBackup *buckup) {
|
||||
/* Release buckup. */
|
||||
zfree(buckup->dbarray);
|
||||
zfree(buckup);
|
||||
|
||||
moduleFireServerEvent(REDISMODULE_EVENT_REPL_BACKUP,
|
||||
REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
int selectDb(client *c, int id) {
|
||||
|
16
src/module.c
16
src/module.c
@ -7350,7 +7350,7 @@ void ModuleForkDoneHandler(int exitcode, int bysignal) {
|
||||
*
|
||||
* RedisModuleEvent_SwapDB
|
||||
*
|
||||
* This event is called when a swap db command has been successfully
|
||||
* This event is called when a SWAPDB command has been successfully
|
||||
* Executed.
|
||||
* For this event call currently there is no subevents available.
|
||||
*
|
||||
@ -7360,6 +7360,18 @@ void ModuleForkDoneHandler(int exitcode, int bysignal) {
|
||||
* int32_t dbnum_first; // Swap Db first dbnum
|
||||
* int32_t dbnum_second; // Swap Db second dbnum
|
||||
*
|
||||
* RedisModuleEvent_ReplBackup
|
||||
*
|
||||
* Called when diskless-repl-load config is set to swapdb,
|
||||
* And redis needs to backup the the current database for the
|
||||
* possibility to be restored later. A module with global data and
|
||||
* maybe with aux_load and aux_save callbacks may need to use this
|
||||
* notification to backup / restore / discard its globals.
|
||||
* The following sub events are available:
|
||||
*
|
||||
* REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE
|
||||
* REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE
|
||||
* REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD
|
||||
*
|
||||
*
|
||||
* The function returns REDISMODULE_OK if the module was successfully subscribed
|
||||
@ -7432,6 +7444,8 @@ int RM_IsSubEventSupported(RedisModuleEvent event, int64_t subevent) {
|
||||
return subevent < _REDISMODULE_SUBEVENT_LOADING_PROGRESS_NEXT;
|
||||
case REDISMODULE_EVENT_SWAPDB:
|
||||
return subevent < _REDISMODULE_SUBEVENT_SWAPDB_NEXT;
|
||||
case REDISMODULE_EVENT_REPL_BACKUP:
|
||||
return subevent < _REDISMODULE_SUBEVENT_REPL_BACKUP_NEXT;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -215,9 +215,10 @@ typedef uint64_t RedisModuleTimerID;
|
||||
#define REDISMODULE_EVENT_MODULE_CHANGE 9
|
||||
#define REDISMODULE_EVENT_LOADING_PROGRESS 10
|
||||
#define REDISMODULE_EVENT_SWAPDB 11
|
||||
#define REDISMODULE_EVENT_REPL_BACKUP 12
|
||||
|
||||
/* Next event flag, should be updated if a new event added. */
|
||||
#define _REDISMODULE_EVENT_NEXT 12
|
||||
#define _REDISMODULE_EVENT_NEXT 13
|
||||
|
||||
typedef struct RedisModuleEvent {
|
||||
uint64_t id; /* REDISMODULE_EVENT_... defines. */
|
||||
@ -276,6 +277,10 @@ static const RedisModuleEvent
|
||||
RedisModuleEvent_SwapDB = {
|
||||
REDISMODULE_EVENT_SWAPDB,
|
||||
1
|
||||
},
|
||||
RedisModuleEvent_ReplBackup = {
|
||||
REDISMODULE_EVENT_REPL_BACKUP,
|
||||
1
|
||||
};
|
||||
|
||||
/* Those are values that are used for the 'subevent' callback argument. */
|
||||
@ -317,11 +322,15 @@ static const RedisModuleEvent
|
||||
#define REDISMODULE_SUBEVENT_MODULE_UNLOADED 1
|
||||
#define _REDISMODULE_SUBEVENT_MODULE_NEXT 2
|
||||
|
||||
|
||||
#define REDISMODULE_SUBEVENT_LOADING_PROGRESS_RDB 0
|
||||
#define REDISMODULE_SUBEVENT_LOADING_PROGRESS_AOF 1
|
||||
#define _REDISMODULE_SUBEVENT_LOADING_PROGRESS_NEXT 2
|
||||
|
||||
#define REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE 0
|
||||
#define REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE 1
|
||||
#define REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD 2
|
||||
#define _REDISMODULE_SUBEVENT_REPL_BACKUP_NEXT 3
|
||||
|
||||
#define _REDISMODULE_SUBEVENT_SHUTDOWN_NEXT 0
|
||||
#define _REDISMODULE_SUBEVENT_CRON_LOOP_NEXT 0
|
||||
#define _REDISMODULE_SUBEVENT_SWAPDB_NEXT 0
|
||||
|
@ -13,6 +13,45 @@ RedisModuleType *testrdb_type = NULL;
|
||||
RedisModuleString *before_str = NULL;
|
||||
RedisModuleString *after_str = NULL;
|
||||
|
||||
void replBackupCallback(RedisModuleCtx *ctx, RedisModuleEvent e, uint64_t sub, void *data)
|
||||
{
|
||||
REDISMODULE_NOT_USED(e);
|
||||
REDISMODULE_NOT_USED(data);
|
||||
static RedisModuleString *before_str_backup = NULL;
|
||||
static RedisModuleString *after_str_backup = NULL;
|
||||
|
||||
switch (sub) {
|
||||
case REDISMODULE_SUBEVENT_REPL_BACKUP_CREATE:
|
||||
assert(before_str_backup == NULL);
|
||||
assert(after_str_backup == NULL);
|
||||
before_str_backup = before_str;
|
||||
after_str_backup = after_str;
|
||||
before_str = NULL;
|
||||
after_str = NULL;
|
||||
break;
|
||||
case REDISMODULE_SUBEVENT_REPL_BACKUP_RESTORE:
|
||||
if (before_str)
|
||||
RedisModule_FreeString(ctx, before_str);
|
||||
if (after_str)
|
||||
RedisModule_FreeString(ctx, after_str);
|
||||
before_str = before_str_backup;
|
||||
after_str = after_str_backup;
|
||||
before_str_backup = NULL;
|
||||
after_str_backup = NULL;
|
||||
break;
|
||||
case REDISMODULE_SUBEVENT_REPL_BACKUP_DISCARD:
|
||||
if (before_str_backup)
|
||||
RedisModule_FreeString(ctx, before_str_backup);
|
||||
if (after_str_backup)
|
||||
RedisModule_FreeString(ctx, after_str_backup);
|
||||
before_str_backup = NULL;
|
||||
after_str_backup = NULL;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void *testrdb_type_load(RedisModuleIO *rdb, int encver) {
|
||||
int count = RedisModule_LoadSigned(rdb);
|
||||
RedisModuleString *str = RedisModule_LoadString(rdb);
|
||||
@ -247,6 +286,9 @@ int RedisModule_OnLoad(RedisModuleCtx *ctx, RedisModuleString **argv, int argc)
|
||||
if (RedisModule_CreateCommand(ctx,"testrdb.get.key", testrdb_get_key,"",1,1,1) == REDISMODULE_ERR)
|
||||
return REDISMODULE_ERR;
|
||||
|
||||
RedisModule_SubscribeToServerEvent(ctx,
|
||||
RedisModuleEvent_ReplBackup, replBackupCallback);
|
||||
|
||||
return REDISMODULE_OK;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user