客户端
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文件,完成后打印时长。