目录
前言
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 命令来切换数据库;
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2YfNWawNyZuBnLldjZlFWNjhDNjRmY5QWM5IjN5QjY4UGM0EmMykDM4czLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
数据库的定义在<code>redis.h/redisDb</code>结构中:
键空间的键是数据库的键,每个键是一个字符串对象;
键空间的值是数据库的值,每个值可以是字符串对象、列表对象、哈希表对象、集合对象和有序集合对象中的一种;
数据库键空间是一个字典,所有针对数据库的操作都是通过键空间字典来操作的;
在对键空间进行读写操作时,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> 函数实现,流程如下:
定期删除策略由 <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 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> 函数实现;
新人制作,如有错误,欢迎指出,感激不尽!
欢迎关注公众号,会分享一些更日常的东西!
如需转载,请标注出处!