redis(一)内部机制的介绍和启动过程


redis的基本介绍

redis是一种非关系型数据库,采用=key,value的形式来存储数据。key是二进制数据,对于value的数据类型,redis支持string、hash、list、set、sorted set五种类型。
对于单个redis实例,内部使用多线程通信,但是对外采用RESP单线程通信协议,在TCP层通过二进制方式进行传输数据,单线程采用同步的请求方式。


redis服务端

redis服务端内部结构为struct redisServer和struct redisDb。redis中默认16个数据库,可以通过配置来修改数据库数量,每一个数据库对应一个redisDb。数据库之间的数据是相互独立的。查询数据的时候,可以通过select指定具体某个数据库。

 1 struct redisServer {
2 int dbnum;//服务器的数据库数量,值由服务器配置的“databases”选项决定,默认为16
3 redisDb *db;//数组,保存着服务器中的所有数据库
4
5 list *clients;//一个链表,保存了所有客户端状态,每个链表元素都是“redisClient”结构
6
7 time_t unixtime;//保存秒级精度的系统当前UNIX时间戳,减少获取系统当前时间的系统调用次数,100毫秒更新一次
8 long long mstime;//保存毫秒级精度的系统当前UNIX时间戳
9 unsigned lruclock;//默认每10秒更新一次,用于计算数据库键的空转时长,数据库键的空转时长 = 服务器的“lruclock”属性值 - 数据库键值对象的“lru”属性值
10
11 long long ops_sec_last_sample_time;//上一次进行服务器每秒执行命令数量抽样的时间
12 long long ops_sec_last_sample_ops;//上一次进行服务器每秒执行命令数量抽样时,服务器已执行命令的数量
13 long long ops_sec_samples[REDIS_OPS_SEC_SAMPLE];//环形数组,每个元素记录一次服务器每秒执行命令数量抽样结果,估算服务器在最近一秒钟处理的命令请求数量(数组长度默认为16,100毫秒更新一次)
14 int ops_sec_idx;//ops_sec_samples数组的索引值,每次抽样后值增1,等于16时重置为0
15
16 size_t stat_peak_memory;//已使用内存峰值
17
18 int shutdown_asap;//关闭服务器的标识,1表示关闭,0不关闭
19
20 pid_t rdb_child_pid;//记录执行BGSAVE命令的子进程的ID,-1表示服务器没有正在执行BGSAVE
21 pid_t aof_child_pid;//记录执行BGREWRITEAOF命令的子进程的ID,-1表示服务器没有正在执行BGREWRITEAOF
22 int aof_rewrite_scheduled;//1表示有BGREWRITEAOF命令被延迟了(服务器执行BGSAVE期间收到的BGREWRITEAOF会被延迟到BGSAVE执行完成之后执行)
23 struct saveparam *saveparams;//记录了自动保存条件的数组(执行BGSAVE的条件)
24 long long dirty;//修改计数器(上一次执行BGSAVE之后已经产生了多少修改)
25 time_t lastsave;//上一次执行自动保存操作(BGSAVE)的时间
26 sds aof_buf;//AOF缓冲区
27
28 int cronloops;//serverCron函数的运行次数计数器
29
30 lua;//用于执行Lua脚本的Lua环境
31 redisClient *lua_client;//Lua脚本的伪客户端,在服务器运行的整个生命周期一直存在,直至服务器关闭才会关闭
32 dict *lua_scripts;//字典,记录所有载入的Lua脚本,键为某个Lua脚本的SHA1校验和,值为对应的Lua脚本
33 dict *repl_scriptcache_dict;//字典,记录已经传播给所有从服务器的所有Lua脚本,键为脚本的SHA1校验和,值为NULL,用于EVALSHA1命令的复制
34
35 long long slowlog_entry_id;//下一条慢查询日志的ID
36 list *slowlog;//保存了所有慢查询日志的链表
37 long long slowlog_log_slower_than;//服务器配置“slowlog-log-slower-than”选项的值,表示查询慢于多少微秒便记录慢查询日志
38 unsigned long slowlog_max_len;//服务器配置“slowlog-max-len”选项的值,表示服务器最多保存多少条慢查询日志记录,若超出,最久的记录会被覆盖
39
40 monitors;//链表,监视器客户端列表
41
42 dict *pubsub_channels;//字典,保存所有频道的订阅关系,键为某个被订阅的频道,值为链表,记录了所有订阅这个频道的客户端
43 list *pubsub_patterns;//链表,保存所有模式的订阅关系,每个链表节点都包含了订阅的客户端和被订阅的模式
44 };
struct redisDb {
dict *dict;//数据库键空间字典,保存数据库中所有的键值对
dict *expires;//过期字典,保存数据库中所有键的过期时间
dict *watched_keys;//字典,正在被WATCH命令监视的键
};
redisDb中三个字典中的key共享对象,value值不一样。对于过期的键,redis采用惰性删除和定时删除相结合的方式,惰性删除,指执行之前会查看这个key是否过期,定时删除值一段时间之后分多次遍历数据库,每次只删除部分过期的数据。

redis客户端

redis-server通过tcp端口或socket来创建和redis-cli的连接,可以修改redis.conf中的maxclients来指定最大连接数,在建立连接之后,socket会被设置为非阻塞模式,同时创造一个struct redisClient来保存客户端的连接信息。

 1 struct redisClient {
2 redisDb *db;//记录客户端当前正在使用的数据库,上文提到之前有16个们默认的数据库,可以通过select进行切换数据库
3 int fd;//客户端正在使用的套接字描述符,-1表示伪客户端(AOF文件或者Lua脚本),大于-1表示普通客户端
4 robj *name;//客户端名字
5 int flags;//客户端标志,记录了客户端的角色,以及客户端目前所处的状态
6 sds querybuf;//输入缓冲区,根据输入内容动态地缩小或扩大,但不能超过1GB,否则服务器将关闭这个客户端
7 robj **argv;//命令与命令参数,数组,每个元素都是一个字符串对象,argv[0]为命令,其余元素为参数
8 int argc;//argv数组的长度
9 struct redisCommand *cmd;//当前执行的命令的实现函数,指向命令表中的命令结构
10 char buf[REDIS_REPLY_CHUNK_BYTES];//固定大小输出缓冲区,数组,默认大小为16KB
11 int bufpos;//buf数组目前已使用的字节数量
12 list *reply;//可变大小输出缓冲区,链表
13 obuf_soft_limit_reached_time:记录了“reply”输出缓冲区第一次到达软性限制的时间,用于计算持续超出软性限制的时长,以此决定是否关闭客户端
14 int authenticated;//0表示未通过身份验证,1表示已通过身份验证
15 time_t ctime:创建客户端的时间,可用于计算客户端与服务器连接的时间长度
16 time_t lastinteraction:客户端与服务器最后一次进行互动的时间,可用于客户端的空转时长
17 multiState mstate;//事务状态,包含一个事务队列,以及一个已入列命令计数器
18 };
db:是一个指针,指向Redis服务器状态结构中的“db”数组其中一个元素,表示当前客户端正在使用的数据库。默认情况下,Redis客户端的目标数据库为0号数据库,可以通过select命令切换,所以select命令的实现原理为:修改redisClient.db指针,让它指向服务器中指定的数据库。
fd:连接当前客户端与Redis服务器的套接字描述符。值为-1表示伪客户端(AOF文件或者Lua脚本),值大于-1则表示普通客户端。Redis客户端分为普通客户端与伪客户端两种类型,其中通过网络连接与Redis服务器进行连接的就是普通客户端,反之则是伪客户端了。伪客户端也有两种类型,分别是Lua脚本的伪客户端和AOF文件的伪客户端。Redis服务器状态结构的“lua_client”属性就保存了Lua脚本的伪客户端,它会在Redis服务器初始化时就被创建,负责执行Lua脚本中包含的Redis命令,在服务器运行的整个生命周期一直存在,直至服务器关闭才会关闭。而AOF伪客户端则是在载入AOF文件时被创建,用于执行AOF文件中的Redis命令,在AOF文件载入完成之后被关闭。client list:列出目前所有连接到服务器的普通客户端。

redis的持久化

AOF、RDB指的是redis持久化策略,可以通过redis.conf中的参数来配置。
appendfsync (always/everysec/no)
save [time(s)] [times]
AOF指的是保存操作命令,他会将每一次redis的数据操作命令追加到文件中,当键过期的时候会加入del命令,并且每过一段时间,会对已经生成的文件优化一次,主要指的是操作命令的合并。
RDB指的是执行save或bgsave命令创建一个新的RDB文件,新建一个子进程,把所有的数据写入文件。


redis中的文件事件和时间时间

redis中的事件分为文件事件和时间事件
文件事件:指的是通过epoll实现io多路复用程序来监听多个套接字,对读、写、关闭、连接都支持事务,支持原子操作。
时间事件:指的是redis中在默写特定时间执行操作,主要有定时事件和周期性事件。所有的时间事件会被放在一个无须列表中,新加入的事件会在事件的头部插入。每次执行事件的时候都会去遍历列表。正常情况下只有一个serverCron时间时间,在benchmark模式下,也只有两个时间事件。


redis的启动过程

(1)初始化服务器状态结构
  新创建一个struct redisServer类型的实例变量作为服务器的状态,记录着整个服务器的状态,并为结构中的各个属性设置默认值,例如:服务器的运行ID、默认配置文件路径、默认端口等等,同时创建Redis命令表。
(2)载入配置选项
  载入用户指定的配置参数和配置文件,并根据用户设定的配置,对服务器状态变量的相关属性进行修改。
(3)初始化服务器数据结构
  这一步主要是为服务器状态中的一些数据结构分配内存,例如:

  1. “clients“:链表,保存所有与服务器连接的客户端的状态结构。
  2. ”db“:字典保存服务器的所有数据库。
  3. ”lua“:用于执行Lua脚本的Lua环境。
  4. ”slowlog“:用于保存慢查询日志。

除此之外,还会进行一些非常重要的设置操作,例如:

  1. 为服务器设置进程信号处理器。
  2. 创建共享对象,例如经常经常用到的“OK”回复字符串对象,1到10000的字符串对象等等。
  3. 为serverCron函数创建时间事件。
  4. 如果AOF持久化功能已经打开,则打开现有的AOF文件,若AOF文件不存在,则创建并打开一个新的AOF文件,为AOF写入做好准备。
  5. 初始化服务器的后台I/O模块,为将来的I/O操作做好准备。

(4)还原数据库状态
  若服务器启用了AOF持久化功能,则载入AOF文件,否则载入RDB文件,根据AOF文件或RDB文件记录的内容还原数据库状态,同时在日志文件中打印出载入文件并还原数据库状态所耗费的时长。
(5)执行事件循环
  一切准备就绪,开始执行服务器的事件循环,开始接受客户端的连接请求,处理客户端发送的命令请求。

redis(一)内部机制的介绍和启动过程的更多相关文章

  1. Redis的内部运作机制

    本文将分五个部分来分析和总结Redis的内部机制,分别是:Redis数据库.Redis客户端.Redis事件.Redis服务器的初始化步骤.Redis命令的执行过程. 首先介绍一下Redis服务器的状 ...

  2. Android应用程序的Activity启动过程简要介绍和学习计划

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6685853 在Android系统中,Activ ...

  3. NopCommerce 1. NopCommerce Application_Start启动过程

    这里简单介绍整个启动过程,其他具体的后续讲解 从Application_Start中执行开始,一开始执行EngineContext.Initialize(false); EngineContext 是 ...

  4. [linux 整理] linux启动过程3

    本文介绍linux启动过程的第三步 busybox--------------------> rc init busybox位置即内容 busybox/init/init.c 1.各种设置信号 ...

  5. HotSpot的启动过程(配视频进行源码分析)

    本文将详细介绍HotSpot的启动过程,启动过程涉及到的逻辑比较复杂,细节也比较多,为了让大家更快的了解这部分知识,我录制了对应的视频放到了B站上,大家可以参考. 第4节-HotSpot的启动过程 下 ...

  6. Redis 文章一 之持久化机制的介绍

    我们已经知道对于一个企业级的redis架构来说,持久化是不可减少的 企业级redis集群架构:海量数据.高并发.高可用 持久化主要是做灾难恢复,数据恢复,也可以归类到高可用的一个环节里面去,比如你re ...

  7. 深入redis内部之redis启动过程之一

    redis作为一个服务器,它的启动是从main函数开始的.redis.c 1. 进程重命名 #ifdef INIT_SETPROCTITLE_REPLACEMENT spt_init(argc, ar ...

  8. Android10_原理机制系列_Window介绍及WMS的启动过程

    简介 Window简介 Android中,Window是一个重要部分,用户看到的界面.触摸显示界面进行一系列操作都涉及到Window.但实际上,Window本身并不具备绘制功能. 该篇简单介绍下Win ...

  9. 探索Redis设计与实现13:Redis集群机制及一个Redis架构演进实例

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

随机推荐

  1. Linux01 /Linux初识

    Linux01 /Linux初识 目录 Linux01 /Linux初识 1. 服务器 2. Linux系统介绍 3. linux简单介绍 4. VMware与Centos系统安装 5. 各个连接协议 ...

  2. How to use the functions of apply and call

    Although  apply and  call  can implement same function. However, there is a litter different between ...

  3. Reface.AppStarter 类型扫描 —— 获得系统中所有的实体类型

    类型扫描 是 Reface.AppStarter 提供的最基本.最核心的功能. AutoConfig , ComponentScan 等功能都是基于该功能完成的. 每一个使用 Reface.AppSt ...

  4. C#程序安装为windows服务的方式

    项目开发中,需要将采集程序以windows服务的形式进行部署,可分为定时采集程序以及监控采集程序. 1.定时采集程序 采用Quartz.net框架实现定时任务,针对该种情形,可采用批处理文件的形式进行 ...

  5. 小书MybatisPlus第4篇-表格分页与下拉分页查询

    本文为mybatis系列文档的第4篇,前三篇请访问下面的网址. 小书MybatisPlus第1篇-整合SpringBoot快速开始增删改查 小书MybatisPlus第2篇-条件构造器的应用及总结 小 ...

  6. 面试官:请你说下N95应该怎么测试?这样回答让他竖起大拇指!

    随着”新冠疫情“慢慢地消散,各大企业都开始恢复正常的运行. 因为疫情造成很多工作人员的流失,企业也开始疯狂的招聘新鲜的人才,这对于莘莘求职者无疑是个机会. 但是因为求职者众多,很多面试官也开始想方设法 ...

  7. ResNeXt论文阅读笔记.md

    目录 1. 提出背景 2. 核心思想 3. 论文核心 4. 分组卷积 5. 核心代码 论文: Aggregated Residual Transformations for Deep Neural N ...

  8. 简单分析 ztree 源码

    为了把 SVG标注 代码抽成一个库,我要学习一下 ztree 是怎么写的. 开始正文. 这只是一个很简单的版本,以后可能会详细分析... (function ($) { var settings = ...

  9. 地图热点 jquery.image-maps.js 的使用

    在我悠闲了几天之后,我们后端给了我个任务,地图热点问题.简单来说,就是后台划出热点区域,设置链接,前端拿到数据渲染页面,显示热点区域.我主要使用了jquery.image-maps.js,并且添加了一 ...

  10. 记录一次JSON数据处理(省市区数据)

    最近在实习工作中遇到了一个需要问题:将后台返回的省市区 json 数据格式化以便前端渲染.这个问题真的是缠绕了我好几天,有思路但是思路特别模糊,今天终于解决了. 返回的数据格式如下: [ { &quo ...