文章目录
- 一、前言
- 二、redis服务器中数据库
- 三、从底层原理图讲解redis增删改查操作
- 3.1 添加新键
- 3.2 删除键
- 3.3 更新键
- 3.4 对键取值
- 四、生存时间在数据库的存储
- 4.1 生存时间的设置与读取
- 4.2 生存时间的底层保存(过期字典)
- 五、尾声
一、前言
Redis是一种基于键值对的非关系型数据库(ps: mongdb也是一种基于键值对的非关系型数据库),有五种基本类型,每一种的都是 key-value 键值对,本文介绍Redis服务端的数据库,说一下这些 key-value 键值对是如何在redis底层存放的。
1、redis的键值对在数据库中如何存放的,如何完成增删查改的。
2、redis的键值对的过期时间/生存时间ttl在数据库中如何存放的。
二、redis服务器中数据库
让我们来见识一下redis中的数据库结构,看一下这些 key-value 是如何在redis底层存放的。
struct redisServer{
// ...
//一个数组,保存着服务器中的所有数据库
redisDb *db;
//服务器的数据库数量
int dbnum;
// ...
};
对于上述代码和示意图的解释是:Redis服务器将所有数据库都保存在服务器状态redis.h/ redisServer结构的db数组中,db数组的每个项都是一个 redis.h/redisDb结构,每个 redisDb结构(即代码中的redisDb *db)代表一个数据库,同时,程序会根据服务器状态的donum属性(即代码中的int dbnum)来决定应该创建多少个数据库。num属性的值由服务器配置的 database选项决定,默认情况下,该选项的值为16,所以 Redis服务器默认会创建16个数据库:
切换数据库:对于redis默认的16个数据库(db0-db15),在操作的时候可以选择将数据(五种类型均可)存放在哪个数据库中,只要将某个数据库设置成当前数据库就好(select 数目),宏观命令如下:
底层变化:
三、从底层原理图讲解redis增删改查操作
Redis是一个键值对(key- value pair)数据库服务器,服务器中的每个数据库都由一个 redis.h/ redisDb结构表示,其中, redisDb结构的dict字典保存了数据库中的所有键值对,我们将这个字典称为键空间( key space):
键空间和用户所见的数据库是直接对应的:
1)键空间的键也就是数据库的键,每个键都是一个字符串对象;
2)键空间的值也就是数据库的值,每个值可以是字符串对象、列表对象、哈希表对象集合对象和有序集合对象中的任意一种Redis对象。
如图:
对于上图解释:redisDb即表示redis服务器中的数据库,里面有一个dict字典,里面存放数据实体(即key-value键值对),这里有三个key-value键值对,分别是
(key,value)=(“alpha”,“a b c”)为ListObjet类型,
(key,value)=(“book”,“<name,Redis in Action><author,Josiah L.Carlson><publisher,Manning>”)为HashObject类型,
(key,value)=(“alpha”,“hello world”)为StringObject类型
3.1 添加新键
对于上图解释:添加新键,StringObject类型 <key,value>=<“date”,“2020/02/09”>
3.2 删除键
对于上图解释:删除新键,删除key为“book”的键值对
3.3 更新键
对于上图解释:更新键,更新key为“message”的键值对
3.4 对键取值
对于上图解释:对键取值,获取key为“message”的value
四、生存时间在数据库的存储
Redis每一个键值对都有一个过期时间 ttl,也成为了生存时间,那么,这个时间在redis数据库是如何存放的呢?
4.1 生存时间的设置与读取
介绍四个命令(和TTL time to live 生存时间有关的),用表格清晰些,如下:
命令 | 含义 |
EXPIRE | 设置剩余生存时间,以秒为单位,将键key的生存时间设置为ttl秒 |
PEXPIRE | 设置剩余生存时间,以毫秒为单位,将键key的生存时间设置为ttl毫秒 |
EXPIREAT | 设置剩余生存时间,以秒为单位,将键key的生存时间设置为timestamp所指定的秒数时间戳 |
PEXPIREAT | 设置剩余生存时间,以毫秒为单位,将键key的生存时间设置为timestamp所指定的秒数时间戳 |
TTL | 返回指定key的剩余生存时间,以秒为单位 |
PTTL | 返回指定key的剩余生存时间,以毫秒为单位 |
这个表格给出了指定key的过期时间的存储,这里需要注意一个点,设置指定key生存时间一共有四个命令EXPIRE PEXPIRE EXPIREAT PEXPIREAT,这里展示四个命令底层关系,如图:
我们可以看到,四个命令底层关系:四个设置生存时间的命令,底层最终都是使用PEXPIREAT命令去实现的。
4.2 生存时间的底层保存(过期字典)
redis是基于key-value存储的一个非关系型数据库,对于每一个记录的key,都有一个生存时间TTL,上面介绍了指定key的生存时间的读写,那么,redis中每一个key的生存时间是底层是如何存储的呢?答案是使用“过期字典”存储。
过期字典引入:redisDB结构的expires字典保存了数据库中所有键的过期时间,这个expires字典就是过期字典。
过期字典的键:是一个指针,这个指针指向键空间中的某个键对象(也即是某个数据库键)。
过期字典的值:是一个long long类型的整数 ,这个整数保存了键所指向的数据库键的过期时间,即—个毫秒精度的UNIX时间戳。
展示了一个带有过期字典的数据库例子,在这个例子中,键空间保存了数据库中的所有键值对,而过期时间则保存了数据库中所有按键值对的过期时间。
生存时间(过期时间)的添加和删除略过。
五、尾声
Redis服务端的数据库,完成了。
天天打码,天天进步!