文章目录
- 配置文件
- redisServer
- main函数
- initServerConfig
- loadServerConfigFromString
配置文件
一个好的项目,是无状态的。 状态在哪里?在配置文件里。
这不我的毕设马上要用到开机配置文件了嘛,但是没有什么太好的想法,于是就想着学学redis是如何实现这个过程的,学完马上就能学以致用了。
redis服务器的启动命令如下:
代码语言:javascript复制redis-server [configfile] [options]
configfile 参数指定配置文件,options 参数指定启动配置项,可以覆盖配置文件中的配置项。
举个栗子:
代码语言:javascript复制redis-server ./redis.conf --port 6380 --protected-mode no
redisServer
关于配置信息,存储在如下结构体中:
代码语言:javascript复制//结构体稍微有点庞大(接近2W字),所以我稍微缩写一点哈,具体后面有用到再拿出来
struct redisServer {
/* General */
pid_t pid; /* Main process pid. */
char *configfile; /* Absolute config file path, or NULL */
char *executable; /* Absolute executable file path. */
char **exec_argv; /* Executable argv vector (copy). */
···
}
main函数
这是一个极长的函数,不过没有那个结构体长,而我们此次要学的技法也主要是在这里面,所以还是能接受的。
代码语言:javascript复制int main(int argc, char **argv) {
struct timeval tv;
int j;
#ifdef REDIS_TEST
//这里略去
#endif
/* We need to initialize our libraries, and the server configuration. */
#ifdef INIT_SETPROCTITLE_REPLACEMENT
spt_init(argc, argv); //修改进程名
#endif
//此处略去一批
server.sentinel_mode = checkForSentinelMode(argc,argv); // 检查服务器是否以 Sentinel 模式启动
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. */
if (server.sentinel_mode) { //今天不讲哨兵,所以不管它
initSentinelConfig();
initSentinel();
}
//略
//开始了
if (argc >= 2) {
j = 1; /* First option to parse in argv[] */
sds options = sdsempty();
char *configfile = NULL;
/* Handle special options --help and --version */
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 4096nn");
exit(1);
}
}
/* 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 6380n" 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 ;
}
//略
resetServerSaveParams();
loadServerConfig(configfile,options); //从配置文件中加载所有配置项,见下文
sdsfree(options);
}
//略
initServer();
//略
redisSetCpuAffinity(server.server_cpulist);
aeMain(server.el);
aeDeleteEventLoop(server.el);
return 0;
}
initServerConfig
学习一下,毕竟不是每次启动都非得带上配置文件不是?
代码语言:javascript复制void initServerConfig(void) {
int j;
updateCachedTime(1);
getRandomHexChars(server.runid,CONFIG_RUN_ID_SIZE);
server.runid[CONFIG_RUN_ID_SIZE] = '