客户端
客户端的数据结构:
typedef struct redisClient {
int fd;
robj *name;
sds querybuf;
robj **argv; // 命令及参数
int argc; // argv 的长度
struct redisCommand *cmd;
char bug[REDIS_REPLY_CHUNK_BYTES];
int bufpos;
list *reply;
int authenticated;
time_t ctime;
time_t lastinteraction;
time_t obuf_soft_limit_reached_time; // 输出缓冲区第一次达到软性限制的时间
...
} redisClient;
- 套接字描述符 fd
- 根据客户端的类型,属性的值可以是 -1 或者大于 -1 的整数。
- 伪客户端的属性值为 -1,伪客户端的命令请求来源于 AOF 文件或者 Lua 脚本,而不是网络,这种客户端不需要套接字连接。
- client list 命令列出目前所有连接到服务器的普通客户端
- 名字 name
- client setname
- 标志值 flags
- 记录客户端的角色,以及客户端目前所处的状态
- REDIS_MASTER // 客户端是一个主服务器
- REDIS_BLOCKED // 客户端正在被列表命令阻塞
- 指向客户端正在使用的数据库的指针,以及该数据库的号码
- 当前要执行的命令、命令的参数、命令的个数,以及指向命令实现函数的指针
- 输入缓冲区 querybuf
- 大小根据输入内容动态地缩小或者扩大,最大 1GB,否则服务器将关闭这个客户端
- 输出缓冲区
- 每个客户端都有两个输出缓冲区,一个大小是固定的,另一个大小是可变的
- 固定大小的缓冲区保存长度较小的回复,比如 OK、简短的字符串值、整数值、错误回复
- 可变大小的缓冲区保存长度比较大的回复
- 服务器使用软性限制、硬性限制来限制客户端输出缓冲区的大小
- client-output-buffer-limit
- 复制状态信息,以及复制所需的数据结构
- 执行 BRPOP、BLPOP 等列表阻塞命令时使用的数据结构
- 事务状态,以及执行 WATCH 命令时用到的数据结构
- 执行发布与订阅功能时用到的数据结构
- 身份验证标志
- 客户端的创建时间,客户端和服务器最后一次通信时间,以及客户端的输出缓冲区大小超过软性限制的时间
pubsub 命令和 script load 命令的特殊性
虽然 pubsub 和 script load 命令没有修改数据库,但它修改了服务器状态,服务器需要使用 REDIS_FORCE_AOF 标志强制将这个命令写入 AOF 文件,使用 REDIS_FORCE_PERL 标志强制将 script load 命令复制给所有从服务器。
服务器
redisCommand 结构
typedef struct redisCommand {
char* name;
redisCommandProc *proc;
int arity;
char* sflags; // 记录了命令的属性,比如是写命令还是读命令,是否允许在载入数据时使用等等
int flags; // sflags 的二进制
long long calls;
long long milliseconds;
...
} redisCommand;
sflags
serverCron(默认100ms更新一次)
-
更新服务器时间缓存
-
struct redisServer { time_t unixtime; // 秒级精度的系统当前 UNIX 时间戳 long long mstime; // 毫秒级 ... }
-
服务器只会在打印日志、更新服务器的 LRU 时钟、决定是否执行持久化任务、计算服务器上线时间这类对时间精度要求不高的功能上使用。
-
-
更新 LRU 时钟,默认10s更新一次
-
更新服务器每秒执行命令次数(抽样计算的平均估算值)
-
更新服务器内存峰值记录
-
处理 SIGTERM 信号
-
管理客户端资源
-
管理数据库资源
-
执行被延迟的 BGREWRITEAOF
-
检查持久化操作的运行状态
-
将 AOF 缓冲区中的内容写入 AOF 文件
-
关闭异步客户端
-
增加 cronloops 计数器的值
初始化服务器
- 初始化服务器状态结构
- 载入配置选项
- 初始化服务器数据结构
- 还原数据库状态
- 执行事件循环