14.1 命令请求的执行过程

读取命令请求

命令执行器(1):查找命令实现

在命令表(command table)中查找参数所指定的命令,并将找到的命令保存到客户端状态的cmd属性里面

命令执行器(2):执行预备操作

14.2 serverCron函数

更新服务器时间缓存

struct redisServer{
//...
// 保存了秒级精度的系统当前UNIX时间戳
time_t unixtime; // 保存了毫秒级精度的系统当前UNIX时间戳
long long mstime; // 默认10秒更新一次的时间缓存, 用于计算键的空转时间
unsigned lruclock:22; }; struct redisObject{
//... // 对象最后一次被命令访问的时间
unsigned lru:22; //...
};

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

serverCron函数中的trackOperationsPerSecond函数会以每100毫秒一次的频率执行,这个函数的功能是以抽样计算的方式,估算并记录服务器在最近一秒处理的命令请求数量

struct redisServer{
//... // 上一次进行抽样的时间
long long ops_sec_last_sample_time; // 上一次抽样时,服务器已执行命令的数量
long long ops_sec_last_sample_ops; // REDIS_OPS_SEC_SAMPLES大小(默认值为16)的环形数组
// 数组中的每个项都记录了一次抽样结果
long long ops_sec_samples[REDIS_OPS_SEC_SAMPLES]; // ops_sec_samples数组的索引值
// 每次抽样后将值自增1
// 在值等于16时重置为0
int ops_sec_idx; //...
};

更新服务器内存峰值记录

struct redisServer{
//... // 已使用内存峰值
size_t stat_peaak_memory; //...
};

处理SIGTERM信号

管理客户端资源

serverCron函数每次执行都会调用clientsCron函数,clientsCron函数会对一定数量的客户端进行以下两个检查:

  • 如果客户端与服务器之间的连接已经超时,那么程序释放这个客户端
  • 如果客户端在上一次执行命令请求之后,输入缓冲区的大小超过了一定的长度,那么程序会释放客户端当前的输入缓冲区,并重新创建一个默认大小的输入缓冲区

管理数据库资源

serverCron函数每次执行都会调用databasesCron函数,这个函数会对服务器中的一部分数据库进行检查,删除其中的过期键,并在有需要时,对字典进行收缩操作

执行被延迟的BGREWRITEAOF

服务器的aof_rewrite_scheduled标识记录了服务器是否延迟了BGREWRITEAOF命令:

struct redisServer{
//... //如果值为1, 那么标识有 BGREWRITEAOF 命令被延迟了
int aof_rewrite_scheduled; //...
};

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

服务器状态使用rdb_child_pid 属性和 aof_child_pid 属性记录执行BGSAVE命令和 BGREWRITEAOF 命令的子进程的ID

struct redisServer{
//... // 记录执行BGSAVE命令的子进程的ID
// 如果服务器没有在执行BGSAVE
// 那么这个属性的值为-1
pid_t rdb_child_pid; // 记录执行BGREWRITEAOF 命令的子进程的ID
// 如果服务器没有在执行BGREWRITEAOF
// 那么这个属性的值为-1
pid_t aof_child_pid; //...
};

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

关闭异步客户端

增加cronloops计数器的值

struct redisServer{
//... // serverCron函数的运行次数计数器
int cronloops; //...
};

14.3 初始化服务器

void initServerConfig(void) {
int j; updateCachedTime(1); // 设置服务器运行id
getRandomHexChars(server.runid,CONFIG_RUN_ID_SIZE); // 设置默认服务器频率
server.hz = CONFIG_DEFAULT_HZ; /* Initialize it ASAP, even if it may get
updated later after loading the config.
This value may be used before the server
is initialized. */
server.timezone = getTimeZone(); /* Initialized by tzset(). */ // 设置默认配置文件路径
server.configfile = NULL; // 设置服务器的运行架构
server.arch_bits = (sizeof(long) == 8) ? 64 : 32; //...
}

载入配置选项

初始化服务器数据结构

initServerConfig函数主要负责初始化一般属性

initServer函数主要负责初始化数据结构

除了初始化数据结构之外,initServer还进行了一些非常重要的设置操作,其中包括:

  • 为服务器设置进程信号处理器
  • 创建共享对象:这些对象包含Redis服务器经常用到的一些值,比如包含“OK”回复的自负床对象,包含整数1 到 10000 的字符串对象等等,服务器通过重用这些共享对象来避免反复创建相同的对象
  • 打开服务器的监听端口,并为监听套接字关联连接应答事件处理器,等待服务器正式运行时接收客户端的连接
  • 为serverCron函数创建时间事件,等待服务器正式运行时执行serverCron函数
  • 如果AOF持久化功能已经打开,那么打开现有的AOF文件,如果AOF文件不存在,那么创建并打开一个新的AOF文件,为AAOF写入做好准备
  • 初始化服务器的后台IO模块,为将来的IO操作做好准备

还原数据库状态

根据服务器是否启用了AOF持久化功能,服务器载入数据时所使用的目标文件会有所不同:

  • 如果服务器启用了AOF持久化功能,那么服务器使用AOF文件来还原数据库状态
  • 否则使用RDB文件来还原数据库状态

执行事件循环

【笔记】《Redis设计与实现》chapter14 服务器的更多相关文章

  1. 《Redis设计与实现》读书笔记

    <Redis设计与实现>读书笔记 很喜欢这本书的创作过程,以开源的方式,托管到Git上进行创作: 作者通读了Redis源码,并分享了详细的带注释的源码,让学习Redis的朋友轻松不少: 阅 ...

  2. 《Redis设计与实现》阅读笔记(一)--Redis学习

    Redis学习资料与过程记录 在实习中经常会用到很多Redis,对Redis有了一些模糊的了解,总觉得隔靴搔痒的不痛快,所以决定开始深入的了解Redis,也作为我实习期间的目标. 这篇只是为了占个位置 ...

  3. Redis | 第7章 Redis 服务器《Redis设计与实现》

    目录 前言 1. 命令请求的执行过程 1.1 发送命令请求 1.2 读取命令请求 1.3 命令执行器(1):查找命令实现 1.4 命令执行器(2):执行预备操作 1.5 命令执行器(3):调用命令的实 ...

  4. Redis | 第11章 服务器的复制《Redis设计与实现》

    目录 前言 1. 旧版复制功能的实现 1.1 同步与命令传播 1.2 旧版复制功能的缺陷 2. 新版复制功能的实现 2.1 部分重同步的实现原理 3. PSYNC 命令的实现 4. 复制的详细步骤 4 ...

  5. Redis | 第一部分:数据结构与对象 上篇《Redis设计与实现》

    目录 前言 1. 简单动态字符串 1.1 SDS的定义 1.2 空间预分配与惰性空间释放 1.3 SDS的API 2. 链表 2.1 链表与节点的定义 2.2 链表的API 3. 字典 3.1 哈希表 ...

  6. Redis | 第一部分:数据结构与对象 下篇《Redis设计与实现》

    目录 前言 1. Redis对象概述 1.1 对象的定义 2. 字符串对象 3. 列表对象 3.1 quicklist 快速链表 4. 哈希对象 5. 集合对象 6. 有序集合对象 7. Redis对 ...

  7. Redis设计与实现2.2:数据持久化

    数据持久化 这是<Redis设计与实现>系列的文章,系列导航:Redis设计与实现笔记 RDB持久化 RDB 持久化功能所生成的 RDB 文件是一个经过压缩的二进制文件,通过该文件可以还原 ...

  8. Redis设计与实现2.1:数据库和事件

    数据库和事件 这是<Redis设计与实现>系列的文章,系列导航:Redis设计与实现笔记 数据库 数据库的结构定义在 redis.h/redisServer 这个结构体中,这个结构体有许多 ...

  9. Redis设计与实现3.3:集群

    集群 这是<Redis设计与实现>系列的文章,系列导航:Redis设计与实现笔记 集群中的节点 创建集群 通过 CLUSTER NODE 命令可以查看当前集群中的节点.刚启动时,默认每一台 ...

  10. Redis设计与实现3.2:Sentinel

    Sentinel哨兵 这是<Redis设计与实现>系列的文章,系列导航:Redis设计与实现笔记 哨兵:监视.通知.自动故障恢复 启动与初始化 Sentinel 的本质只是一个运行在特殊模 ...

随机推荐

  1. django学习-2.urls.py和view.py的相关知识点

    1.URL函数简单解析 1.1.url() 函数可以接收四个参数,分别是两个必选参数:regex.view,和两个可选参数:kwargs.name. def url(regex, view, kwar ...

  2. AtCoder Beginner Contest 192 F - Potion

    题目链接 点我跳转 题目大意 给定 \(N\) 个物品和一个 \(X\) ,第 \(i\) 个物品的重量为 \(ai\),你可以从中选择任意个物品(不能不选) 假定选择了 \(S\) 个物品,物品的总 ...

  3. [Python学习笔记]正则表达式总结

    常用缩写字符及其含义表格查询 缩写字符分类 含义 \d 0-9的任意数字 \D 除0-9的数字以外的任何字符 \w 任何字母.数字或下划线字符(可以认为是匹配"单词"字符) \W ...

  4. iOS拍照定制之AVCaptureVideoDataOutput

    问题 领导看了前面做的拍照,问了句"哪来的声音", "系统的,自带的,你看系统的拍照也有声音" "有办法能去掉吗?挺糟心的" "我 ...

  5. RocketMQ同一个消费者唯一Topic多个tag踩坑经历

    最近做的项目的一个版本需求中,需要用到MQ,对数据记录进行异步落库,这样可以减轻数据库的压力,同时可以抗住大量的数据落库.这里需要说明一下本人用到的MQ是公司自己在阿里的RokectMQ的基础上进行封 ...

  6. 微信小程序:自定义组件

    为什么要学习自定义组件? 1.用上我自己的单词abc,我希望在页面中展示椭圆形的图片, 2.打开手机淘宝,假如现在要做一个企业级项目,里面有很多页面,首页存在导航模块,点击天猫,进入第二个页面,而第二 ...

  7. 使用Mongodb设计评论系统

    1:如何设计数据存储结构 1.1:mysql 1:评论表 2:回复表(评论的评论) 1.2:mongodb 不需要两张表,一个collection 就可以搞定. 数据结构如图: 通过对象数组中的字段作 ...

  8. MYSQL安全模式"sql_safe_updates"设置update和delete不带where的操作限制

    前言 在数据库操作中,如果在update和delete没有加上where条件,数据将会全部修改. 不只是初识mysql的开发者会遇到这个问题,工作有一定经验的开发者有时难免也会忘记写入where条件. ...

  9. ValidationUtils 验证工具

    package com.appnirman.vaidationutils;import android.content.Context;import java.util.regex.Matcher;i ...

  10. 如何用Eggjs从零开始开发一个项目(2)

    在上一篇文章,我们已经使用Sequelize连接上了数据库,并能进行简单的数据库操作,在此基础上,我们试着来开发一个完整的项目.这篇文章我们从用户的注册.登录着手,试着开发用户模块的相关的代码. 用户 ...