【redis源码学习】redis启动并读取配置文件的过程

文章详细解释了Redis启动时如何解析配置文件名、命令行参数,并加载配置项的过程,涉及选项如端口、保存间隔、主从复制设置等。
摘要由CSDN通过智能技术生成

/* 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++;

}

//略

resetServerSaveParams();

loadServerConfig(configfile,options); //从配置文件中加载所有配置项,见下文

sdsfree(options);

}

//略

initServer();

//略

redisSetCpuAffinity(server.server_cpulist);

aeMain(server.el);

aeDeleteEventLoop(server.el);

return 0;

}


initServerConfig

学习一下,毕竟不是每次启动都非得带上配置文件不是?

void initServerConfig(void) {

int j;

updateCachedTime(1);

getRandomHexChars(server.runid,CONFIG_RUN_ID_SIZE);

server.runid[CONFIG_RUN_ID_SIZE] = ‘\0’;

changeReplicationId();

clearReplicationId2();

server.hz = CONFIG_DEFAULT_HZ; /* Initialize it ASAP, even if it may get

updated later after loading the config.

This value may be used before the server

is initialized. */

server.timezone = getTimeZone(); /* Initialized by tzset(). */

server.configfile = NULL;

//略

/* Replication related */

server.masterauth = NULL;

server.masterhost = NULL;

server.masterport = 6379;

server.master = NULL;

//略

/* By default we want scripts to be always replicated by effects

  • (single commands executed by the script), and not by sending the

  • script to the slave / AOF. This is the new way starting from

  • Redis 5. However it is possible to revert it via redis.conf. */

server.lua_always_replicate_commands = 1;

initConfigValues();

}


loadServerConfigFromString

void loadServerConfigFromString(char *config) {

char *err = NULL;

int linenum = 0, totlines, i;

int slaveof_linenum = 0;

sds *lines;

lines = sdssplitlen(config,strlen(config),“\n”,1,&totlines);

for (i = 0; i < totlines; i++) {

sds *argv;

int argc;

linenum = i+1;

lines[i] = sdstrim(lines[i]," \t\r\n");

/* Skip comments and blank lines */

if (lines[i][0] == ‘#’ || lines[i][0] == ‘\0’) continue;

/* Split into arguments */

argv = sdssplitargs(lines[i],&argc);

if (argv == NULL) {

err = “Unbalanced quotes in configuration line”;

goto loaderr;

}

/* Skip this line if the resulting command vector is empty. */

if (argc == 0) {

sdsfreesplitres(argv,argc);

continue;

}

sdstolower(argv[0]);

/* Iterate the configs that are standard */

int match = 0;

for (standardConfig *config = configs; config->name != NULL; config++) {

if ((!strcasecmp(argv[0],config->name) ||

(config->alias && !strcasecmp(argv[0],config->alias))))

{

if (argc != 2) {

err = “wrong number of arguments”;

goto loaderr;

}

if (!config->interface.set(config->data, argv[1], 0, &err)) {

goto loaderr;

}

match = 1;

break;

}

}

if (match) {

sdsfreesplitres(argv,argc);

continue;

}

/* Execute config directives */

if (!strcasecmp(argv[0],“bind”) && argc >= 2) {

int j, addresses = argc-1;

if (addresses > CONFIG_BINDADDR_MAX) {

err = “Too many bind addresses specified”; goto loaderr;

}

/* Free old bind addresses */

for (j = 0; j < server.bindaddr_count; j++) {

zfree(server.bindaddr[j]);

}

for (j = 0; j < addresses; j++)

server.bindaddr[j] = zstrdup(argv[j+1]);

server.bindaddr_count = addresses;

} else if (!strcasecmp(argv[0],“unixsocketperm”) && argc == 2) {

errno = 0;

server.unixsocketperm = (mode_t)strtol(argv[1], NULL, 8);

if (errno || server.unixsocketperm > 0777) {

err = “Invalid socket file permissions”; goto loaderr;

}

} else if (!strcasecmp(argv[0],“save”)) {

if (argc == 3) {

int seconds = atoi(argv[1]);

int changes = atoi(argv[2]);

if (seconds < 1 || changes < 0) {

err = “Invalid save parameters”; goto loaderr;

}

appendServerSaveParams(seconds,changes);

} else if (argc == 2 && !strcasecmp(argv[1],“”)) {

resetServerSaveParams();

}

} else if (!strcasecmp(argv[0],“dir”) && argc == 2) {

if (chdir(argv[1]) == -1) {

serverLog(LL_WARNING,“Can’t chdir to ‘%s’: %s”,

argv[1], strerror(errno));

exit(1);

}

} else if (!strcasecmp(argv[0],“logfile”) && argc == 2) {

FILE *logfp;

zfree(server.logfile);

server.logfile = zstrdup(argv[1]);

if (server.logfile[0] != ‘\0’) {

/* Test if we are able to open the file. The server will not

  • be able to abort just for this problem later… */

logfp = fopen(server.logfile,“a”);

if (logfp == NULL) {

err = sdscatprintf(sdsempty(),

“Can’t open the log file: %s”, strerror(errno));

goto loaderr;

}

fclose(logfp);

}

} else if (!strcasecmp(argv[0],“include”) && argc == 2) {

loadServerConfig(argv[1],NULL);

} else if ((!strcasecmp(argv[0],“client-query-buffer-limit”)) && argc == 2) {

server.client_max_querybuf_len = memtoll(argv[1],NULL);

} else if ((!strcasecmp(argv[0],“slaveof”) ||

!strcasecmp(argv[0],“replicaof”)) && argc == 3) {

slaveof_linenum = linenum;

server.masterhost = sdsnew(argv[1]);

server.masterport = atoi(argv[2]);

server.repl_state = REPL_STATE_CONNECT;

} else if (!strcasecmp(argv[0],“requirepass”) && argc == 2) {

if (strlen(argv[1]) > CONFIG_AUTHPASS_MAX_LEN) {

err = “Password is longer than CONFIG_AUTHPASS_MAX_LEN”;

goto loaderr;

}

/* The old “requirepass” directive just translates to setting

  • a password to the default user. The only thing we do

  • additionally is to remember the cleartext password in this

  • case, for backward compatibility with Redis <= 5. */

ACLSetUser(DefaultUser,“resetpass”,-1);

sds aclop = sdscatprintf(sdsempty(),“>%s”,argv[1]);

ACLSetUser(DefaultUser,aclop,sdslen(aclop));

sdsfree(aclop);

sdsfree(server.requirepass);

server.requirepass = sdsnew(argv[1]);

} else if (!strcasecmp(argv[0],“list-max-ziplist-entries”) && argc == 2){

/* DEAD OPTION */

} else if (!strcasecmp(argv[0],“list-max-ziplist-value”) && argc == 2) {

/* DEAD OPTION */

} else if (!strcasecmp(argv[0],“rename-command”) && argc == 3) {

struct redisCommand *cmd = lookupCommand(argv[1]);

int retval;

if (!cmd) {

err = “No such command in rename-command”;

goto loaderr;

}

/* If the target command name is the empty string we just

  • remove it from the command table. */

retval = dictDelete(server.commands, argv[1]);

serverAssert(retval == DICT_OK);

/* Otherwise we re-add the command under a different name. */

if (sdslen(argv[2]) != 0) {

sds copy = sdsdup(argv[2]);

retval = dictAdd(server.commands, copy, cmd);

if (retval != DICT_OK) {

sdsfree(copy);

err = “Target command name already exists”; goto loaderr;

}

}

} else if (!strcasecmp(argv[0],“cluster-config-file”) && argc == 2) {

zfree(server.cluster_configfile);

server.cluster_configfile = zstrdup(argv[1]);

} else if (!strcasecmp(argv[0],“client-output-buffer-limit”) &&

argc == 5)

{

int class = getClientTypeByName(argv[1]);

unsigned long long hard, soft;

int soft_seconds;

if (class == -1 || class == CLIENT_TYPE_MASTER) {

总结

至此,文章终于到了尾声。总结一下,我们谈论了简历制作过程中需要注意的以下三个部分,并分别给出了一些建议:

  1. 技术能力:先写岗位所需能力,再写加分能力,不要写无关能力;
  2. 项目经历:只写明星项目,描述遵循 STAR 法则;
  3. 简历印象:简历遵循三大原则:清晰,简短,必要,要有的放矢,不要海投;

以及最后为大家准备的福利时间:简历模板+Java面试题+热门技术系列教程视频

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

mp(argv[0],“client-output-buffer-limit”) &&

argc == 5)

{

int class = getClientTypeByName(argv[1]);

unsigned long long hard, soft;

int soft_seconds;

if (class == -1 || class == CLIENT_TYPE_MASTER) {

总结

至此,文章终于到了尾声。总结一下,我们谈论了简历制作过程中需要注意的以下三个部分,并分别给出了一些建议:

  1. 技术能力:先写岗位所需能力,再写加分能力,不要写无关能力;
  2. 项目经历:只写明星项目,描述遵循 STAR 法则;
  3. 简历印象:简历遵循三大原则:清晰,简短,必要,要有的放矢,不要海投;

以及最后为大家准备的福利时间:简历模板+Java面试题+热门技术系列教程视频

[外链图片转存中…(img-UG8E2UEz-1714518721710)]

[外链图片转存中…(img-UWAF1KUu-1714518721710)]

[外链图片转存中…(img-4Op0aLUW-1714518721710)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 27
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值