redis源码阅读1-----redis的启动过程
redis版本:6.2.6
为了调试方便,配置文件绝大部分保持一致,只修改如下:
daemonize no。
关闭后台运行。这会影响debug,因为在server.c/6312行会进入daemonize(),然后执行setsid(),这样会导致debug退出。
然后将断点打在server.c/6157行。开始debug。
另外server相关的结构体都在server.h/1146行
最初始的几个函数主要用于设置时区,设置字符,设置地域,设置随机种子等,主要调用如下函数:
#ifdef INIT_SETPROCTITLE_REPLACEMENT spt_init(argc, argv); #endif setlocale(LC_COLLATE,""); tzset(); /* Populates 'timezone' global. */ zmalloc_set_oom_handler(redisOutOfMemoryHandler); srand(time(NULL)^getpid()); srandom(time(NULL)^getpid()); gettimeofday(&tv,NULL); init_genrand64(((long long) tv.tv_sec * 1000000 + tv.tv_usec) ^ getpid()); crc64_init(); umask(server.umask = umask(0777)); uint8_t hashseed[16]; getRandomBytes(hashseed,sizeof(hashseed)); dictSetHashFunctionSeed(hashseed); 然后如果你开启了哨兵模式,那么会通过如下函数进行检查: server.sentinel_mode = checkForSentinelMode(argc,argv); 哨兵模式如果开启,那么会单独于redis单实例进行初始化和检查。因为哨兵模式比起单实例的配置会有所不同。 这其中最主要的函数为initSentinelConfig和initSentinel。 然后开始最重要的参数检查 initServerConfig(); 这部分主要调用 initConfigValues();函数。 随后会对tls和module进行初始化。 ACLInit(); /* The ACL subsystem must be initialized ASAP because the basic networking code and client creation depends on it. */ moduleInitModulesSystem(); tlsInit(); 然后会重新检查一遍哨兵模式: if (server.sentinel_mode) { initSentinelConfig(); initSentinel(); } 然后开始检查aof和rdb: if (strstr(argv[0],"redis-check-rdb") != NULL) redis_check_rdb_main(argc,argv,NULL); else if (strstr(argv[0],"redis-check-aof") != NULL) redis_check_aof_main(argc,argv); 然后如果argc>=2,那么会重新检查一下命令行参数。没有太多意义,就不贴函数了。 不过在这个if最后,会加载参数和再一次检查是否开启哨兵模式,如下: loadServerConfig(server.configfile, config_from_stdin, options); if (server.sentinel_mode) loadSentinelConfigFromQueue(); 当然如果argc<2,那么随后来的还是检查哨兵模式: if (server.sentinel_mode) sentinelCheckConfigFile(); 然后检查redis的supervised和backgroud。生产上daemonize肯定设置的yes,不过正如前文所说,为了调试方便,此处我们设置为no。 server.supervised = redisIsSupervised(server.supervised_mode); int background = server.daemonize && !server.supervised; if (background) daemonize(); 最后就开始初始化服务,设置PID文件,检查tcp连接。 readOOMScoreAdj(); initServer(); if (background || server.pidfile) createPidFile(); if (server.set_proc_title) redisSetProcTitle(NULL); redisAsciiArt(); checkTcpBacklogSettings(); 然后如果你开启了aof或者rdb,那么还会加载数据 loadDataFromDisk(); 最后redis检查下部分参数,没有问题user就能进行连接。 随后进入ae事件监听,redis启动成功。