Redis学习笔记二、数据库

本文深入解析Redis数据库的内部结构,包括redisDb结构体的字段及其作用,如键空间和过期时间管理。介绍了Redis中数据库切换、键空间操作以及键的生存时间和过期时间设置。讨论了三种过期键删除策略:定时删除、惰性删除和定期删除,并指出Redis的实际策略是结合两者。此外,还涵盖了AOF和RDB在处理过期键时的不同处理方式,以及复制模式下主从服务器的处理差异。
摘要由CSDN通过智能技术生成

数据库

  Redis数据库结构体在源码中定义为redis.h/redisDb结构体,结构体并不复杂,其中仅仅含有8个字段,理解*dict、*expires、id三个字段即可。


/* Redis database representation. There are multiple databases identified
 * by integers from 0 (the default database) up to the max configured
 * database. The database number is the 'id' field in the structure. */
typedef struct redisDb {

    // 数据库键空间,保存着数据库中的所有键值对
    dict *dict;                 /* The keyspace for this DB */

    // 键的过期时间,字典的键为键,字典的值为过期事件 UNIX 时间戳
    dict *expires;              /* Timeout of keys with a timeout set */

    // 正处于阻塞状态的键
    dict *blocking_keys;        /* Keys with clients waiting for data (BLPOP) */

    // 可以解除阻塞的键
    dict *ready_keys;           /* Blocked keys that received a PUSH */

    // 正在被 WATCH 命令监视的键
    dict *watched_keys;         /* WATCHED keys for MULTI/EXEC CAS */

    struct evictionPoolEntry *eviction_pool;    /* Eviction pool of keys */

    // 数据库号码
    int id;                     /* Database ID */

    // 数据库的键的平均 TTL ,统计信息
    long long avg_ttl;          /* Average TTL, just for stats */

} redisDb;

   从本篇文章开始记录Redis数据库相关的内容,数据库相关的知识点分为五个部分,分别是Redis服务器中的数据库、键的生存时间和过期时间、过期键删除策略和AOF,RDB,复制功能对过期键的处理。

1. Redis服务器中的数据库

  Redis服务器将所有数据库保存在一个redisDb类型的数组中,数组中每一个redisDb类型的元素代表一个数组。在初始化服务器时,程序会根据服务器状态的dbnum属性来决定应该创建多少个数据库,该属性由服务器配置选项database进行设置。,默认值为16。

在这里插入图片描述
Redis服务器中的数据库

  Redis服务器结构体在源码中定义为redis.h/redisServer结构体,redisServer结构体中数据库相关的定义仅有2个字段*dbdbnum

struct redisServer {
	...
	// 数据库,指向一个长度为dbnum的数组首地址
    redisDb *db;
    // 服务器数量,由服务器配置的database选项确定,默认值为16
    int dbnum;
    ...
}

1.1. 切换数据库

  每个Redis客户端都有自己的目标数据库,当客户端执行命令时,目标数据库就会成为这些命令的操作对象。默认情况下,Redis客户端目标数据库为0号数据库,客户端通过执行SELECT命令来切换目标数据库。

  切换数据库时,只需要将redisClient结构体中的redisDb类型的指针指向redisServer.db相应的数组元素即可。通过修改redisClient.db指针,让其指向服务器中的不同数据库,从而实现切换目标数据库的功能,这便是SELECT命令的实现原理。

在这里插入图片描述
选择数据库

1.2. 数据库键空间

  Redis是一个键值对数据库服务器,在redisDb结构体中有一个dict类型的字典,保存了数据库中的所有键值对,这个字典称为键空间。键空间中的键都是一个STRING对象;值对应Redis支持的五种数据类型中任意一种,分别是STRING、HASH、LIST、SET和ZSET。

在这里插入图片描述
数据库键空间

  数据库的键空间本质上就是一个字典,对Redis数据库的操作,实际上就是对redisDb.dict进行的操作。下面以数据库常见的四种操作增、删、改、查为例分别进行说明。

  增加一个键值对到数据库,实际是将该键值对添加到键空间字典里,键为字符串对象,值为Redis支持的任意类型对象。同样删除,修改,查询数据库中的某个键,实际上是删除,修改,查询redisDb.dict中对应的键值对对象。

  除此之外,还有其他针对Redis键空间的一些操作,如清空数据库FLUSHDB,随机返回某个键RANDOMKEY等。

2. 键的生存时间和过期时间

  有些情况下,需要键空间中的某些键仅在某一个时间段(秒和毫秒级别)存在,过了设定时间就自动删除。Redis提供了两种策略,分别是设置键的生存时间和过期时间。设置键的生存时间,使得键空间中的某些键仅在指定时间内存在,也就是EXPIREPEXPIRE命令。设置键的过期时间,是以UNIX时间戳的方式设置键在某个时间段的有效性,也就是EXPIREATPEXPIREAT命令。

  数据库键的过期时间都保存在过期字典中,对应redisDb.expires属性。Redis中和过期时间相关的知识点包括,设置过期时间,保存过期时间,移除过期时间,计算并返回剩余生存时间,过期键的判定等

3. 过期键删除策略

  既然Redis支持设置键的生存时间和过期时间,那么在键的失效后,如何执行删除操作呢?Redis针对过期键提供了三种不同的过期删除策略,分别是定时删除、惰性删除和定期删除。定时删除和定期删除为主动删除策略,惰性删除为被动删除策略。

3.1. 定时删除

  在设置键的过期时间的同时,创建一个定时器(timer),让定时器在键的过期时间来临时,立即执行对键的删除操作。
  定时删除策略对内存最友好,可以保证过期键尽可能快的被删除。从另一方面讲,这种策略对CPU并不友好,可能会占据相当一部分CPU时间。

  如果有大量命令等待服务器处理,且服务器中有大量空闲内存,如果此时有大量过期键,CPU会去删除这些过期键,而不去处理客户端请求。
  另外,服务器维护大量定时器的创建,也是一个很大的开销,事实上,现阶段使用定时删除策略并不现实。

3.2. 惰性删除

  放任过期键不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期就删除,否则就返回该键。

  惰性删除策略对CPU是最友好的,程序只会在取键时才会对键进行过期检查。从另一方面讲,这种策略对内存并不友好,一些过期键会保留在数据库中。

  如果数据库中有大量过期键,而这些键又恰好没有被访问到,会永远不被删除,这种情况甚至可以被看作内存泄露。
  对于一些和时间有关的数据,如log文件,在某个时间点过后,访问会大大减少,甚至不再访问,这种数据大量积压在数据库,会造成严重的后果。

3.3. 定期删除

  每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。

  定期删除可以看作定时删除和惰性删除两种策略的折中,但执行起来有一定难度,主要问题在确定删除操作的执行时长和删除频率。因此,如果采用定期删除策略,一定要根据服务器具体情况,合理设置删除操作的执行时长和删除频率。

3.4. Redis的过期键删除策略

  Redis服务器使用的过期键删除策略是惰性删除和定期删除配合使用。惰性删除由db.c/expireIfNeeded函数实现,所有读写数据库的Redis命令,在执行之前都会调用expireIfNeeded函数对输入键进行检查;定期删除策略由redis.c/activeExpireCycle函数实现,每当redis的服务器周期性操作redis.c/serverCron函数执行时,activeExpireCycle函数就会被调用。

4. AOF、RDB和复制功能对过期键处理

  • RDB:Redis的RDB文件涉及到的对过期键操作,主要体现在生成RDB文件和载入RDB文件两个过程中。

生成RDB文件和载入RDB文件:

  1. 生成RDB文件 :执行SAVE或者BGSAVE命令时,程序会对数据库进行检查,已过期的键不会被保存到新创建的RDB文件中
  2. 载入RDB文件:如果服务器以主服务器模式运行,过期键会被忽略,不会对RDB文件主服务器造成影响;如果服务器以从服务器模式运行,载入RDB文件时,文件中保存的所有键都会载入到数据库中。
  • AOF:Redis的AOF文件涉及到的对过期键的操作,主要体现在AOF文件写入和AOF文件重写两个过程中。

AOF文件写入和AOF重写:

  1. AOF文件写入:当执行GET命令,发现过期键被惰性删除或定期删除之后,程序会向AOF文件追加(append)一条DEL命令,来显式地记录该键已被删除。
  2. AOF重写:在执行AOF重写过程中,程序会对数据库中的键进行检查,已过期的键不会保存到重写后的AOF文件中。
  • 复制:当服务器运行在复制模式下,从服务器的过期删除动作由主服务器控制,从服务器即使发现过期键也不会自作主张删除它。

5. 参考文献

[1] 黄健宏.Redis设计与实现[M].北京:机械工业出版社

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值