Redis设计与实现第14章 -- 服务器 总结(命令执行器 serverCron函数 初始化)

14.1 命令请求的执行过程

一个命令请求从发送到获得回复的过程中,客户端和服务器都需要完成一系列操作。

14.1.1 发送命令请求

当用户在客户端中输入一个命令请求的时候,客户端会把这个命令请求转换为协议格式,然后通过连接到服务器的套接字,将协议格式的命令请求发送给服务器。

14.1.2 读取命令请求

当客户端与服务器之间的连接套接字因为客户端的写入而变得可读时,服务器将调用命令请求处理器来执行以下操作:
  • 读取套接字中协议格式的命令请求,并将其保存到客户端状态的输入缓冲区里面
  • 对输入缓冲区中的命令请求进行分析,提取出命令请求中包含的命令参数和个数,分别保存到argv/argc属性里面。
  • 调用命令执行器,执行客户端指定的命令

14.1.3 命令执行器1:查找命令实现

根据客户端状态的argv[0]参数,在命令表里查找参数所指定的命令,并将找到的命令保存到客户端状态的cmd属性里。

命令表是一个字典,字典的键是一个个命令名字,字典的值是一个个redisCommend结构。

主要属性有:name 名字、proc 函数指针、arity 命令参数的个数、sflags 字符串形式的标识值、flags 二进制标识、calls 服务器总共执行了多少次这个命令、millseconds 服务器执行这个命令耗费的总时长

sflags属性可以使用的标识值如下:

  • w:写入命令
  • r:只读命令
  • m:可能占用大量内存,内存紧张的话禁用
  • a:管理命令
  • p:发布订阅功能的命令
  • s:不可以在lua脚本执行
  • R:随机命令
  • S:排序
  • l:可以在服务器载入数据的过程中使用
  • t:允许从服务器在带有过期数据时使用的命令
  • M:监视器模式下不会自动被传播

14.1.4 命令执行器2:执行预备操作

+ 检查客户端状态的cmd指针是否指向NULL + 根据客户端cmd属性指向的redisCommand结构的arity属性,检查命令请求所给定的参数个数是否正确。 + 检查客户端是否通过了身份认证 + 如果服务器打开了maxmemory功能,执行命令前先检查服务器的内存占用情况,并在有需要时进行内存回收 + 如果服务器上一次执行BGSAVE命令时出错,并且服务器打开了stop-writes-on-bgsave-error功能,而且即将要执行的是写命令,那么服务器将拒绝执行 + 客户端正在用SUBSCRIBE命令订阅频道,或是正在用PSUBSCRIBE命令订阅模式,服务端只会执行客户端发来的SUBSCRIBE PSUBSCRIBE UNSUBSCRIBE PUNSUBSCRIBE 四个命令,其他命令都会被服务器拒绝 + 如果服务器正在进行数据载入,客户端发送的命令必须要带有l标识才会被执行 + 如果服务器因为执行Lua脚本而超时并进入阻塞状态,服务器只会执行客户端发来的SHUTDOWN nosave和SCRIPT KILL命令 + 如果客户端正在执行事务,只会执行EXEC DISCARD MULTI WATCH 四个命令 + 如果服务器打开了监视器功能,将要执行的命令和参数等信息发送给监视器

14.1.5 命令执行器3:调用命令实现函数

被调用的命令实现函数会执行指定的操作,并产生相应的命令回复,这些回复会被保存在客户端状态的输出缓冲区里,buf属性和reply属性。

14.1.6 命令执行器4:执行后续工作

+ 如果服务器开启了慢查询日志功能,会检查是否需要为刚刚执行完的命令请求添加一条新的慢查询日志 + 根据刚刚执行命令所耗费的时长,更新被执行命令的redisCommand结构的millseconds属性,并将命令的redisCommand结构的calls计数器的值加一 + 如果服务器开启了AOF持久化功能,会将刚刚执行的命令请求写入AOF缓冲区里 + 如果有其他从服务器正在复制当前这个服务器,那么服务器会将刚刚执行的命令传播给所有从服务器

14.1.7 将命令回复发送给客户端

命令实现函数将命令回复保存到客户端的输出缓冲区里面,并为客户端的套接字关联命令回复处理器。

当客户端套接字变成可写状态的时候,服务器就会执行命令回复处理器,将保存在客户端输出缓冲区的命令回复发送给客户端

14.1.8 客户端接收并打印命令回复

客户端收到协议格式的命令回复后,会转化为人类可读的格式。

14.2 serverCron函数

每隔100ms执行一次

14.2.1 更新服务器时间缓存

Redis服务器中有不少功能需要获取系统的当前时间,而每次获取系统的当前时间都需要执行一次系统调用,为了减少系统调用的执行次数,服务器状态中的unixtime属性和mstime属性被用作当前时间的缓存

这两个属性是100ms更新一次的,所以精确度不高

  • 当打印日志、更新服务器的LRU时钟、决定是否执行持久化任务、计算服务器上线时间这种对时间精确度要求不高的功能上才会用
  • 对于为键设置过期时间、添加慢查询日志这种需要高精度时间的功能来说,服务器还是会再次执行系统调用

14.2.2 更新LRU时钟

服务器的lruclock属性保存了服务器的LRU时钟,每个redis对象都会有一个lru属性,保存了对象最后一次被命令访问的时间。当服务器计算数据库键的空转时间的时候,会用服务器的lruclock属性记录的时间减去对象lru属性记录的时间。

serverCron函数默认以10秒一次的频率更新lruclock属性的值

14.2.3 更新服务器每秒执行命令次数

trackOperationsPerSecond函数以每100ms一次的频率执行,功能是以抽样计算的方式,估算并记录服务器在最后一秒钟处理的命令请求数量。

可以通过INFO status命令的instantaneous_ops_per_sec域查看

14.2.4 更新服务器内存峰值记录

服务器状态的stat_peak_memory属性记录了服务器的内存峰值大小

每次serverCron函数执行时,服务器都会查看当前使用的内存数量

14.2.5 处理SIGTERM信号

在启动服务器时,Redis会为服务器进程的SIGTERM信号关联处理器sigtermHandler函数,这个信号处理器负责在服务器接到SIGTERM信号时,打开服务器状态的shutdown_asap 标识

每次serverCron函数运行时,程序都会对shutdown_asap 属性进行检查,并根据属性的值决定是否关闭服务器。值为1表示关闭服务器。

服务器在关闭自身前会进行RDB持久化操作,这也就是服务器拦截SIGTERM信号的原因

14.2.6 管理客户端资源

调用clientsCron函数,对一定数量的客户端进行检查:
  • 连接超时,很久没互动
  • 上一次执行请求命令后,输入缓冲区的大小超过了一定长度,程序会释放客户端当前的输入缓冲区,重新创建一个默认大小的输入缓冲区

14.2.7 管理数据库资源

databasesCron函数,对服务器中的一部分数据库进行检查,1删除过期键,收缩字典等,详情见第9章

14.2.8 执行被延迟的BGREWRITEAOF

在服务器执行BGSAVE命令的期间,如果客户端向服务器发来BGREWRITEAOF命令那么服务器会将 BGREWRITEAOF命令的执行时间延迟到 BGSAVE命令执行完毕之后。服务器的aof_rewrite_scheduled标识记录了服务器是否延迟了BGREWRITEAOF命令

每次serverCron函数执行时,函数都会检查BGSAVE命令或者BGREWRITEAOF命令是否正在执行,如果这两个命令都没在执行,并且aof_rewrite_scheduled属性的值为1,那么服务器就会执行之前被推延的BGREWRITEAOF命令。

14.2.9 检查持久化操作的运行状态

服务器状态使用 rdb_child_pid属性和aof_child_pid属性记录执行 BGSAVE 命令和BGREWRITEAOF命令的子进程的ID,这两个属性也可以用于检查BGSAVE命令或者BGREWRITEAOF命令是否正在执行

每次serverCron函数执行时,程序都会检查这两个属性的值,只要其中一个属性的值不为-1,程序就会执行一次wait3函数,检查子进程是否有信号发给服务器进程

  • 如果有信号到达,那么表示新的RDB文件已经生成完成或是AOF文件已经重写完毕,服务器进行后续的替换操作
  • 如果没有信号,不做动作

如果两个属性的值都是-1,说明没有进行持久化操作,检查:

  • 查看是否有BGREWRITEAOF被延迟了
  • 检查服务器的自动保存条件是否已经被满足,如果条件满足,而且服务器没有在执行其他持久化操作,那么服务器开始一次新的BGSAVE操作
  • 检查服务器设置的AOF重写条件是否满足,如果满足并且没有进行其他持久化操作,服务器开始一次新的BHREWRITEAOF操作

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

14.2.10 将AOF缓冲区文件的内容写入AOF文件

详情见11章

14.2.11 关闭异步客户端

输出缓冲区大小超出限制的客户端,详情见13章

14.2.12 增加cronloops计数器的值

cronloops属性记录了serverCron函数执行的次数,目前唯一的作用就是在复制模块中实现:每执行serverCron函数N次就执行一次指定代码的功能

14.3 初始化服务器

14.3.1 初始化服务器状态结构

创建一个redisServer类型的实例变量server作用服务器的状态,并为结构里的各个属性设置默认值,初始化函数为initServerConfig函数完成,主要工作为:设置服务器的运行ID、默认运行频率、默认配置文件路径、运行架构、默认端口号、默认RDB/AOF持久化条件、LRU时钟、创建命令表

14.3.2 载入配置选项

载入用户给定的配置参数和配置文件,并根据用户设定的配置,对server变量相关属性的值进行修改

14.3.3 初始化服务器数据结构

initServerConfig函数初始化server状态时,只创建了命令表一个数据结构,还有其他数据结构,比如:
  • server.clients链表,记录了和服务端相连的客户端的状态结构
  • server.db数组,包含了服务器的所有数据库
  • 保存频道订阅信息的pubsub_channels字典 保存模式订阅信息的pubsub_patterns链表
  • 执行lua脚本的lua环境
  • 用户保存慢查询日志的slowlog属性

这些都是在initServer函数里执行的,该函数负责初始化数据结构和设置操作,比如

  • 设置进行信号处理器
  • 设置共享对象,比如OK回复的字符串对象
  • 打开服务器的监听端口,并为监听套接字关联连接应答事件处理器,等待服务器正式运行时接受客户端的连接
  • 为serverCron函数创建时间事件,等待服务器正式运行时执行serverCron函数
  • 如果AOF持久化功能打开,创建/打开AOF文件
  • 初始化后台IO模块,bio

14.3.4 还原数据库状态

完成对服务器状态server变量的初始化之后,服务器需要载入RDB文件或AOF文件并根据文件记录的内容来还原服务器的数据库状态。
  • 如果开启了AOF持久化功能,用AOF文件还原
  • 否则,用RDB文件还原

14.3.5 执行事件循环

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/478833.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ArcGIS pro中的回归分析浅析(加更)关于广义线性回归工具的补充内容

在回归分析浅析中篇的文章中, 有人问了一个问题: 案例里的calls数据貌似离散,更符合泊松模型,为啥不采用泊松而采用高斯呢? 确实,在中篇中写道: 在这个例子中我们为了更好地解释变量&#x…

【面试题】2025年百度校招Java后端面试题

文章目录 前言一、网络IO1、服务器处理并发请求有哪几种方式?2、说一下select,poll,epoll的区别?3、Java 有一种现代的处理方式,属于异步I/O,是什么?redis,nginx,netty 是…

【Zookeeper 和 Kafka】为什么 Zookeeper 不用域名?

人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 目录 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌…

RiceChem——用于评估大语言模型在教育领域自动长答卷评分 (ALAG) 的数据集

摘要 论文地址:https://arxiv.org/abs/2404.14316 源码地址:https://github.com/luffycodes/automated-long-answer-grading 迄今为止,教育领域的自然语言处理(NLP)主要集中在简答题评分和自由文本作文评分方面。然而&#xff0c…

Java ArrayList 与顺序表:在编程海洋中把握数据结构的关键之锚

我的个人主页 我的专栏:Java-数据结构,希望能帮助到大家!!!点赞❤ 收藏❤ 前言:在 Java编程的广袤世界里,数据结构犹如精巧的建筑蓝图,决定着程序在数据处理与存储时的效率、灵活性以…

【04】Selenium+Python 手动添加Cookie免登录(实例)

一、什么是Cookie? Cookie 是一种由服务器创建并保存在用户浏览器中的小型数据文件。它用于存储用户的相关信息,以便在后续访问同一网站时可以快速检索这些信息。Cookie 主要用于以下几个方面: 1.状态管理: Cookie 可以保存用户…

GitLab|应用部署

创建docker-compose.yaml文件 输入docker-compose配置 version: 3.8 services:gitlab:image: gitlab/gitlab-ce:15.11.2-ce.0restart: alwayscontainer_name: gitlab-ceprivileged: truehostname: 192.168.44.235environment:TZ: Asia/ShanghaiGITLAB_OMNIBUS_CONFIG: |exter…

【PX4_Autopolite飞控源码】中飞控板初始化过程中的引脚IO控制(拉低/拉高)

先选择自己飞控板支持的硬件平台 打开对应的路径我的是Desktop/px4/PX4-Autopilot/boards/zhty/nora 找到board_config.h文件,打开nora后再往下去找Desktop/px4/PX4-Autopilot/boards/zhty/nora/src/borad_config.h 打开后可以看到有很多GPIO引脚的定义&#xff0c…

如何使用Postman优雅地进行接口自动加密与解密

引言 在上一篇文章中,分享了 Requests 自动加解密的方法,本篇文章分享一下更加方便的调试某个服务端接口。 Postman Postman 这个工具后端小伙伴应该相当熟悉了,一般情况下我们会在开发和逆向过程中使用它来快速向接口发送请求,…

Spring Boot——统一功能处理

1. 拦截器 拦截器主要用来拦截用户的请求,在指定方法前后,根据业务需要执行设定好的代码,也就是提前定义一些逻辑,在用户的请求响应前后执行,也可以在用户请求前阻止其执行,例如登录操作,只有登…

PYTORCH基础语法知识

初识Torch PyTorch,简称Torch,主流的经典的深度学习框架,深度学习的框架。 简介 PyTorch是一个基于Python的深度学习框架,它提供了一种灵活、高效、易于学习的方式来实现深度学习模型。PyTorch最初由Facebook开发,被…

C嘎嘎探索篇:栈与队列的交响:C++中的结构艺术

C嘎嘎探索篇:栈与队列的交响:C中的结构艺术 前言: 小编在之前刚完成了C中栈和队列(stack和queue)的讲解,忘记的小伙伴可以去我上一篇文章看一眼的,今天小编将会带领大家吹奏栈和队列的交响&am…

刷题日常(数据流中的中位数,逆波兰表达式求值,最长连续序列,字母异位词分组)

数据流中的中位数 描述 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()…

SQL 复杂查询

目录 复杂查询 一、目的和要求 二、实验内容 (1)查询出所有水果产品的类别及详情。 查询出编号为“00000001”的消费者用户的姓名及其所下订单。(分别采用子查询和连接方式实现) 查询出每个订单的消费者姓名及联系方式。 在…

uniapp-vue2引用了vue-inset-loader插件编译小程序报错

报错信息 Error: Vue packages version mismatch: - vue3.2.45 (D:\qjy-myApp\admin-app\node_modules\vue\index.js) - vue-template-compiler2.7.16 (D:\qjy-myApp\admin-app\node_modules\vue-template-compiler\package.json) This may cause things to work incorrectly.…

VOLO实战:使用VOLO实现图像分类任务(二)

文章目录 训练部分导入项目使用的库设置随机因子设置全局参数图像预处理与增强读取数据设置Loss设置模型设置优化器和学习率调整策略设置混合精度,DP多卡,EMA定义训练和验证函数训练函数验证函数调用训练和验证方法 运行以及结果查看测试完整的代码 在上…

【Linux】TCP网络编程

目录 V1_Echo_Server V2_Echo_Server多进程版本 V3_Echo_Server多线程版本 V3-1_多线程远程命令执行 V4_Echo_Server线程池版本 V1_Echo_Server TcpServer的上层调用如下,和UdpServer几乎一样: 而在InitServer中,大部分也和UDP那里一样&…

XG(S)-PON原理

前言 近年来,随着全球范围内接入市场的飞快发展以及全业务运营的快速开展,已有的PON技术标准在带宽需求、业务支撑能力以及接入节点设备和配套设备的性能提升等方面都面临新的升级需求XG(S)-PON(10G GPON)是在已有GPON技术标准上演进的增强下一代GPON技…

C语言学习 12(指针学习1)

一.内存和地址 1.内存 在讲内存和地址之前,我们想有个⽣活中的案例: 假设有⼀栋宿舍楼,把你放在楼⾥,楼上有100个房间,但是房间没有编号,你的⼀个朋友来找你玩,如果想找到你,就得挨…

前端---CSS(部分用法)

HTML画页面--》这个页面就是页面上需要的元素罗列起来,但是页面效果很差,不好看,为了让页面好看,为了修饰页面---》CSS CSS的作用:修饰HTML页面 用了CSS之后,样式和元素本身做到了分离的效果。---》降低了代…