Redis 服务端
Redis 服务端通过负责和多个客户端建立网络连接,并处理客户端发送来的命令请求,在数据库中保存命令执行结果,通过自检系统提供稳定服务。
初始化
Redis 服务端对外服务,需要经过一系列的初始化过程,包括:声明全局Server、加载配置、初始化数据结构
声明全局Server
redis.c
/* Global vars */
struct redisServer server; /* server global state */
加载配置
void initServerConfig(void) {
// 设置服务器运行ID
getRandomHexChars(server.runid,REDIS_RUN_ID_SIZE);
// 设置默认配置文件路径
server.configfile = NULL;
// 设置默认服务器频率
server.hz = REDIS_DEFAULT_HZ;
// 为运行ID加上结束符
server.runid[REDIS_RUN_ID_SIZE] = '\0';
// 设置服务器运行架构
server.arch_bits = (sizeof(long) == 8) ? 64 : 32;
// 设置服务器默认端口号
server.port = REDIS_SERVERPORT;
// ...
}
初始化数据结构
void initServer(void) {
// ...
// 服务器运行的进程 ID
server.pid = getpid();
// 设置当前客户端为 NULL
server.current_client = NULL;
// redisClient 结构实例链表,保存所有与服务器相连接的客户端的状态结构
server.clients = listCreate();
// 设置从服务器列表
server.slaves = listCreate();
// db数组,包含所有服务器的数据库
server.db = zmalloc(sizeof(redisDb)*server.dbnum);
// ...
}
此外,初始化还包括:
- 创建共享对象
- 创建事件循环,打开服务器监听端口,为套接字关联连接应答事件处理器,等待客户端连接
- 创建 serverCron 时间事件
- 初始化服务脚本缓存
- 初始化慢查询日志
- 初始化主从服务器
- …
至此,Redis 服务器初始化完成。
处理连接请求
服务器初始化后,程序会将连接应答处理器和服务器监听套接字的AE_READABLE 事件关联,当客户端使用 connect 函数连接服务端监听的套接字时,I/O 多路复用程序收到套接字产生 AE_READABLE 事件,引发连接应答处理器执行。
处理命令请求
客户端
用户输入命令 ——> 客户端转化成协议格式——> 发送到服务端
服务端
- 读取套接字中协议格式的命令请求——> 保存到 redisClient 结构的 querybuf 缓冲区。
- 分析协议格式的命令,提取参数和参数数量分别保存到 redisClient 结构的 argv 和 argc 属性中。
- 调用命令执行器,执行客户端发送过来的命令。
serverCron
serverCron 函数负责管理服务器的资源,保持服务器的良好运行。
主要职责包括:
- 更新服务器事缓存事件
- 更新空转(LRU)时钟
- 更新服务器每秒执行命令次数
- 更新服务器内存峰值记录
- 处理SIGTERM信号
- 管理客户端资源
- 管理数据库资源
- 执行被延迟的 BGREWRITEAOF 命令
- 将 AOF 缓冲区内从写入到 AOF 文件
- 检查持久化运行状态
- 关闭异步客户端
- 增加 cronloops 计数器的值