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. P1136 迎接仪式 题解

    题目描述 LHX教主要来X市指导OI学习工作了.为了迎接教主,在一条道路旁,一群Orz教主er穿着文化衫站在道路两旁迎接教主,每件文化衫上都印着大字.一旁的Orzer依次摆出"欢迎欢迎欢迎欢 ...

  2. Cyber Security - Palo Alto Firewall Objects Addresses, Services, and Groups(1)

    Address Objects and Groups Creating address objects. Organizing address objects with address groups ...

  3. OSCP Learning Notes - WebApp Exploitation(5)

    Remote File Inclusion[RFI] Prepare: Download the DVWA from the following website and deploy it on yo ...

  4. Ethical Hacking - NETWORK PENETRATION TESTING(20)

    MITM - Capturing Screen Of Target & Injecting a Keylogger ScreenShotter Plugin: ScreenShotter: U ...

  5. .net core 使用 Serilog 作为日志提供者

    nuget引入 Serilog.AspNetCore Startup构造函数: public Startup(IConfiguration configuration) { Configuration ...

  6. 水题----B - Badge CodeForces - 1020B

    In Summer Informatics School, if a student doesn't behave well, teachers make a hole in his badge. A ...

  7. 图表可视化seaborn风格和调色盘

    seaborn是基于matplotlib的python数据可视化库,提供更高层次的API封装,包括一些高级图表可视化等工具. 使用seaborn需要先安装改模块pip3 install seaborn ...

  8. SpringBoot实现前后端数据交互、json数据交互、Controller接收参数的几种常用方式

    1.获取参数的集中常见注解 @PathVariable:一般我们使用URI template样式映射使用,即url/{param}这种形式,也就是一般我们使用的GET,DELETE,PUT方法会使用到 ...

  9. API返回延迟,FPM重启后恢复之后又重现 问题解决方案

    背景 最近在提供后台API时,提供了一个简单逻辑的接口 部署在测试环境,自测没问题,提交测试 突然有一天,接口响应延迟严重,几乎每次都是3-4秒返回 这对于一个接口来说,肯定是有问题的 于是便有了以下 ...

  10. 蒲公英 · JELLY技术周刊 Vol.16 谷歌首个线上 Web 开发者大会

    蒲公英 · JELLY技术周刊 Vol.16 近期,谷歌有史以来的第一次线上谷歌 Web 开发者大会,Web Vitals.PWA.DevTools 和 Lighthouse 6.0 等一系列特性或产 ...