redis(一)内部机制的介绍和启动过程
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)初始化服务器数据结构
这一步主要是为服务器状态中的一些数据结构分配内存,例如:
- “clients“:链表,保存所有与服务器连接的客户端的状态结构。
- ”db“:字典保存服务器的所有数据库。
- ”lua“:用于执行Lua脚本的Lua环境。
- ”slowlog“:用于保存慢查询日志。
除此之外,还会进行一些非常重要的设置操作,例如:
- 为服务器设置进程信号处理器。
- 创建共享对象,例如经常经常用到的“OK”回复字符串对象,1到10000的字符串对象等等。
- 为serverCron函数创建时间事件。
- 如果AOF持久化功能已经打开,则打开现有的AOF文件,若AOF文件不存在,则创建并打开一个新的AOF文件,为AOF写入做好准备。
- 初始化服务器的后台I/O模块,为将来的I/O操作做好准备。
(4)还原数据库状态
若服务器启用了AOF持久化功能,则载入AOF文件,否则载入RDB文件,根据AOF文件或RDB文件记录的内容还原数据库状态,同时在日志文件中打印出载入文件并还原数据库状态所耗费的时长。
(5)执行事件循环
一切准备就绪,开始执行服务器的事件循环,开始接受客户端的连接请求,处理客户端发送的命令请求。
redis(一)内部机制的介绍和启动过程的更多相关文章
- Redis的内部运作机制
本文将分五个部分来分析和总结Redis的内部机制,分别是:Redis数据库.Redis客户端.Redis事件.Redis服务器的初始化步骤.Redis命令的执行过程. 首先介绍一下Redis服务器的状 ...
- Android应用程序的Activity启动过程简要介绍和学习计划
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6685853 在Android系统中,Activ ...
- NopCommerce 1. NopCommerce Application_Start启动过程
这里简单介绍整个启动过程,其他具体的后续讲解 从Application_Start中执行开始,一开始执行EngineContext.Initialize(false); EngineContext 是 ...
- [linux 整理] linux启动过程3
本文介绍linux启动过程的第三步 busybox--------------------> rc init busybox位置即内容 busybox/init/init.c 1.各种设置信号 ...
- HotSpot的启动过程(配视频进行源码分析)
本文将详细介绍HotSpot的启动过程,启动过程涉及到的逻辑比较复杂,细节也比较多,为了让大家更快的了解这部分知识,我录制了对应的视频放到了B站上,大家可以参考. 第4节-HotSpot的启动过程 下 ...
- Redis 文章一 之持久化机制的介绍
我们已经知道对于一个企业级的redis架构来说,持久化是不可减少的 企业级redis集群架构:海量数据.高并发.高可用 持久化主要是做灾难恢复,数据恢复,也可以归类到高可用的一个环节里面去,比如你re ...
- 深入redis内部之redis启动过程之一
redis作为一个服务器,它的启动是从main函数开始的.redis.c 1. 进程重命名 #ifdef INIT_SETPROCTITLE_REPLACEMENT spt_init(argc, ar ...
- Android10_原理机制系列_Window介绍及WMS的启动过程
简介 Window简介 Android中,Window是一个重要部分,用户看到的界面.触摸显示界面进行一系列操作都涉及到Window.但实际上,Window本身并不具备绘制功能. 该篇简单介绍下Win ...
- 探索Redis设计与实现13:Redis集群机制及一个Redis架构演进实例
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
随机推荐
- Linux01 /Linux初识
Linux01 /Linux初识 目录 Linux01 /Linux初识 1. 服务器 2. Linux系统介绍 3. linux简单介绍 4. VMware与Centos系统安装 5. 各个连接协议 ...
- How to use the functions of apply and call
Although apply and call can implement same function. However, there is a litter different between ...
- Reface.AppStarter 类型扫描 —— 获得系统中所有的实体类型
类型扫描 是 Reface.AppStarter 提供的最基本.最核心的功能. AutoConfig , ComponentScan 等功能都是基于该功能完成的. 每一个使用 Reface.AppSt ...
- C#程序安装为windows服务的方式
项目开发中,需要将采集程序以windows服务的形式进行部署,可分为定时采集程序以及监控采集程序. 1.定时采集程序 采用Quartz.net框架实现定时任务,针对该种情形,可采用批处理文件的形式进行 ...
- 小书MybatisPlus第4篇-表格分页与下拉分页查询
本文为mybatis系列文档的第4篇,前三篇请访问下面的网址. 小书MybatisPlus第1篇-整合SpringBoot快速开始增删改查 小书MybatisPlus第2篇-条件构造器的应用及总结 小 ...
- 面试官:请你说下N95应该怎么测试?这样回答让他竖起大拇指!
随着”新冠疫情“慢慢地消散,各大企业都开始恢复正常的运行. 因为疫情造成很多工作人员的流失,企业也开始疯狂的招聘新鲜的人才,这对于莘莘求职者无疑是个机会. 但是因为求职者众多,很多面试官也开始想方设法 ...
- ResNeXt论文阅读笔记.md
目录 1. 提出背景 2. 核心思想 3. 论文核心 4. 分组卷积 5. 核心代码 论文: Aggregated Residual Transformations for Deep Neural N ...
- 简单分析 ztree 源码
为了把 SVG标注 代码抽成一个库,我要学习一下 ztree 是怎么写的. 开始正文. 这只是一个很简单的版本,以后可能会详细分析... (function ($) { var settings = ...
- 地图热点 jquery.image-maps.js 的使用
在我悠闲了几天之后,我们后端给了我个任务,地图热点问题.简单来说,就是后台划出热点区域,设置链接,前端拿到数据渲染页面,显示热点区域.我主要使用了jquery.image-maps.js,并且添加了一 ...
- 记录一次JSON数据处理(省市区数据)
最近在实习工作中遇到了一个需要问题:将后台返回的省市区 json 数据格式化以便前端渲染.这个问题真的是缠绕了我好几天,有思路但是思路特别模糊,今天终于解决了. 返回的数据格式如下: [ { &quo ...