美文网首页工作生活
「Redis源码解读」—数据库(一)启动

「Redis源码解读」—数据库(一)启动

作者: wh4763 | 来源:发表于2019-07-01 23:39 被阅读0次

Redis启动总体上可以分为如下几步:

1.初始化全局服务器配置

  1. 加载配置文件(如果指定了配置文件,否则使用默认配置)
  2. 初始化服务器
  3. 加载数据库
  4. 网络监听
  • redis整个程序的入口函数在server.c中的main函数,函数调用关系如下图1,调用顺序为从上到下,从左至右。


  • main——程序入口
  • initServerConfig——初始化 server 变量
  • populateCommanTable——初始化命令表
  • loadServerConfig——根据配置文件和传入的选项,修改 server 变量(服务器配置)
  • initServer——初始化Server
  • createSharedObjects—— 初始化共享对象
  • aeCreateEventLoop——初始化事件状态
  • listenToPort——开始网络监听
  • aeCreateTimeEvent——初始化时间事件
  • aeSetBeforeSleepProc——设置每次事件循环等待前的事件处理
  • aeMain——启动服务器循环

时间事件

  • 打印一些运行参数。
  • 关闭连接超时的客户端(需开启timeout配置项)
  • rehash数据库字典,循环1ms,每次rehash100个key(需开启activerehashing配置项)
  • 检查BGSAVE或者BGREWRITEAOF是否已经执行完毕
  • 集群相关操作。

程序入口

Redis服务器的main函数是在server.c中

//整个程序的入口函数
int main(int argc, char **argv) {
    //初始化服务器配置,设置全局对象server的状态
    initServerConfig();

    /* Store the executable path and arguments in a safe place in order
     * to be able to restart the server later. */
    //存储运行命令的绝对路径及运行参数
    server.executable = getAbsolutePath(argv[0]);
    server.exec_argv = zmalloc(sizeof(char*)*(argc+1));
    server.exec_argv[argc] = NULL;
    for (j = 0; j < argc; j++) server.exec_argv[j] = zstrdup(argv[j]);

    if (argc >= 2) {
        j = 1; /* First option to parse in argv[] */
        sds options = sdsempty();
        char *configfile = NULL;

        //命令指定了配置文件,对配置文件做处理,配置文件跟在程序名后第一位
        /* First argument is the config file name? */
        if (argv[j][0] != '-' || argv[j][1] != '-') {
            configfile = argv[j];
            server.configfile = getAbsolutePath(configfile);
            /* Replace the config file in server.exec_argv with
             * its absolute path. */
            zfree(server.exec_argv[j]);
            server.exec_argv[j] = zstrdup(server.configfile);
            j++;
        }

        /* All the other options are parsed and conceptually appended to the
         * configuration file. For instance --port 6380 will generate the
         * string "port 6380\n" to be parsed after the actual file name
         * is parsed, if any. */
        while(j != argc) {//解析除配置文件外的其它参数
            if (argv[j][0] == '-' && argv[j][1] == '-') {
                /* Option name */
                if (!strcmp(argv[j], "--check-rdb")) {
                    /* Argument has no options, need to skip for parsing. */
                    j++;
                    continue;
                }
                if (sdslen(options)) options = sdscat(options,"\n");
                options = sdscat(options,argv[j]+2);//去掉参数前面的--
                options = sdscat(options," ");//参数对应的值和参数名应" "分隔
            } else {
                /* Option argument */
                options = sdscatrepr(options,argv[j],strlen(argv[j]));
                options = sdscat(options," ");
            }
            j++;
        }
        //从指定配置文件和命令选项设置服务器对象server参数,覆盖默认配置
        loadServerConfig(configfile,options);
    }

    server.supervised = redisIsSupervised(server.supervised_mode);
    int background = server.daemonize && !server.supervised;
    if (background) daemonize();//后台进程模式

    //初始化服务器功能,包括时间事件1ms调用serverCron,文件事件(套接字可读可写时的处理函数),集群初始化等
    initServer();
    aeSetBeforeSleepProc(server.el,beforeSleep);//设置beforeSleep事件处理函数
    aeSetAfterSleepProc(server.el,afterSleep);//设置aftersleep事件处理函数
    aeMain(server.el);//循环,接受客户端连接,处理命令等
    aeDeleteEventLoop(server.el);//退出循环,删除事件处理
    return 0;
}

初始化服务器配置initServerConfig()

  • 初始化redis的16个db。dict是hash table结构,之后统一描述各种数据结构
/*
 * 初始化 server 结构
 */
void initServerConfig() {
    getRandomHexChars(server.runid,REDIS_RUN_ID_SIZE);
    server.runid[REDIS_RUN_ID_SIZE] = '\0';

    // 判断架构
    server.arch_bits = (sizeof(long) == 8) ? 64 : 32;

    // 网络连接相关
    server.port = REDIS_SERVERPORT;
    server.bindaddr = NULL;
    server.unixsocket = NULL;
    server.unixsocketperm = 0;
    server.ipfd = -1;
    server.sofd = -1;

    // 数据库个数
    server.dbnum = REDIS_DEFAULT_DBNUM;
    server.verbosity = REDIS_NOTICE;
    server.maxidletime = REDIS_MAXIDLETIME;

    // 客户端查询缓存最大长度
    server.client_max_querybuf_len = REDIS_MAX_QUERYBUF_LEN;

    // 保存 flag
    server.saveparams = NULL;

    // 是否正在载入数据?
    server.loading = 0;

    // log
    server.logfile = NULL; /* NULL = log on standard output */
    server.syslog_enabled = 0;
    server.syslog_ident = zstrdup("redis");
    server.syslog_facility = LOG_LOCAL0;

    // deamon 进程
    server.daemonize = 0;

    // AOF 状态
    server.aof_state = REDIS_AOF_OFF;
    server.aof_fsync = AOF_FSYNC_EVERYSEC;
    server.aof_no_fsync_on_rewrite = 0;
    server.aof_rewrite_perc = REDIS_AOF_REWRITE_PERC;
    server.aof_rewrite_min_size = REDIS_AOF_REWRITE_MIN_SIZE;
    server.aof_rewrite_base_size = 0;
    server.aof_rewrite_scheduled = 0;
    server.aof_last_fsync = time(NULL);
    server.aof_rewrite_time_last = -1;
    server.aof_rewrite_time_start = -1;
    server.aof_lastbgrewrite_status = REDIS_OK;
    server.aof_delayed_fsync = 0;
    server.aof_fd = -1;
    server.aof_selected_db = -1; /* Make sure the first time will not match */
    server.aof_flush_postponed_start = 0;

    // 持久化相关
    server.pidfile = zstrdup("/var/run/redis.pid");
    server.rdb_filename = zstrdup("dump.rdb");
    server.aof_filename = zstrdup("appendonly.aof");
    server.requirepass = NULL;
    server.rdb_compression = 1;
    server.rdb_checksum = 1;

    // 开启主动 rehash
    server.activerehashing = 1;

    // 最大客户端数量
    server.maxclients = REDIS_MAX_CLIENTS;
    server.bpop_blocked_clients = 0;

    // 内存相关
    server.maxmemory = 0;
    server.maxmemory_policy = REDIS_MAXMEMORY_VOLATILE_LRU;
    server.maxmemory_samples = 3;

    // 压缩数据结构实体数量限制
    server.hash_max_ziplist_entries = REDIS_HASH_MAX_ZIPLIST_ENTRIES;
    server.hash_max_ziplist_value = REDIS_HASH_MAX_ZIPLIST_VALUE;
    server.list_max_ziplist_entries = REDIS_LIST_MAX_ZIPLIST_ENTRIES;
    server.list_max_ziplist_value = REDIS_LIST_MAX_ZIPLIST_VALUE;
    server.set_max_intset_entries = REDIS_SET_MAX_INTSET_ENTRIES;
    server.zset_max_ziplist_entries = REDIS_ZSET_MAX_ZIPLIST_ENTRIES;
    server.zset_max_ziplist_value = REDIS_ZSET_MAX_ZIPLIST_VALUE;

    // 关闭指示 flag
    server.shutdown_asap = 0;

    // REPL
    server.repl_ping_slave_period = REDIS_REPL_PING_SLAVE_PERIOD;
    server.repl_timeout = REDIS_REPL_TIMEOUT;

    // 集群相关
    server.cluster_enabled = 0;
    server.cluster.configfile = zstrdup("nodes.conf");

    // LUA 脚本相关
    server.lua_caller = NULL;
    server.lua_time_limit = REDIS_LUA_TIME_LIMIT;
    server.lua_client = NULL;
    server.lua_timedout = 0;
    server.migrate_cached_sockets = dictCreate(&migrateCacheDictType,NULL);

    updateLRUClock();
    resetServerSaveParams();

    // 保存相关
    appendServerSaveParams(60*60,1);  /* save after 1 hour and 1 change */
    appendServerSaveParams(300,100);  /* save after 5 minutes and 100 changes */
    appendServerSaveParams(60,10000); /* save after 1 minute and 10000 changes */

    // 复制相关
    /* Replication related */
    server.masterauth = NULL;
    server.masterhost = NULL;
    server.masterport = 6379;
    server.master = NULL;
    server.repl_state = REDIS_REPL_NONE;
    server.repl_syncio_timeout = REDIS_REPL_SYNCIO_TIMEOUT;
    server.repl_serve_stale_data = 1;
    server.repl_slave_ro = 1;
    server.repl_down_since = time(NULL);
    server.slave_priority = REDIS_DEFAULT_SLAVE_PRIORITY;

    // 客户端输出缓存限制
    /* Client output buffer limits */
    server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_NORMAL].hard_limit_bytes = 0;
    server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_NORMAL].soft_limit_bytes = 0;
    server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_NORMAL].soft_limit_seconds = 0;
    server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_SLAVE].hard_limit_bytes = 1024*1024*256;
    server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_SLAVE].soft_limit_bytes = 1024*1024*64;
    server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_SLAVE].soft_limit_seconds = 60;
    server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_PUBSUB].hard_limit_bytes = 1024*1024*32;
    server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_PUBSUB].soft_limit_bytes = 1024*1024*8;
    server.client_obuf_limits[REDIS_CLIENT_LIMIT_CLASS_PUBSUB].soft_limit_seconds = 60;

    /* Double constants initialization */
    R_Zero = 0.0;
    R_PosInf = 1.0/R_Zero;
    R_NegInf = -1.0/R_Zero;
    R_Nan = R_Zero/R_Zero;

    /* Command table -- we intiialize it here as it is part of the
     * initial configuration, since command names may be changed via
     * redis.conf using the rename-command directive. */
    // 命令表
    server.commands = dictCreate(&commandTableDictType,NULL);
    populateCommandTable();
    server.delCommand = lookupCommandByCString("del");
    server.multiCommand = lookupCommandByCString("multi");
    server.lpushCommand = lookupCommandByCString("lpush");
    server.lpopCommand = lookupCommandByCString("lpop");
    server.rpopCommand = lookupCommandByCString("rpop");
    
    /* Slow log */
    // 慢查询
    server.slowlog_log_slower_than = REDIS_SLOWLOG_LOG_SLOWER_THAN;
    server.slowlog_max_len = REDIS_SLOWLOG_MAX_LEN;

    /* Debugging */
    // 调试
    server.assert_failed = "<no assertion failed>";
    server.assert_file = "<no file>";
    server.assert_line = 0;
    server.bug_report_start = 0;
    server.watchdog_period = 0;
}

初始化服务器initServer()

void initServer() {
    int j;

    signal(SIGHUP, SIG_IGN);
    signal(SIGPIPE, SIG_IGN);
    setupSignalHandlers();

    // LOG
    if (server.syslog_enabled) {
        openlog(server.syslog_ident, LOG_PID | LOG_NDELAY | LOG_NOWAIT,
            server.syslog_facility);
    }

    // 当前处理的客户端
    server.current_client = NULL;
    // 所有客户端
    server.clients = listCreate();
    // 要被关闭的客户端
    server.clients_to_close = listCreate();
    // 附属节点
    server.slaves = listCreate();
    // monitor 客户端
    server.monitors = listCreate();
    // 被取消阻塞的客户端
    server.unblocked_clients = listCreate();
    // 所有已就绪 key
    server.ready_keys = listCreate();

    // 初始化共享对象
    createSharedObjects();

    // 获取最大打开文件数目
    adjustOpenFilesLimit();

    // 初始化事件状态
    server.el = aeCreateEventLoop(server.maxclients+1024);
    
    // 初始化数据库
    server.db = zmalloc(sizeof(redisDb)*server.dbnum);

    // 初始化网络连接
    if (server.port != 0) {
        server.ipfd = anetTcpServer(server.neterr,server.port,server.bindaddr);
        if (server.ipfd == ANET_ERR) {
            redisLog(REDIS_WARNING, "Opening port %d: %s",
                server.port, server.neterr);
            exit(1);
        }
    }

    if (server.unixsocket != NULL) {
        unlink(server.unixsocket); /* don't care if this fails */
        server.sofd = anetUnixServer(server.neterr,server.unixsocket,server.unixsocketperm);
        if (server.sofd == ANET_ERR) {
            redisLog(REDIS_WARNING, "Opening socket: %s", server.neterr);
            exit(1);
        }
    }
    if (server.ipfd < 0 && server.sofd < 0) {
        redisLog(REDIS_WARNING, "Configured to not listen anywhere, exiting.");
        exit(1);
    }

    // 初始化数据库
    for (j = 0; j < server.dbnum; j++) {
        // key space
        server.db[j].dict = dictCreate(&dbDictType,NULL);
        // 过期空间
        server.db[j].expires = dictCreate(&keyptrDictType,NULL);
        // 被阻塞键
        server.db[j].blocking_keys = dictCreate(&keylistDictType,NULL);
        // 可解除阻塞的键
        server.db[j].ready_keys = dictCreate(&setDictType,NULL);
        // 被 WATCH 命令监视的键
        server.db[j].watched_keys = dictCreate(&keylistDictType,NULL);
        // 数据库 ID
        server.db[j].id = j;
    }

    // pubsub
    server.pubsub_channels = dictCreate(&keylistDictType,NULL);
    server.pubsub_patterns = listCreate();
    listSetFreeMethod(server.pubsub_patterns,freePubsubPattern);
    listSetMatchMethod(server.pubsub_patterns,listMatchPubsubPattern);

    // CRON 执行计数
    server.cronloops = 0;

    // BGSAVE 执行指示变量
    server.rdb_child_pid = -1;
    // BGREWRITEAOF 执行指示变量
    server.aof_child_pid = -1;
    // 初始化 AOF 重写缓存
    aofRewriteBufferReset();
    server.aof_buf = sdsempty();
    // 最后一次成功保存的时间
    server.lastsave = time(NULL);
    // 结束 SAVE 的时间
    server.rdb_save_time_last = -1;
    // 开始 SAVE 的时间
    server.rdb_save_time_start = -1;
    server.dirty = 0;

    // 统计变量
    server.stat_numcommands = 0;
    server.stat_numconnections = 0;
    server.stat_expiredkeys = 0;
    server.stat_evictedkeys = 0;
    server.stat_starttime = time(NULL);
    server.stat_keyspace_misses = 0;
    server.stat_keyspace_hits = 0;
    server.stat_peak_memory = 0;
    server.stat_fork_time = 0;
    server.stat_rejected_conn = 0;
    memset(server.ops_sec_samples,0,sizeof(server.ops_sec_samples));
    server.ops_sec_idx = 0;
    server.ops_sec_last_sample_time = mstime();
    server.ops_sec_last_sample_ops = 0;
    server.unixtime = time(NULL);
    server.lastbgsave_status = REDIS_OK;
    server.stop_writes_on_bgsave_err = 1;

    // 关联 server cron 到时间事件
    aeCreateTimeEvent(server.el, 1, serverCron, NULL, NULL);

    // 关联网络连接事件
    if (server.ipfd > 0 && aeCreateFileEvent(server.el,server.ipfd,AE_READABLE,
        acceptTcpHandler,NULL) == AE_ERR) redisPanic("Unrecoverable error creating server.ipfd file event.");
    if (server.sofd > 0 && aeCreateFileEvent(server.el,server.sofd,AE_READABLE,
        acceptUnixHandler,NULL) == AE_ERR) redisPanic("Unrecoverable error creating server.sofd file event.");

    // 如果 AOF 已打开,那么打开或创建 AOF 文件
    if (server.aof_state == REDIS_AOF_ON) {
        server.aof_fd = open(server.aof_filename,
                               O_WRONLY|O_APPEND|O_CREAT,0644);
        if (server.aof_fd == -1) {
            redisLog(REDIS_WARNING, "Can't open the append-only file: %s",
                strerror(errno));
            exit(1);
        }
    }
    /* 32 bit instances are limited to 4GB of address space, so if there is
     * no explicit limit in the user provided configuration we set a limit
     * at 3 GB using maxmemory with 'noeviction' policy'. This avoids
     * useless crashes of the Redis instance for out of memory. */
    // 设置内存限制
    if (server.arch_bits == 32 && server.maxmemory == 0) {
        redisLog(REDIS_WARNING,"Warning: 32 bit instance detected but no memory limit set. Setting 3 GB maxmemory limit with 'noeviction' policy now.");
        server.maxmemory = 3072LL*(1024*1024); /* 3 GB */
        server.maxmemory_policy = REDIS_MAXMEMORY_NO_EVICTION;
    }

    // 如果集群模式已打开,那么初始化集群
    if (server.cluster_enabled) clusterInit();

    // 初始化脚本环境
    scriptingInit();

    // 初始化慢查询
    slowlogInit();

    // 初始化后台 IO 
    bioInit();
}

主循环

//处理客户端命令的主函数,由main函数调用,aeEventLoop定义在(ae.h),beforesleep和aftersleep均在服务器启动初始化时设定
void aeMain(aeEventLoop *eventLoop) {
    eventLoop->stop = 0;
    while (!eventLoop->stop) {
        // 如果有需要在事件处理前执行的函数,那么运行它
        if (eventLoop->beforesleep != NULL)
            eventLoop->beforesleep(eventLoop);
        //处理文件时间及时间事件
        aeProcessEvents(eventLoop, AE_ALL_EVENTS|AE_CALL_AFTER_SLEEP);
    }
}

相关结构体

struct redisServer {
    /* General */

    // 数据库数组
    redisDb *db;

    // 命令表
    dict *commands;             /* Command table hash table */

    // 事件状态结构
    aeEventLoop *el;

    // LRU
    unsigned lruclock:22;       /* Clock incrementing every minute, for LRU */
    unsigned lruclock_padding:10;

    // 关闭标志
    int shutdown_asap;          /* SHUTDOWN needed ASAP */

    // 主动 rehash
    int activerehashing;        /* Incremental rehash in serverCron() */

    // 密码
    char *requirepass;          /* Pass for AUTH command, or NULL */

    // PID 文件路径
    char *pidfile;              /* PID file path */

    // 宿主架构字长
    int arch_bits;              /* 32 or 64 depending on sizeof(long) */

    // CRON 函数调用的次数
    int cronloops;              /* Number of times the cron function run */

    // 每次调用 exec 时都创建新 ID
    char runid[REDIS_RUN_ID_SIZE+1];  /* ID always different at every exec. */

    // 如果服务器为 SENTINEL ,那么为真
    int sentinel_mode;          /* True if this instance is a Sentinel. */

    /* Networking */
    // 监听端口
    int port;                   /* TCP listening port */
    // 绑定地址
    char *bindaddr;             /* Bind address or NULL */
    // 套接字路径
    char *unixsocket;           /* UNIX socket path */
    // 套接字权限
    mode_t unixsocketperm;      /* UNIX socket permission */
    int ipfd;                   /* TCP socket file descriptor */
    int sofd;                   /* Unix socket file descriptor */
    int cfd;                    /* Cluster bus lisetning socket */

    /* 客户端 */
    // 所有当前活动的客户端
    list *clients;              /* List of active clients */
    // 所有等待关闭的客户端
    list *clients_to_close;     /* Clients to close asynchronously */
    // 所有附属节点和 MONITOR
    list *slaves, *monitors;    /* List of slaves and MONITORs */
    // 当前客户端,只在创建崩溃报告时使用
    redisClient *current_client; /* Current client, only used on crash report */

    char neterr[ANET_ERR_LEN];   /* Error buffer for anet.c */
    dict *migrate_cached_sockets;/* MIGRATE cached sockets */

    /* RDB / AOF loading information */
    int loading;                /* We are loading data from disk if true */
    off_t loading_total_bytes;
    off_t loading_loaded_bytes;
    time_t loading_start_time;

    /* Fast pointers to often looked up command */
    struct redisCommand *delCommand, *multiCommand, *lpushCommand, *lpopCommand,
                        *rpopCommand;

    /* Fields used only for stats */
    time_t stat_starttime;          /* Server start time */
    long long stat_numcommands;     /* Number of processed commands */
    long long stat_numconnections;  /* Number of connections received */
    long long stat_expiredkeys;     /* Number of expired keys */
    long long stat_evictedkeys;     /* Number of evicted keys (maxmemory) */
    long long stat_keyspace_hits;   /* Number of successful lookups of keys */
    long long stat_keyspace_misses; /* Number of failed lookups of keys */
    size_t stat_peak_memory;        /* Max used memory record */
    long long stat_fork_time;       /* Time needed to perform latets fork() */
    long long stat_rejected_conn;   /* Clients rejected because of maxclients */

    // 保存慢查询日志的链表
    list *slowlog;                  /* SLOWLOG list of commands */

    // 慢查询日志的当前 id 值
    long long slowlog_entry_id;     /* SLOWLOG current entry ID */
    // 慢查询时间限制
    long long slowlog_log_slower_than; /* SLOWLOG time limit (to get logged) */
    // 慢查询日志的最大条目数量
    unsigned long slowlog_max_len;     /* SLOWLOG max number of items logged */

    /* The following two are used to track instantaneous "load" in terms
     * of operations per second. */
    long long ops_sec_last_sample_time; /* Timestamp of last sample (in ms) */
    long long ops_sec_last_sample_ops;  /* numcommands in last sample */
    long long ops_sec_samples[REDIS_OPS_SEC_SAMPLES];
    int ops_sec_idx;

    /* Configuration */
    int verbosity;                  /* Loglevel in redis.conf */
    int maxidletime;                /* Client timeout in seconds */
    size_t client_max_querybuf_len; /* Limit for client query buffer length */
    int dbnum;                      /* Total number of configured DBs */
    int daemonize;                  /* True if running as a daemon */
    clientBufferLimitsConfig client_obuf_limits[REDIS_CLIENT_LIMIT_NUM_CLASSES];

    /* AOF persistence */
    int aof_state;                  /* REDIS_AOF_(ON|OFF|WAIT_REWRITE) */
    int aof_fsync;                  /* Kind of fsync() policy */
    char *aof_filename;             /* Name of the AOF file */
    int aof_no_fsync_on_rewrite;    /* Don't fsync if a rewrite is in prog. */
    int aof_rewrite_perc;           /* Rewrite AOF if % growth is > M and... */
    off_t aof_rewrite_min_size;     /* the AOF file is at least N bytes. */
    off_t aof_rewrite_base_size;    /* AOF size on latest startup or rewrite. */
    off_t aof_current_size;         /* AOF current size. */
    int aof_rewrite_scheduled;      /* Rewrite once BGSAVE terminates. */
    pid_t aof_child_pid;            /* PID if rewriting process */
    list *aof_rewrite_buf_blocks;   /* Hold changes during an AOF rewrite. */
    sds aof_buf;      /* AOF buffer, written before entering the event loop */
    int aof_fd;       /* File descriptor of currently selected AOF file */
    int aof_selected_db; /* Currently selected DB in AOF */
    time_t aof_flush_postponed_start; /* UNIX time of postponed AOF flush */
    time_t aof_last_fsync;            /* UNIX time of last fsync() */
    time_t aof_rewrite_time_last;   /* Time used by last AOF rewrite run. */
    time_t aof_rewrite_time_start;  /* Current AOF rewrite start time. */
    int aof_lastbgrewrite_status;   /* REDIS_OK or REDIS_ERR */
    unsigned long aof_delayed_fsync;  /* delayed AOF fsync() counter */

    /* RDB persistence */
    long long dirty;                /* Changes to DB from the last save */
    long long dirty_before_bgsave;  /* Used to restore dirty on failed BGSAVE */
    pid_t rdb_child_pid;            /* PID of RDB saving child */
    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? */
    int rdb_checksum;               /* Use RDB checksum? */
    time_t lastsave;                /* Unix time of last save succeeede */
    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 lastbgsave_status;          /* REDIS_OK or REDIS_ERR */
    int stop_writes_on_bgsave_err;  /* Don't allow writes if can't BGSAVE */

    /* Propagation of commands in AOF / replication */
    redisOpArray also_propagate;    /* Additional command to propagate. */
    /* Logging */
    char *logfile;                  /* Path of log file */
    int syslog_enabled;             /* Is syslog enabled? */
    char *syslog_ident;             /* Syslog ident */
    int syslog_facility;            /* Syslog facility */

    /* Slave specific fields */
    char *masterauth;               /* AUTH with this password with master */
    char *masterhost;               /* Hostname of master */
    int masterport;                 /* Port of master */
    int repl_ping_slave_period;     /* Master pings the slave every N seconds */
    int repl_timeout;               /* Timeout after N seconds of master idle */
    redisClient *master;     /* Client that is master for this slave */
    int repl_syncio_timeout; /* Timeout for synchronous I/O calls */
    int repl_state;          /* Replication status if the instance is a slave */
    off_t repl_transfer_size; /* Size of RDB to read from master during sync. */
    off_t repl_transfer_read; /* Amount of RDB read from master during sync. */
    off_t repl_transfer_last_fsync_off; /* Offset when we fsync-ed last time. */
    int repl_transfer_s;     /* Slave -> Master SYNC socket */
    int repl_transfer_fd;    /* Slave -> Master SYNC temp file descriptor */
    char *repl_transfer_tmpfile; /* Slave-> master SYNC temp file name */
    time_t repl_transfer_lastio; /* Unix time of the latest read, for timeout */
    int repl_serve_stale_data; /* Serve stale data when link is down? */
    int repl_slave_ro;          /* Slave is read only? */
    time_t repl_down_since; /* Unix time at which link with master went down */
    int slave_priority;             /* Reported in INFO and used by Sentinel. */

    /* Limits */
    unsigned int maxclients;        /* Max number of simultaneous clients */
    unsigned long long maxmemory;   /* Max number of memory bytes to use */
    int maxmemory_policy;           /* Policy for key evition */
    int maxmemory_samples;          /* Pricision of random sampling */

    /* Blocked clients */
    unsigned int bpop_blocked_clients; /* Number of clients blocked by lists */
    // 要在下一次事件 lopp 前取消阻塞的所有客户端
    list *unblocked_clients; /* list of clients to unblock before next loop */
    list *ready_keys;        /* List of readyList structures for BLPOP & co */

    /* Sort parameters - qsort_r() is only available under BSD so we
     * have to take this state global, in order to pass it to sortCompare() */
    int sort_desc;
    int sort_alpha;
    int sort_bypattern;

    /* Zip structure config, see redis.conf for more information  */
    size_t hash_max_ziplist_entries;
    size_t hash_max_ziplist_value;
    size_t list_max_ziplist_entries;
    size_t list_max_ziplist_value;
    size_t set_max_intset_entries;
    size_t zset_max_ziplist_entries;
    size_t zset_max_ziplist_value;
    time_t unixtime;        /* Unix time sampled every second. */

    /* Pubsub */
    // 频道
    dict *pubsub_channels;  /* Map channels to list of subscribed clients */
    // 模式
    list *pubsub_patterns;  /* A list of pubsub_patterns */

    /* Cluster */
    int cluster_enabled;    /* Is cluster enabled? */
    clusterState cluster;   /* State of the cluster */

    /* Scripting */
    lua_State *lua; /* The Lua interpreter. We use just one for all clients */
    redisClient *lua_client;   /* The "fake client" to query Redis from Lua */
    redisClient *lua_caller;   /* The client running EVAL right now, or NULL */
    dict *lua_scripts;         /* A dictionary of SHA1 -> Lua scripts */
    long long lua_time_limit;  /* Script timeout in seconds */
    long long lua_time_start;  /* Start time of script */
    int lua_write_dirty;  /* True if a write command was called during the
                             execution of the current script. */
    int lua_random_dirty; /* True if a random command was called during the
                             execution of the current script. */
    int lua_timedout;     /* True if we reached the time limit for script
                             execution. */
    int lua_kill;         /* Kill the script if true. */

    /* Assert & bug reportign */
    char *assert_failed;
    char *assert_file;
    int assert_line;
    int bug_report_start; /* True if bug report header was already logged. */
    int watchdog_period;  /* Software watchdog period in ms. 0 = off */
};

相关文章

  • 「Redis源码解读」—数据库(一)启动

    Redis启动总体上可以分为如下几步: 1.初始化全局服务器配置 加载配置文件(如果指定了配置文件,否则使用默认配...

  • spring源码解读网上知识摘要

    spring 启动源码 spring 启动流程源码解读spring 启动注解加载类源码解读springxml 文件...

  • Redis安装

    Redis官网地址: http://www.redis.io/ 下载源码,解压缩后编译源码: 启动Redis 进入...

  • yum安装redis

    #安装redis数据库 yuminstallredis # 启动redis service redis start...

  • redis存取

    Redis的数据库 Redis 对数据库进行了抽象,在 Redis 源码中,承担数据库角色的叫 redisDb。 ...

  • Redis Docker安装

    下载redis 启动redis 进入容器 redis默认有16个数据库;

  • redis基本操作

    启动数据库 1.打开redis-server2.再打开redis-cli 启动redis输入KEYS * 查看是否...

  • redis在Centos7上介绍和安装

    redis一般提供缓存服务 redis基本操作 解释 命令 安装 源码编译安装 启动 ...

  • redis 安装

    1. 源码安装redis 下载地址:http://redis.io/download下载最新版 启动redis-s...

  • 若依框架启动

    打开MySQL服务 本地数据库(Navicat Premium) 启动redis-service redis-cl...

网友评论

    本文标题:「Redis源码解读」—数据库(一)启动

    本文链接:https://www.haomeiwen.com/subject/pkeocctx.html