Redis源码阅读-服务端初始化-配置加载部分

本文聚焦Redis服务端1.3.6版本的初始化,特别是配置加载部分。首先介绍Redis服务端初始化的逻辑,包括初始化基本配置、从配置文件加载配置、设置守护进程模式、初始化服务器数据结构等步骤。接着详细讲解`initServerConfig()`函数,涉及Redis的基本配置和持久化设置。最后,阐述如何根据配置文件覆盖默认配置,通过`loadServerConfig()`解析配置文件,确保所有配置读入内存。
摘要由CSDN通过智能技术生成

Redis服务端(1.3.6版本)初始化——配置加载部分

Redis服务端代码主要放在redis.c文件中。主要负责服务端业务逻辑实现,由上到下分为头文件引用、宏定义、数据结构、函数声明、全局变量、业务实现,几部分组成。本文主要讨论Redis服务端的初始化过程。

Redis服务端的main函数如下:

int main(int argc, char **argv) {
   
    time_t start;
    /* 初始化服务器配置 */
    initServerConfig();
    /* 加载配置 */
    if (argc == 2) {
   
        /* 重置服务端持久化参数 */
        resetServerSaveParams();
        /* 加载配置文件配置*/
        loadServerConfig(argv[1]);
    } else if (argc > 2) {
   
        fprintf(stderr,"Usage: ./redis-server [/path/to/redis.conf]\n");
        exit(1);
    } else {
   
        redisLog(REDIS_WARNING,"Warning: no config file specified, using the default config. In order to specify a config file use 'redis-server /path/to/redis.conf'");
    }
    /*设置守护进程方式运行 */
    if (server.daemonize) daemonize();
    /* 初始化服务器数据结构 */
    initServer();
    redisLog(REDIS_NOTICE,"Server started, Redis version " REDIS_VERSION);
#ifdef __linux__
/*
    该文件指定了内核针对内存分配的策略,其值可以是0、1、2。
    0,表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败,并把错误返回给应用进程。
    1,表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
    2,表示内核允许分配超过所有物理内存和交换空间总和的内存(参照overcommit_ratio)。
 */
    linuxOvercommitMemoryWarning();
#endif
    start = time(NULL);
    /* 加载持久化数据 */
    if (server.appendonly) {
   
        if (loadAppendOnlyFile(server.appendfilename) == REDIS_OK)
            redisLog(REDIS_NOTICE,"DB loaded from append only file: %ld seconds",time(NULL)-start);
    } else {
   
        if (rdbLoad(server.dbfilename) == REDIS_OK)
            redisLog(REDIS_NOTICE,"DB loaded from disk: %ld seconds",time(NULL)-start);
    }
    redisLog(REDIS_NOTICE,"The server is now ready to accept connections on port %d", server.port);
    /* Redis启动部分 */
    aeSetBeforeSleepProc(server.el,beforeSleep);
    /* Redis主程序部分 */
    aeMain(server.el);
    /* Redis程序结束,清理数据 */
    aeDeleteEventLoop(server.el);
    return 0;
}

Redis的main函数逻辑主要是如下部分:

  1. 初始化Redis服务端基本配置。
  2. 从配置文件或者其他地方加载配置
  3. 按照配置,设置是否以守护方式进行
  4. 初始化服务器数据结构
  5. 判断Linux系统内存分配方式
  6. 从持久化文件中加载原有数据
  7. 使用多路复用API运行Redis主程序

Redis服务端配置数据结构

* Global server state structure */
struct redisServer {
   
    /* 端口号 */
    int port;
    /* file description 文件描述符  多路复用API使用 */
    int fd;
    /* db数组,数据存储位置 */
    redisDb *db;
    dict *sharingpool;          /* Poll used for object sharing */
    unsigned int sharingpoolsize;
    /* 距离上一次save,数据更改次数 */
    long long dirty;            /* changes to DB from the last save */
    /* 连接的客户端数 */
    list *clients;
    /* 从节点和监听节点 */
    list *slaves, *monitors;
    char neterr[ANET_ERR_LEN];
    /* 事件循环,多路复用API使用 */
    aeEventLoop *el;
    /* 定时任务循环 */
    int cronloops;              /* number of times the cron function run */
    /* Redis的key-value内存释放不是立即释放,这样避免了频繁释放空间导致消耗资源过多 */
    list *objfreelist;          /* A list of freed objects to avoid malloc() */
    /* 上一次save的时间 */
    time_t lastsave;            /* Unix time of last save succeeede */
    /* 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 */
    /* Configuration */
    /* 配置部分 */
    /* 日志级别 */
    int verbosity;
    /* Redis支持小数据打包成打数据进行打包发送,使用该配置开启 */
    int glueoutputbuf;
    /* 客户端最大空闲时间 */
    int maxidletime;
    /* 数据库个数 */
    int dbnum;
    /* 是否按照守护进程运行 */
    int daemonize;
    /* 是否每条修改都进行日志记录 */
    int appendonly;
    /* 更新日志策略
    指定更新日志条件,共有 3 个可选值:
        no:表示等操作系统进行数据缓存同步到磁盘(快)
        always:表示每次更新操作后手动调用 fsync() 将数据写到磁盘(慢,安全)
        everysec:表示每秒同步一次(折中,默认值)
     */
    int appendfsync;
    /* 上一次更新时间 */
    time_t lastfsync;
    int appendfd;
    int appendseldb;
    /* pid文件位置 */
    char *pidfile;
    /* bgsave子进程pid */
    pid_t bgsavechildpid;
    /* bgwrite子进程pid */
    pid_t bgrewritechildpid;
    /* bgwrite buffer */
    sds bgrewritebuf; /* buffer taken by parent during oppend only rewrite */
    /* save参数 */
    struct saveparam *saveparams;
    int saveparamslen;
    char *logfile;
    char *bindaddr;
    char *dbfilename;
    /* aof文件名 */
    char *appendfilename;
    char *requirepass;
    int shareobjects;
    int rdbcompression;
    /* Replication related */
    int isslave;
    char *masterauth;
    char *masterhost;
    int masterport;
    redisClient *master;    /* client that is master for this slave */
    int replstate;
    unsigned int maxclients;
    unsigned long long maxmemory;
    unsigned int blpop_blocked_clients;
    unsigned int vm_blocked_clients;
    /* 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;
    /* 以下部分先不考虑 */
    /* Virtual memory configuration */
    int vm_enabled;
    char *vm_swap_file;
    off_t vm_page_size;
    off_t vm_pages;
    unsigned long long vm_max_memory;
    /* Hashes config */
    size_t hash_max_zipmap_entries;
    size_t hash_max_zipmap_value;
    /* Virtual memory state */
    FILE *vm_fp;
    int vm_fd;
    off_t vm_next_page; /* Next probably empty page */
    off_t vm_near_pages; /* Number of pages allocated sequentially */
    unsigned char *vm_bitmap; /* Bitmap of free/used pages */
    time_t unixtime;    /* Unix time sampled every second. */
    /* Virtual memory I/O threads stuff */
    /* An I/O thread process an element taken from the io_jobs queue and
     * put the result of the operation in the io_done list. While the
     * job is being processed, it's put on io_processing queue. */
    list *io_newjobs; /* List of VM I/O jobs yet to be processed */
    list *io_processing; /* List of VM I/O jobs being processed */
    list *io_processed; /* List of VM I/O jobs already processed */
    list *io_ready_clients; /* Clients ready to be unblocked. All keys loaded */
    pthread_mutex_t io_mutex; /* lock to access io_jobs/io_done/io_thread_job */
    pthread_mutex_t obj_freelist_mutex; /* safe redis objects creation/free */
    pthread_mutex_t io_swapfile_mutex; /* So we can lseek + write */
    pthread_attr_t io_threads_attr; /* attributes for threads creation */
    int io_active_threads; /* Number of running I/O threads */
    int vm_max_threads; /* Max number of I/O threads running at the same time */
    /* Our main thread is blocked on the event loop, locking for sockets ready
     * to be read or written, so when a threaded I/O operation is ready to be
     * processed by the main thread, the I/O thread will use a unix pipe to
     * awake the main thread. The followings are the two pipe FDs. */
    int io_ready_pipe_read;
    int io_ready_pipe_write;
    /* Virtual memory stats */
    unsigned long long vm_stats_used_pages;
    unsigned lon
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值