1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
| int main(int argc, char **argv) { struct timeval tv; /* We need to initialize our libraries, and the server configuration. */ // 初始化库 #ifdef INIT_SETPROCTITLE_REPLACEMENT spt_init(argc, argv); #endif setlocale(LC_COLLATE,""); zmalloc_enable_thread_safeness(); zmalloc_set_oom_handler(redisOutOfMemoryHandler); srand(time(NULL)^getpid()); gettimeofday(&tv,NULL); dictSetHashFunctionSeed(tv.tv_sec^tv.tv_usec^getpid()); // 检查服务器是否以 Sentinel 模式启动 server.sentinel_mode = checkForSentinelMode(argc,argv); // 初始化服务器 initServerConfig(); /* We need to init sentinel right now as parsing the configuration file * in sentinel mode will have the effect of populating the sentinel * data structures with master nodes to monitor. */ // 如果服务器以 Sentinel 模式启动,那么进行 Sentinel 功能相关的初始化 // 并为要监视的主服务器创建一些相应的数据结构 if (server.sentinel_mode) { initSentinelConfig(); initSentinel(); } // 检查用户是否指定了配置文件,或者配置选项 if (argc >= 2) { int j = 1; /* First option to parse in argv[] */ sds options = sdsempty(); char *configfile = NULL; /* Handle special options --help and --version */ // 处理特殊选项 -h 、-v 和 --test-memory if (strcmp(argv[1], "-v") == 0 || strcmp(argv[1], "--version") == 0) version(); if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) usage(); if (strcmp(argv[1], "--test-memory") == 0) { if (argc == 3) { memtest(atoi(argv[2]),50); exit(0); } else { fprintf(stderr,"Please specify the amount of memory to test in megabytes.\n"); fprintf(stderr,"Example: ./redis-server --test-memory 4096\n\n"); exit(1); } } /* First argument is the config file name? */ // 如果第一个参数(argv[1])不是以 "--" 开头 // 那么它应该是一个配置文件 if (argv[j][0] != '-' || argv[j][1] != '-') configfile = argv[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. */ // 对用户给定的其余选项进行分析,并将分析所得的字符串追加稍后载入的配置文件的内容之后 // 比如 --port 6380 会被分析为 "port 6380\n" while(j != argc) { if (argv[j][0] == '-' && argv[j][1] == '-') { /* Option name */ 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++; } if (configfile) server.configfile = getAbsolutePath(configfile); // 重置保存条件 resetServerSaveParams(); // 载入配置文件, options 是前面分析出的给定选项 loadServerConfig(configfile,options); sdsfree(options); // 获取配置文件的绝对路径 if (configfile) server.configfile = getAbsolutePath(configfile); } else { redisLog(REDIS_WARNING, "Warning: no config file specified, using the default config. In order to specify a config file use %s /path/to/%s.conf", argv[0], server.sentinel_mode ? "sentinel" : "redis"); } // 将服务器设置为守护进程 if (server.daemonize) daemonize(); // 创建并初始化服务器数据结构 initServer(); // 如果服务器是守护进程,那么创建 PID 文件 if (server.daemonize) createPidFile(); // 为服务器进程设置名字 redisSetProcTitle(argv[0]); // 打印 ASCII LOGO redisAsciiArt(); // 如果服务器不是运行在 SENTINEL 模式,那么执行以下代码 if (!server.sentinel_mode) { /* Things not needed when running in Sentinel mode. */ // 打印问候语 redisLog(REDIS_WARNING,"Server started, Redis version " REDIS_VERSION); #ifdef __linux__ // 打印内存警告 linuxOvercommitMemoryWarning(); #endif // 从 AOF 文件或者 RDB 文件中载入数据 loadDataFromDisk(); // 启动集群? if (server.cluster_enabled) { if (verifyClusterConfigWithData() == REDIS_ERR) { redisLog(REDIS_WARNING, "You can't have keys in a DB different than DB 0 when in " "Cluster mode. Exiting."); exit(1); } } // 打印 TCP 端口 if (server.ipfd_count > 0) redisLog(REDIS_NOTICE,"The server is now ready to accept connections on port %d", server.port); // 打印本地套接字端口 if (server.sofd > 0) redisLog(REDIS_NOTICE,"The server is now ready to accept connections at %s", server.unixsocket); } else { sentinelIsRunning(); } /* Warning the user about suspicious maxmemory setting. */ // 检查不正常的 maxmemory 配置 if (server.maxmemory > 0 && server.maxmemory < 1024*1024) { redisLog(REDIS_WARNING,"WARNING: You specified a maxmemory value that is less than 1MB (current value is %llu bytes). Are you sure this is what you really want?", server.maxmemory); } // 运行事件处理器,一直到服务器关闭为止 aeSetBeforeSleepProc(server.el,beforeSleep); aeMain(server.el); // 服务器关闭,停止事件循环 aeDeleteEventLoop(server.el); return 0; }
|