redis-rdb-3

2021-12-04

RDB在server中的参数

int child_type;             /* Type of current child */

#define CHILD_TYPE_NONE 0
#define CHILD_TYPE_RDB 1
#define CHILD_TYPE_AOF 2
#define CHILD_TYPE_LDB 3
#define CHILD_TYPE_MODULE 4

赋值的地方
void resetChildState() {	server.child_type = CHILD_TYPE_NONE;
void initServer(void) {		server.child_type = CHILD_TYPE_NONE;
/* purpose is one of CHILD_TYPE_ types */
int redisFork(int purpose) {	server.child_type = purpose;

可以看到reset和init的方法都是把child_type的值赋值为0,只有redisFork可以赋指定值,而调用redisFork的地方有

image-20211204162420987

aof\module\rdb\scripting四个模块,具体到现在分析的rdb中,则有
int rdbSaveBackground(char *filename, rdbSaveInfo *rsi) { 
if ((childpid = redisFork(CHILD_TYPE_RDB)) == 0) {
和
int rdbSaveToSlavesSockets(rdbSaveInfo *rsi) {
if ((childpid = redisFork(CHILD_TYPE_RDB)) == 0)
两个方法第一个就是我们rdb中的bgsave,而rdbSaveToSlavesSockets这个方法就是:生成一个rdb子进程,将db写入当前处于SLAVE_STATE_WAIT_BGSAVE_START状态的从节点套接字。
int rdb_save_incremental_fsync;   /* fsync incrementally while rdb saving? */

赋值的地方
standardConfig configs[] = {
createBoolConfig("rdb-save-incremental-fsync", NULL, MODIFIABLE_CONFIG, server.rdb_save_incremental_fsync, 1, NULL, NULL),
默认的的值是1

调用的地方
#define REDIS_AUTOSYNC_BYTES (1024*1024*4) /* Sync file every 4MB. */
int rdbSave(char *filename, rdbSaveInfo *rsi) {
    if (server.rdb_save_incremental_fsync)
        rioSetAutoSync(&rdb,REDIS_AUTOSYNC_BYTES);  

看下rioSetAutoSync函数

/* Set the file-based rio object to auto-fsync every 'bytes' file written.
 * By default this is set to zero that means no automatic file sync is
 * performed.
 *
 * This feature is useful in a few contexts since when we rely on OS write
 * buffers sometimes the OS buffers way too much, resulting in too many
 * disk I/O concentrated in very little time. When we fsync in an explicit
 * way instead the I/O pressure is more distributed across time. */
 设置那些file_base的rio的对象到auto-fsync。默认这里bytes设置为0,这意味着没有自动文件的写入。当os缓存太多,导致太多的磁盘io在短时间内的的时候很有用,可以分布开。
void rioSetAutoSync(rio *r, off_t bytes) {
    if(r->write != rioFileIO.write) return;
    r->io.file.autosync = bytes;
}
off_t loading_rdb_used_mem;

off_t类型用于指示文件的偏移量,常就是long类型,其默认为一个32位的整数,在gcc编译中会被编译为long int类型,在64位的Linux系统中则会被编译为long long int,这是一个64位的整数,其定义在unistd.h头文件中可以查看。

赋值:
void startLoading(size_t size, int rdbflags, int async) {
server.loading_rdb_used_mem = 0;

int rdbLoadRio(rio *rdb, int rdbflags, rdbSaveInfo *rsi, redisDb *dbarray) {
            } else if (!strcasecmp(auxkey->ptr,"used-mem")) {
                long long usedmem = strtoll(auxval->ptr,NULL,10);
                serverLog(LL_NOTICE,"RDB memory usage when created %.2f Mb",
                    (double) usedmem / (1024*1024));
                server.loading_rdb_used_mem = usedmem;
size_t stat_rdb_cow_bytes;      /* Copy on write bytes during RDB saving. */
size_t stat_current_cow_peak;   /* Peak size of copy on write bytes. */

赋值:
void updateChildInfo(childInfoType information_type, size_t cow, monotime cow_updated, size_t keys, double progress) {
    } else if (information_type == CHILD_INFO_TYPE_RDB_COW_SIZE) {
        server.stat_rdb_cow_bytes = server.stat_current_cow_peak;
int aof_use_rdb_preamble;       /* Use RDB preamble on AOF rewrites. */
默认值:1

调用:
int rewriteAppendOnlyFile(char *filename) {
	    if (server.aof_use_rdb_preamble) {
        int error;
        if (rdbSaveRio(&aof,&error,RDBFLAGS_AOF_PREAMBLE,NULL) == C_ERR) {
/* RDB persistence */
long long dirty;                /* Changes to DB from the last save */
调用:
int rdbSave(char *filename, rdbSaveInfo *rsi) {
	server.dirty = 0;

long long dirty_before_bgsave;  /* Used to restore dirty on failed BGSAVE */  
调用:
int rdbSaveBackground(char *filename, rdbSaveInfo *rsi) {
	server.dirty_before_bgsave = server.dirty;
    
static void backgroundSaveDoneHandlerDisk(int exitcode, int bysignal) {
    if (!bysignal && exitcode == 0) {
        serverLog(LL_NOTICE,
            "Background saving terminated with success");
        server.dirty = server.dirty - server.dirty_before_bgsave;

backgroundSaveDoneHandlerDisk的调用:
int rdb_child_type;             /* Type of save by active child. */
/* RDB active child save type. */
#define RDB_CHILD_TYPE_NONE 0
#define RDB_CHILD_TYPE_DISK 1     /* RDB is written to disk. */
#define RDB_CHILD_TYPE_SOCKET 2   /* RDB is written to slave socket. */

void backgroundSaveDoneHandler(int exitcode, int bysignal) {
    case RDB_CHILD_TYPE_DISK:
    	backgroundSaveDoneHandlerDisk(exitcode,bysignal);

backgroundSaveDoneHandler的调用
void checkChildrenDone(void) {
	 if ((pid = waitpid(-1, &statloc, WNOHANG)) != 0) {
	 	else if (pid == server.child_pid)
     	    if (server.child_type == CHILD_TYPE_RDB) {
                backgroundSaveDoneHandler(exitcode, bysignal);

checkChildrenDone的调用:
int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
   if (hasActiveChildProcess() || ldbPendingChildren())
    {
        run_with_period(1000) receiveChildInfo();
        checkChildrenDone();
    
    long long rdb_last_load_keys_expired;  /* number of expired keys when loading RDB */
    long long rdb_last_load_keys_loaded;   /* number of loaded keys when loading RDB */
    struct saveparam *saveparams;   /* Save points array for RDB */
    int saveparamslen;              /* Number of saving points */
    char *rdb_filename;             /* Name of RDB file */
    int rdb_compression;            /* Use compression in RDB? */
 调用:
ssize_t rdbSaveRawString(rio *rdb, unsigned char *s, size_t len) {
if (server.rdb_compression && len > 20) {	
	n = rdbSaveLzfStringObject(rdb,s,len);
	
    int rdb_checksum;               /* Use RDB checksum? */
    int rdb_del_sync_files;         /* Remove RDB files used only for SYNC if
                                       the instance does not use persistence. */
    time_t lastsave;                /* Unix time of last successful save */
    time_t lastbgsave_try;          /* Unix time of last attempted bgsave */
    time_t rdb_save_time_last;      /* Time used by last RDB save run. */
    time_t rdb_save_time_start;     /* Current RDB save start time. */
    int rdb_bgsave_scheduled;       /* BGSAVE when possible if true. */
赋值:
void bgsaveCommand(client *c) {
	else if (hasActiveChildProcess()) 
		if (schedule) {
            server.rdb_bgsave_scheduled = 1;
            addReplyStatus(c,"Background saving scheduled");
使用:
int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
    if (!hasActiveChildProcess() &&
        server.rdb_bgsave_scheduled &&
        (server.unixtime-server.lastbgsave_try > CONFIG_BGSAVE_RETRY_DELAY ||
         server.lastbgsave_status == C_OK))
    {
        rdbSaveInfo rsi, *rsiptr;
        rsiptr = rdbPopulateSaveInfo(&rsi);
        if (rdbSaveBackground(server.rdb_filename,rsiptr) == C_OK)
            server.rdb_bgsave_scheduled = 0;
    }
    
/* RDB active child save type. */
#define RDB_CHILD_TYPE_NONE 0
#define RDB_CHILD_TYPE_DISK 1     /* RDB is written to disk. */
#define RDB_CHILD_TYPE_SOCKET 2   /* RDB is written to slave socket. */
    int rdb_child_type;             /* Type of save by active child. */
    
    
    int lastbgsave_status;          /* C_OK or C_ERR */
    int stop_writes_on_bgsave_err;  /* Don't allow writes if can't BGSAVE */
    int rdb_pipe_read;              /* RDB pipe used to transfer the rdb data */
                                    /* to the parent process in diskless repl. */
    int rdb_child_exit_pipe;        /* Used by the diskless parent allow child exit. */
    connection **rdb_pipe_conns;    /* Connections which are currently the */
    int rdb_pipe_numconns;          /* target of diskless rdb fork child. */
    int rdb_pipe_numconns_writing;  /* Number of rdb conns with pending writes. */
    char *rdb_pipe_buff;            /* In diskless replication, this buffer holds data */
    int rdb_pipe_bufflen;           /* that was read from the the rdb pipe. */
    int rdb_key_save_delay;         /* Delay in microseconds between keys while
                                     * writing the RDB. (for testings). negative
                                     * value means fractions of microseconds (on average). */
    int key_load_delay;             /* Delay in microseconds between keys while
                                     * loading aof or rdb. (for testings). negative
                                     * value means fractions of microseconds (on average). */