看图了解数据库结构,图中的信息不再赘述。
数据库结构一览.jpg键的过期时间
有四个命令可以设置键的过期时间,EXPIRE
、PEXPIRE
、EXPIREAT
、PEXPIREAT
。命令最终都会转化成 PEXPIREAT来执行,存的时间是毫秒级。
移除过期时间用命令 PERSIST
,它会从expires表中删除对应键。
命令 TTL
或 PTTL
,返回键的剩余生存时间。它的不同返回值:
- 返回 nil,表示键不存在;
- 返回 n(n>0),表示剩余生存时间;
- 返回 -1,表示此键无过期时间(永不过期)
带P的表示毫秒级操作
过期键的删除策略
Redis用了两种策略:
- 惰性删除(使用时检查):每次读写数据之前先对数据过期时间进行判断。对CPU友好,但对内存不友好(用不到的键无法被释放,内存浪费);
- 定期删除(同期性定量删):周期性任务,分批定量检查过期键。需要合理地设置执行时长和执行频率。
还有一种策略,但Redis没用,即定时删除策略,设置过期时间时,为这个键创建一个删除用的定时器,这种方式对内存友好,但对CPU不友好(频繁删除时),而且不高效,查找一个事件的复杂度为O(n);
持久化、主从复制对过期键的影响
- 生成 RDB 会过滤掉过期的键;
- 载入 RDB 时如果是主服务器,那么会过滤掉过期键的载入;如果是从服务器则会全部载入,然后依靠主服务器同步信息来删除。
- AOF 写入时,过期键被删除时会写一个 DEL 命令到 AOF 中;
- AOF 重写(重新生成优化的AOF文件)时,会忽略已过期的键。
- 在主从复制中,从服务器从不主动删除过期键,而是由主服务器控制,只有在主服务器发送给从服务器DEL命令时才删除。
最后一条,当主服务器中过期键A已经过期但还未删除,这时如果客户端从从服务器GET A,那也是可以正常获取到的(就像没过期一样)。这会是个坑。
数据库通知
数据库通知是 2.8 版本新增的功能。通过订阅对应的频道或模式,来获知键的事件。
订阅分为键空间通知和键事件通知。
键空间通知:关注某个键被什么命令执行了。SUBSCRIBE __keyspace@0__:message
,即订阅 0 号数据库中 message 这个键上执行的所有命令(只返回命令名)。
键事件通知:关注哪些键执行了某个命令(事件)。SUBSCRIBE __keyevent__@0__:del
,即订阅 0 号数据库中哪些键执行了 DEL 命令。
服务器配置项
notify-keyspace-events
决定服务器可以什么类型的对象可以发送事件以及发送什么类型的事件。
事件订阅和通知的实现原理
(先略,书后面有的话再补充)
网友评论