客户端

redis服务器是一对多服务器,服务器状态结构的clients属性是一个链表,可以对客户端执行批量操作。客户端状态包含两类,通用属性和特定功能属性。

typedef struct redisClient{
    int fd;
    robj *name;//客户端名称
    int flags;//客户端角色

    sds querybuf;//输入缓冲区

    robj **argv;//命令参数
    int argc;//参数个数

    struct redisCommand *cmd;

    char buf[REDIS_REPLY_CHUNK_BYTES];//输出缓冲
    list *reply;//链表缓冲输出
    int bufpos;

    int authenticated;//身份验证,0表示未通过,1表示通过

}redisClient

fd属性来记录客户端描述符,-1表示伪客户端,普通客户端为大于1的整数。flags记录客户端的角色和状态,redis.h定义了所有的标志。querybuf包含了输入缓冲区的内容,根据输入内容动态扩展。解析完成querybuf之后,服务器解析命令请求后将保存到argv和argc中。redisCommand保存了命令的实现函数、标志、参数个数、总执行次数等,服务的就调用该字段执行客户端命令。

buf是字节数组,是固定大小的。reply用链表来保存输出。

服务器使用新添加的客户端状态会放到链表的末尾。

输出缓冲区限制有两种,如果超过服务器设置的限制客户端会立即关闭;

服务器

redis服务器负责与多个客户端建立连接,处理客户端发送的命令,并保存数据。当客户端想服务端发送命令,执行流程如下:

  • 1)客户端向服务端发送命令请求
  • 2)服务器接收并处理,并在数据库中设置操作,并回复OK
  • 3)发送OK命令至客户端
  • 4)打印到OK窗口

命令执行器

查找命令:执行对应进行解析,内置的命令表是一个字典,字典的值是一个redisCommand结构。
执行预备操作:进行一些预备操作确保命令可以正确顺利的被执行。检查命令指针是否为null,检查参数是否正确,检查身份验证,检查内存占用情况等。
调用命令的实现函数:执行client->cmd->proc就可以执行对应的命令函数,产生相应的回复将保存到buf字段里。
后续工作:日志慢查询,命令时长,AOF缓冲区,传播到其他服务器等。

serverCron函数

默认100毫秒执行一次,负责管理服务器的资源。

struct redisServer{
    time_t unixtime;//秒级精度时间戳

    long long mstime;//毫秒精度时间戳

    unsigned lurclock:22;//lru时钟
    unsigned lru:22;//对象最后访问时间

    size_t stat_peak_memory;//使用内存峰值

    int shutdown_asap;//服务器关闭标识
}

unixtime属性和mstime当作时间缓存,精度不高。lru用于计算键的空转时长。

trackOperationsPerSecond函数会100毫秒一次估计并记录服务器最近一秒钟处理的命令请求数量。

serverCron会调用clientsCron检查客户端,包括连接超时和缓冲区大小检查。

调用databaseCron检查数据库,删除过期键,并根据需要收缩字典。

初始化服务器

初始化服务器状态结构,initServerConfig函数设置运行id、运行频率、配置文件路径、端口号、RDB和AOF、LRU等

redis.conf可以配置启动项,初始化完成后载入RDB或AOF文件,完成后打印时长。