深入Redis原理与应用——Redis中的服务端

深入Redis原理与应用——Redis中的服务端

  • 命令请求的执行过程
  • 执行过程解析
  • serverCron 函数
  • 初始化服务器

命令请求的执行过程

(1)客户端向服务器发送 SET KEY VALUE。
(2) 服务器接收并处理客户端发来的请求,在数据库中进行设置操作,并产生命令回复 OK。
(3)服务器将命令回复 OK 发送给客户端。
(4)客户端接收服务器返回的命令回复 OK,并将这个回复打印给用户看。

执行过程解析

(1)发送的命令请求来自 redis 客户端,当用户在客户端中键入一个命令时,客户端会将这个命令请求转换成协议格式,然后通过连接到服务器的套接字将协议格式的命令请求发送给服务器。

(2)读取命令请求:当客户端与服务器间的套接字因为客户端的写入而变得可读时,服务器将调用命令请求处理器来执行以下操作:

  • 读取套接字中协议格式的命令请求,并将其保存到客户端状态的输入缓冲区里。
  • 对输入缓冲区的命令请求进行分析,提取出命令请求中包含的命令参数以及个数,将其保存在 argv 和 argc 属性中。
  • 调用命令执行器,执行客户端指定的命令。

(3)命令执行器:

  • 查找命令实现:根据 argv[0]的值在命令表中查找参数所指定的命令并将其保存在客户端状态的 cmd 中。命令表是一个字典,key 为命令名称,value 为 redisCommand 结构。
  • 执行预备操作:真正执行命令之前程序会进行一些预备操作,如检查 cmd 指针是否为null、命令请求的参数个数是否正确、是否通过身份验证等。
  • 调用命令的实现函数: client->cmd->proc(client) client 是指向客户端状态的指针。由于参数已经设置在客户端状态的 argv 属性中,所以直接执行就行。执行产生的命令回复会保存在客户端状态的输出缓冲区中,之后实现函数还会为客户端的套接字关联命令回复处理器,该处理器负责将命令回复返回给客户端。
  • 执行后续操作:更新查询日志;更新执行命令 redisCommand 结构的 calls 计数器加一,并更新 milliseconds 属性;若开启 AOF 持久化功能则 AOF 持久化模块会将刚刚的执行的命令写入到 AOF 缓冲器中;若其它服务器正在复制这台服务器,那么服务器将会将刚刚的操作传播给所有服务器。

(4)将命令回复发给客户端:前面已经将回复内容保存到输出缓冲区中了,当客户端套接字的状态为可写时服务器就会执行命令回复处理器将输出缓冲区中的数据发送给客户端。发送完毕清空输出缓冲区为下一次输出做准备。
(5)客户端接收并打印命令回复

serverCron 函数

(1)redis 服务器中的 serverCron 函数默认每隔 100 毫秒执行一次。该函数复制管理服务器的资源并保持服务器自身的良好运转。以下是该函数的作用:

  • 更新服务器时间缓存:更新 unixtime 属性和 mstime 属性,由于 serverCron 的频率为100 毫秒一次,所以这两属性的精确度并不高。
  • 更新 LRU 时钟。
  • 更新服务器每秒执行的次数。
  • 更新服务器内存峰值记录。
  • 处理 SIGTERM 信号:关闭自身之前会先进行 RDB 持久化操作,这也是服务器拦截 SIGTERM信号的原因。
  • 管理客户端资源:若客户端连接超时则会释放当前客户端;若客户端在上一次执行命令请求之后输入缓冲区大小超过一定限制,那么程序会释放客户端当前的输入缓冲区并重新创建一个默认大小的输入缓冲区从而防止输入缓冲区耗费过多内存。
  • 管理数据库资源:如检查并删除过期的键并在有需要时对字典进行收缩。
  • 执行被延迟的 BGREWRITEAOF:若服务器在执行 BGSAVE 期间客户端发来 BGREWRITEAOF请求则其会被延迟到 BGSAVE 命令之后执行。
  • 检查持久化操作的运行状态:查看是否有 BGREWRITEAOF 操作被延迟,若有则开始一次新的 BGREWRITEAOF 操作;检查服务器自动保存条件是否满足,若满足且没在执行其它持久化操作则开始一次新的 BGSAVE;检查 AOF 重写条件是否满足,如果满足且没在执行其它持久化操作则会开始一次新的 BGWRITEAOF 操作。
  • 将 AOF 缓冲区的内容写入 AOF 文件中。
  • 关闭异步客户端

初始化服务器

(1)初始化服务器状态结构:第一步是创建一个 redisServer 类型的实例变量 server 作为服务器的状态,并为结构中的各个属性设置默认值。初始化 server 变量的工作由initServerConfig 函数完成。
(2)载入配置选项:通过指定配置文件的方式修改了服务器的数据库配置。
(3)初始化服务器的数据结构:在 initServerConfig 函数中只创建了命令表一个数据结构,然而服务器还需要其它数据结构,比如 server.clients 链表(记录了与服务器相连的每个客户端的状态)、server.db 数组(包含了服务器的所有数据库)等等。
(4)然后将会调用 initServer 函数为以上数据结构分配内存,并在有需要时为这些数据结构关联初始值。(initServerConfig 主要负责初始化一般属性,initServer 主要负责初始化数据结构)
(5)除了初始化数据结构,initServer 还进行一些比较重要的设置:为服务器设置进程信号处理器;创建一些常用的共享对象,比如 OK、ERR 的字符串以及整数 1 到 10000 的字符对象等等;打开服务器的监听端口并为监听套接字关联连接应答事件处理器,等待服务器正式运行后接收客户端连接;为 serverCron 创建时间事件,等待服务器正式运行时执行serverCron 函数;如果 AOF 持久化功能打开,那么打开现有的 AOF 文件,如果 AOF 文件不存在则创建并打开一个新的 AOF 文件;初始化服务器的后台 IO 模块。
(6)还原数据库状态:在完成了对服务器状态 server 的初始化之后服务器需要载入 RDB 文件或者 AOF 文件,并根据文件记录来还原数据库状态。若开启了 AOF 持久化功能则由 AOF 文件还原数据库状态;否则使用 RDB 还原数据库状态。
(7)开始执行事件循环

你可能感兴趣的:(深入Redis原理,redis,java,服务器)