天天看点

Redis | 第4章 Redis中的数据库《Redis设计与实现》

目录

前言

1. Redis中的数据库

2. 数据库的键空间

3. 键的生成时间与过期时间

4. Redis中的过期键删除策略

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

5.1 生成 RDB 文件

5.2 载入 RDB 文件

5.3 AOF 文件写入

5.4 AOF 重写

5.5 复制

6. 数据库通知

最后

参考资料:《Redis设计与实现 第二版》;

第二部分为单机数据库的实现,主要由以下模块组成:数据库、持久化、事件、客户端与服务器;

本篇将介绍 Redis 中的数据库;

与本章相关的 Redis 命令总结在下篇文章,欢迎点击收藏,本篇将不再重复:

《Redis常用命令及示例总结(API)》:https://www.cnblogs.com/dlhjw/p/15639773.html

Redis服务器的所有数据库保存在<code>redis.h/redisService</code>结构的db数组中:

<code>dbnum</code>属性由服务器配置的 database 选项决定,默认为 16;

Redis客户端数据库保存在在<code>redisClient</code>结构的<code>db</code>属性:

客户端通过修改目标数据库指针,让它指向 redisService.db 数组中的不同元素;

可以通过 SELECT index 命令来切换数据库;

Redis | 第4章 Redis中的数据库《Redis设计与实现》

数据库的定义在<code>redis.h/redisDb</code>结构中:

键空间的键是数据库的键,每个键是一个字符串对象;

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

Redis | 第4章 Redis中的数据库《Redis设计与实现》

数据库键空间是一个字典,所有针对数据库的操作都是通过键空间字典来操作的;

在对键空间进行读写操作时,Redis 还会进行一些维护操作:

读取键后,会根据键是否存在更新服务器的键空间命中 keyspace_hits 次数或键空间不命中 keyspace_misses 次数。通过 INFO stats 命令查看属性;

读取键后,服务器会更新键的 LRU(最后一次使用时间)。通过 ONBJECT idlettime [key] 命令查看key的闲置时间;

服务器在读取键时发现键已经过期,会先删除这个过期键;

如果有客户端使用 WATCH 命令监视某个键,服务器对该键修改后会标记上脏 <code>dirty</code>,让事务处理程序注意;

服务器每修改一个键后,会对脏 <code>dirty</code> 键计数器值增 1,计数器会触发服务器的持久化以及复制操作;

键的时间相关设置命令参看《Redis常用命令及示例总结》1.3 生存时间的功能;

生存时间:

客户端可以通过 EXPIRE 或 PEXPIRE 命令以秒或毫秒精度为数据库中某个键设置生存时间(Time To Live,TTL)。经过指定时间后,服务器自动删除生存时间为0的键;

可以通过 SETEX 命令在设置字符串键同时设置过期时间;

使用 TTL 或 PTTL 命令获取键的剩余生存时间;

过期时间:

客户端设置过期时间的命令是 EXPIREAT 或 PEXPIREAT;

过期时间是一个 UNIX 时间戳;

EXPIRE、PEXPIRE 和 EXPIREAT 三个命令都会转换成 PEXPIREAT 命令实现;

有三种删除过期键的策略:

定时删除:主动策略。对内存最友好,到期就释放内存。缺点是对CPU事件不友好,当过期键比较多时,会占用一部分CPU时间;

惰性删除:被动策略。对CPU时间最友好。每次从键空间获取键时,检查取得的键是否过期,过期则删除。缺点是对内存不友好;

定期删除:主动策略。前两种策略的整合与折中。每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长与频率减少删除操作对CPU时间的影响。缺点是难以确定删除操作执行的时长和频率;

惰性删除策略由 <code>db.c/expireIfNeeded</code> 函数实现,流程如下:

Redis | 第4章 Redis中的数据库《Redis设计与实现》

定期删除策略由 <code>redis.c/activeExpireCycle</code> 函数实现,每当Redis的服务器周期性操作 <code>redis.c/serverCron</code> 函数执行时,activeExpireCycle 函数会被调用。在规定的时间内,分多次遍历服务器各个数据库,从数据库的 <code>expires</code> 字典中随机检查一部分过期时间,删除其中过期键;

在执行 SAVE 或 BGSAVE 命令创建一个新的 RBG 文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到新创建的 RDB 文件中;

载入 RDB 文件时:

若服务器以主服务器模式运行,过期键不载入;

若服务器以从服务器模式运行,所有键都会载入;

当服务器以 AOF 持久化模式运行时,未被惰性删除和定期删除的过期键不会对 AOF 文件产生影响;

当过期键被惰性删除或定期删除后,程序会向 AOF 文件追加(append)一条 DEL 命令,显示记录该键已被删除;

与 RDB 文件类似,在执行 AOF 重写过程中,程序会对数据库中的键进行检查,已过期的键不会被保存到重写后的 AOF 文件中;

当服务器运行在复制模式下时,从服务器的过期键删除动作由主服务器控制;

Redis | 第4章 Redis中的数据库《Redis设计与实现》
Redis | 第4章 Redis中的数据库《Redis设计与实现》

数据库通知是 Redis 2.8 版本新增的功能;

数据库通知可以让客户端通过订阅给定的频道或模式,来获知数据库中键的变化,以及数据库中命令的执行情况;

Redis 命令对数据库进行修改后,服务器会根据配置向客户端发送数据库通知;

通知的相关命令可以参考 《Redis常用命令及示例总结》7. Pub/Sub(发布/订阅);

两类通知类型:

键空间通知 key-space notification:关注 “某个键执行了什么命令”;SUBSCRIBE channel:message;

键事件通知 key-event notification:关注 “某个命令被什么键执行了”;SUBSCRIBE channel:del;

服务器配置的 <code>notify-keyspace-events</code> 选项决定服务器所发送通知的类型:

AKE:发送所有类型的键空间和键事件通知;

AK:发送所有类型的键空间通知;

AE:发送所有类型的键事件通知;

K$:只发送字符串有关的键空间通知;

EL:只发送列表键有关的键事件通知;

发送数据库通知的功能是由 <code>notify.c/notifyKeyspaceEvent</code> 函数实现;

新人制作,如有错误,欢迎指出,感激不尽!

欢迎关注公众号,会分享一些更日常的东西!

如需转载,请标注出处!

Redis | 第4章 Redis中的数据库《Redis设计与实现》