一 从一条命令说起之配置文件
当我们谈到 Redis 服务端启动程序时,可能有很多人会想到 redis-server
这个命令。作为 Redis 的核心组件,redis-server
不仅仅是 Redis 服务端启动的命令,还包括了 Redis 的许多配置选项和功能。在这篇博客中,我们将从这个简单的命令入手,一步步了解 Redis 服务端启动的过程和相关的配置选项。无论你是 Redis 初学者还是有一定经验的开发者,相信这篇博客都会对你有所启发和帮助。
1 redis-server
redis-server
是 Redis 的服务端启动程序。它通过监听端口,接收客户端发送的请求,并执行相应的 Redis 命令。在默认情况下,redis-server
启动后会监听 127.0.0.1:6379 这个地址和端口,这意味着只有本地能够连接到 Redis 服务器。
redis-server
命令可以带有多个参数和选项,用于配置 Redis 服务器的不同功能和行为。例如,你可以通过 -p
选项来指定 Redis 监听的端口,通过 -a
选项来设置 Redis 访问密码等等。这些选项和参数将在后续的博客中逐一介绍。
在启动 redis-server
命令之前,你需要确保已经安装了 Redis,并且 Redis 的配置文件已经正确配置。如果你还没有安装 Redis,可以参考官方文档进行安装和配置。
1.1 redis配置文件(简单介绍)
Redis 配置文件是一个文本文件,包含了 Redis 服务器的配置选项和参数。在启动 Redis 服务器时,可以通过命令行参数指定配置文件的路径,例如:
┌──(root㉿kali)-[/opt/local/myconfig]
└─# redis-server redis.conf
┌──(root㉿kali)-[/opt/local/myconfig]
└─# ps aux |grep redis-server
root 8632 0.5 0.1 55480 10268 ? Ssl 14:59 0:00 redis-server 127.0.0.1:6379
复制代码
通过ps aux命令我们可以很清楚的看到redis服务器已经启动且其监听在本机的6379的端口号上。
下面我会简单的介绍一下redis配置文件中的一点点信息,以便于我们能快速的配置出不同端口的服务器,后续的博客中我们将会详细的聊一聊这个话题,如过对这阔比较感兴趣的话,记得点赞点赞哦,废话不多说,下面我们来看看redis的配置文件:
bind:服务器启动的ip地址;
prot:服务器所监听的端口号;
requirepass:认证信息
Redis 配置文件支持 include
模块,可以在一个配置文件中引用另一个配置文件。这个功能非常有用,可以将一些通用的配置选项和参数抽象出来,单独存放在一个文件中,然后在需要的配置文件中通过 include
引用即可。
使用 include
模块非常简单,只需要在配置文件中使用 include
指令即可。例如,下面是一个示例:
# Redis 配置文件示例
# 引用通用配置文件
include redis.cong
# 监听地址和端口
bind 127.0.0.1
port 6380
# 认证密码
requirepass mypassword
# 日志文件路径
logfile /var/log/redis.log
复制代码
在这个示例中,include
指令引用了另一个配置文件 redis.conf
,这个文件包含了一些通用的配置选项和参数。在当前配置文件中,只需要指定一些特定的配置选项即可。
需要注意的是,include
指令可以出现在任何位置,而且可以多次引用不同的配置文件。在解析配置文件时,Redis 会按照 include
指令的顺序逐一引用配置文件,以此来构建最终的配置选项和参数列表。
我们启动看看:
└─# redis-server myredis.conf
复制代码
我们可以明显的看到redis服务器如我们预期所料的一样,在6380号端口启动了。
2 执行了redis-server后,redis会做什么
本文章采用的redis版本为7.0版本
2.1 配置文件处理
服务器启动时会调用 loadServerConfig() 函数,该函数定义在 src/config.c 文件中,用于加载配置文件并解析参数。
通过查找我们可以在src/server.c中发现下述代码
int main(int argc , char* argv[])
{
//...
loadServerConfig(server.configfile, config_from_stdin, options);
//...
}
复制代码
在 Redis 服务器启动时,会读取命令行参数,其中包括配置文件的路径。server.configfile
就是配置文件的路径,它是在 Redis 服务器启动时设置的。
在加载配置文件时,Redis 服务器调用了 loadServerConfig
函数,这个函数会读取配置文件中的选项和参数,并将它们保存在 Redis 服务器的内存中。config_from_stdin
和 options
参数表示是否从标准输入读取配置文件和其他选项,这些选项可以用于在 Redis 服务器启动时进行调试和测试。
在加载配置文件的过程中,Redis 会检查配置文件中的语法错误和非法选项,并在出现错误时输出错误信息。如果配置文件中存在错误,Redis 服务器将无法正常启动。
2.3 来看看loadServerConfig
loadServerConfig
是 Redis 服务器加载配置文件的函数。这个函数的定义位于 src/config.c
文件中。
loadServerConfig
函数的参数包括配置文件的路径、是否从标准输入读取配置文件和其他选项等。函数的主要功能是读取配置文件中的选项和参数,并将它们保存在 Redis 服务器的内存中,以供 Redis 服务器后续的操作使用。
具体来说,loadServerConfig
函数会调用 loadServerConfigFromString
函数读取配置文件内容,并将配置文件内容转换为一个字典对象,其中每个键值对表示一个配置选项和参数。然后,函数会逐一遍历字典对象中的键值对,将其转换为相应的 Redis 服务器配置选项和参数,并保存在 Redis 服务器的内存中。
在读取配置文件时,loadServerConfig
函数会检查配置文件的语法错误和非法选项,并在出现错误时输出错误信息。如果配置文件中存在错误,Redis 服务器将无法正常启动。
总之,loadServerConfig
函数是 Redis 服务器加载配置文件的核心函数,它确保了 Redis 服务器能够正确地读取和解析配置文件,并将配置选项和参数保存在内存中,以供 Redis 服务器后续的操作使用。
该函数的原型如下:
void loadServerConfig(char *filename, char config_from_stdin, char *options)
复制代码
该函数的三个参数的作用分别如下:
filename
:配置文件的路径,如果config_from_stdin
参数为假(即不从标准输入读取配置文件),则 Redis 服务器将从该路径读取配置文件。config_from_stdin
:标志变量,如果该参数为真,Redis 服务器将从标准输入读取配置文件。options
:其他选项,目前只有一个选项,即-test-conf
,用于测试配置文件的语法正确性。
下面是几个 loadServerConfig
函数的例子:
-
从文件加载配置文件
如果要从文件中加载配置文件,可以将
config_from_stdin
参数设为假,然后指定配置文件的路径。例如:loadServerConfig("/path/to/redis.conf", 0, NULL); 复制代码
-
从标准输入加载配置文件
如果要从标准输入中加载配置文件,可以将
config_from_stdin
参数设为真,并将filename
参数设为NULL
。例如:loadServerConfig(NULL, 1, NULL); 复制代码
-
测试配置文件的语法正确性
如果要测试配置文件的语法正确性,可以将
options
参数设为-test-conf
。例如:loadServerConfig("/path/to/redis.conf", 0, "-test-conf"); 复制代码
总之,loadServerConfig
函数的参数和作用比较简单,主要用于指定配置文件的路径和读取方式,并提供了一个用于测试配置文件语法正确性的选项。
我么在细看细看该函数:
void loadServerConfig(char *filename, char config_from_stdin, char *options)
{
sds config = sdsempty();
char buf[CONFIG_READ_LEN+1];
FILE *fp;
glob_t globbuf;
if(filename)
{
//....
}
if(config_from_stdin)
{
//...
}
if(option)
{
//...
}
loadServerConfigFromString(config);
sdsfree(config);
}
复制代码
三个if循环代表了我们传入的三个选项,该函数会自动进行选择要进行的操作,并将解析的信息放入到config里面,供 loadServerConfigFromString使用。
接下来我们会具体分析分析这三个条件判断分别干了什么事
2.4 filename
废话不多说,先看代码:
if (filename) {
if (strchr(filename, '*') || strchr(filename, '?') || strchr(filename, '[')) {
/* A wildcard character detected in filename, so let us use glob */
if (glob(filename, 0, NULL, &globbuf) == 0) {
for (size_t i = 0; i < globbuf.gl_pathc; i++) {
if ((fp = fopen(globbuf.gl_pathv[i], "r")) == NULL) {
serverLog(LL_WARNING,
"Fatal error, can't open config file '%s': %s",
globbuf.gl_pathv[i], strerror(errno));
exit(1);
}
while(fgets(buf,CONFIG_READ_LEN+1,fp) != NULL)
config = sdscat(config,buf);
fclose(fp);
}
globfree(&globbuf);
}
} else {
/* No wildcard in filename means we can use the original logic to read and
* potentially fail traditionally */
if ((fp = fopen(filename, "r")) == NULL) {
serverLog(LL_