首页
学习
活动
专区
工具
TVP
发布

Redis——数据库实现

Redis是一款 NoSQL 数据库,在大多数项目中作为缓存使用,也可以作为数据库,存储数据。

Redis源码(https://github.com/antirez/redis)

数据库

Redis 服务器将所有数据库都保存在服务器状态 结构的 数组中, 数组的每个项都是一个 结构,每个 结构代表个数据库:

键空间和用户所见的数据库是直接对应的:

键空间的键也就是数据库的键,每个键都是一个字符串对象。

键空间的值也就是数据库的值,每个值可以是字符串对象、列表对象、哈希表对象、集合对象和有序集合对象中的任意一种 Redis 对象。

过期键删除策略

定时删除:在设置键的过期时间的同时,创建一个定时器( timer),让定时器在键的过期时间来临时,立即执行对键的删除操作。这种策略对内存友好,但是对CPU时间是最不友好的:在国期间比较多的情况下,删除过期键这一行为可能会占用箱单大一部分CPU时间,影响服务器的响应时间和吞吐量。

惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。这种策略是对内存很不友好,如果一些过期键,一直没被查找,就会一直占用内存,可能会出现内存泄露的危险。

定期删除:每隔一段时间,程序就对数据库进行一次检査,删除里面的过期键。至于要删除多少过期键,以及要检查多少个数据库,则由算法决定

在这三种策略中,第一种和第三种为主动删除策略,而第二种则为被动删除策略。

Redis 服务器实际使用的是惰性删除和定期删除两种策略:通过配合使用这两种删除策略,服务器可以很好地在合理使用CPU时间和避免浪费内存空间之间取得平衡。

RDB持久化

因为 Redis 是内存数据库,它将自己的数据库状态储存在内存里面,所以如果不想办法将储存在内存中的数据库状态保存到磁盘里面,那么一且服务器进程退出,服务器中的数据库状态也会消失不见。为了解决这个问题,Redis提供了RDB持久化功能,可以将Redis在内存中的数据库状态保存到磁盘中,避免数据丢失。RDB是一个经过压缩的二进制文件。

Redis有两个命令用来自生成RDB文件: 和 。

SAVE:当save执行是,Redis服务器会被阻塞,客户端发送的所有命令请求都会被拒绝。

BGSAVE:BGSAVE的保存工作是由子进程执行的,所以Redis服务器可以继续执行客户端的命令。

RDB文件结构

RDB文件的最开头是 REDIS 部分,这个部分的长度为5字节,保存着 五个字符。通过这五个字符,程序可以在载入文件时,快速检查所载人的文件是否RDB文件。

db version 长度为 ,它的值是一个字符串表示的整数,这个整数记录了RDB文件的版本号,比如”0006就代表RDB文件的版本为第六版。本章只介绍第六版 RDB 文件的结构。

databases 部分包含着零个或任意多个数据库,以及各个数据库中的键值对数据:

如果服务器的数据库状态为空(所有数据库都是空的),那么这个部分也为空,长度为0字节。

如果服务器的数据库状态为非空(有至少一个数据库非空),那么这个部分也为非空,根据数据库所保存键值对的数量、类型和内容不同,这个部分的长度也会有所不同。

EOF常量的长度为1字节,这个常量标志着RDB文件正文内容的结束,当读入程序遇

这个值的时候,它知道所有数据库的所有键值对都已经载入完毕了。

check sum 是一个8字节长的无符号整数,保存着一个校验和,这个校验和是程序通过对 REDIS、 db version、 databases、EoF四个部分的内容进行计算得出的。服务器在载入RDB文件时,会将载入数据所计算出的校验和与 check sum所记录的校验和进行对比,以此来检查RDB文件是否有出错或者损坏的情况出现。

AOF持久化

AOF 持久化是通过保存 Redis 服务器所执行的写命令来记录数据库状态的。

对于RDB持久化存储的是SET、PUSH这两个键值对;AOF持久化存储的是SET、PUSH这两个命令。

事件

Redis服务器是一个事件驱动程序,服务器需要处理以下两类事件:

文件事件(file event): Redis服务器通过套接字与客户端(或者其他 Redis服务器)进行连接,而文件事件就是服务器对套接字操作的抽象。服务器与客户端(或者其他服务器)的通信会产生相应的文件事件,而服务器则通过监听并处理这些事件来完成一系列网络通信操作。

时间事件(time event): Redis服务器中的一些操作(比如 servercron函数)需要在给定的时间点执行,而时间事件就是服务器对这类定时操作的抽象。

文件事件

Redis 基于Reactor模式开发了自己的网络事件处理器即文件事件处理器。

文件事件处理器使用I/O多路复用程序来同时监听多个套接字,并根据套接字目前执行的任务来为套接字关联不同的事务处理器。

时间事件

Redis的时间事件分为以下两类:

定时事件:让一段程序在指定的时间之后执行一次。比如说,让程序X在当前时间的30毫秒之后执行一次。

周期性事件:让一段程序每隔指定时间就执行一次。比如说,让程序Y每隔30毫秒就执行一次。

一个时间事件的三个属性:

ID:服务器为时间事件创建的全局唯一ID。

when:毫秒精度的UNX时间戳,记录了时间事件的到达( arrive )时间。

timeproc:时间事件处理器,一个函数。当时间事件到达时,服务器就会调用相应的处理器来处理事件。

服务器把所有时间事件都放在一个无序链表中,每当时间事件执行,遍历整个链表,查找所有已达的时间事件,并调用相应的事件处理器。

服务器

命令请求过程:

客户端向服务器发送请求命令:Redis服务器的命令请求来自Reds客户端,当用户在客户端中键入一个命令请求时,客户端会将这个命令请求转换成协议格式,然后通过连接到服务器的套接字,将协议格式的命令请求发送给服务器。

服务器接收并处理客户端发来的命令请求,在数据库中进行设置操作,并尝试命令回复OK

读取套接字中协议格式的命令请求,并将其保存到客户端状态的输入缓冲区里面。

对输入缓冲区中的命令请求进行分析,提取出命令请求中包含的命令参数,以及命令参数的个数,然后分别将参数和参数个数保存到客户端状态的 argv 属性和 argc 属性里面

调用命令执行器,执行客户端指定的命令

服务器将命令回复OK发送给客户端

客户端接收到服务器的返回的命令OK,并打印显示在客户端

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180812G0161C00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券