文章目录
- 前言
- 一、命令执行过程
- 1.客户端发送命令
- 2.服务端读取命令请求
- 二、serverCron函数
- 1.更新服务器的时间缓存
- 2.更新LRU时钟
- 3.更新内存峰值
- 4.处理sigterm信号
- 5.管理客户端资源
- 6.管理数据库资源
- 三、服务器初始化
- 1.初始化服务器redisserver结构体
- 2.载入配置选项
- 3.初始化服务端数据结构
- 4.还原数据库状态
- 5.执行事件循环
- 总结
前言
Redis服务器负责和多个客户端建立网络连接,为多个客户端提供服务,本文对Redis服务器进行简要介绍,包括客户端到服务器的命令执行过程、服务器执行的周期性函数以及服务器的初始化。
一、命令执行过程
1.客户端发送命令
Redis 服务器的命令请求来自 Redis 客户端, 当用户在客户端中键入一个命令请求时, 客户端会将这个命令请求转换成协议格式, 然后通过连接到服务器的套接字, 将协议格式的命令请求发送给服务器, 如下 所示:
假如客户端输入以下命令:
代码语言:javascript复制SET KEY VALUE
客户端会将命令转换成以下内容发送出去:
代码语言:javascript复制*3rn$3rnSETrn$3rnKEYrn$5rnVALUErn
2.服务端读取命令请求
服务端检测到客户端套接字的可读事件以后,将执行以下操作: a.从套接字读取命令内容,放入客户端的接收缓冲区 b.从接收缓冲区分析命令,将命令参数和参数数目分别存放在客户端的argv和argc成员中 c.根据命令名称argv[0]查找服务端的命令表,得到该命令的redisCommand结构,服务端命令表如下所示:
代码语言:javascript复制struct redisServer {
// 命令表(受到 rename 配置选项的作用)
dict *commands; /* Command table */
// 命令表(无 rename 配置选项的作用)
dict *orig_commands; /* Command table before command renaming. */
};
可以看出命令表是一个词典,key是命令名字,值是命令对应的redisCommand结构,redisCommand示意图如下,其中proc是命令的执行函数,arity是命令的参数个数。
命令表示意图如下:
d.查找到rediscommand结构后用客户端的cmd成员中,如下所示:
代码语言:javascript复制struct redisClient{
// 记录被客户端执行的命令
struct redisCommand *cmd;
};
f.在命令执行之前,先要进行检查,比如检查参数个数是否正确、检查客户端是否进行身份验证等。 g.所有验证通过以后,通过以下方法就可以调用对应的函数执行命令了:
代码语言:javascript复制client->cmd->proc(client);
//set命令调用后转到以下函数
/* SET key value [NX] [XX] [EX <seconds>] [PX <milliseconds>] */
void setCommand(redisClient *c) {
int j;
robj *expire = NULL;
int unit = UNIT_SECONDS;
int flags = REDIS_SET_NO_FLAGS;
// 设置选项参数
for (j = 3; j < c->argc; j ) {
char *a = c->argv[j]->ptr;
robj *next = (j == c->argc-1) ? NULL : c->argv[j 1];
if ((a[0] == 'n' || a[0] == 'N') &&
(a[1] == 'x' || a[1] == 'X') && a[2] == '