Redis(十二):Redis过期键删除策略、AOF、RDB、复制功能对过期键处理与数据库通知实现原理

//如果小于,就要根据现有的数据库数量进行检查,否则会越界

db_numbers = server.dbnum;

}

//如果不小于,那就按照默认的检查数量去进行

else{

db_numbers = DEFAULT_KEY-NUMBER;

}

//遍历各个数据库

FOR i IN range(db_numbers):

//先判断进度是否已经完成了,即是否检查完数据库了

//如果当前检查进度,即检查过的数据库数量等于服务器拥有的数据库,那就从头开始,进度归零

IF(current_db == server.dbnum){

current_db = 0;

}

//获取当前数据库(全局记录的db)

redisDB = server.db[current_db];

//让current_db自增,为了下一次的检查

current_db++;

//检查指定数量数据库的键

FOR j IN range(DEFAULT_KEY_NUMBER){

//如果里面没有过期键,就跳出

IF(redisDB.expires.size() == 0){break;}

//通过expires字典随机获取一个键

key_with_ttl = redisDB.expires.get_random_key();

//检查键是否过期,如果过期就删除它

IF(is_expired(key_with_ttl)){

delete_key(key_with_ttl);

}

//没过期就不做任何处理

//最后一步判断执行时间是否达到了上限

if(reach_time_limit()){

//达到上限就结束,等下一次的定期删除

return

}

}

}

重点

  • 拥有全局变量来记录当前进度(current_db,记录检查过的数据库数量,同时记录第一个未检查过的数据库),还有配置文件上有默认的每次定期删除策略检查的数据库数量和检查每个数据库多少个键(即DEFAULT_DB_NUMBER和DEFAULT_KEY_NUMBER)

  • 函数每次运行时,都根据参数去数据库中扫描指定数量的数据库,每个数据库检查指定数量的键值对,并删除里面的过期键

  • 如果在检查键值对的时候,函数执行时间达到了规定的时间,就会停止检查,这不会影响下一次的检查,因为current_db记录了下一个未检查的数据库,下一次会从这个数据库开始

  • 当current_db等于服务器拥有的数据库数量,就代表所有数据库已经都被检查过了,需要重新开始新一轮的检查工作

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


RDB和AOF是Redis的两种持久化策略,后面再详说,现在简单认识一下这两种持久化策略是怎么处理过期键的

RDB

RDB持久化策略是将数据持久化进磁盘的RDB文件里面。

生成RDB文件

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

因此,数据库中包含过期键不会对新生成的RDB文件造成影响(但旧的RDB文件可能会包含过期键,因为那时候键还没有过期,要等下一次覆盖RDB文件的时候才会刷新)。

载入RDB文件

启动Redis服务器时,如果使用的是RDB功能的话,那么服务器将对RDB文件进行载入

载入情况又分为主服务器模式载入和从服务器模式载入

  • 如果服务器以主服务器模式运行,那么在载入RDB文件时,程序会对RDB文件里面的键进行检查,如果过期了就不会载入,过期的了就会被忽略掉。

  • 如果服务器以从服务器模式运行,那么在载入RDB文件时,程序会加载RDB里面所有的键,不论是否过期,虽然过期键被载入,不过在主从服务器进行同步更新的时候,从服务器的数据库会被清空,替换成主服务器的数据,过期键也在这里被清掉了。

所以,一般来说,过期键对载入RDB文件的从服务器也不会造成影响的

AOF

AOF持久化策略其实记录的是写入的redis命令,记录进AOF文件中,然后加载的时候,其实就是执行这些redis命令

AOF文件写入

当服务器以AOF持久化模式运行时,如果数据库中的某个键过期了,且这个键还没有被定期或者惰性删除,是不会AOF产生影响的。

当这个键被定期或者惰性删除时,AOF文件也会追加一条DEL命令,去显示地标识这个键被删除

举个栗子

  • 创建一个5s后过期的键,AOF文件记录了该创建命令

  • 5s后使用访问该键,发现过期,会执行惰性删除策略(定期删除策略在这里也会执行删除),把键删除掉

  • 同时在AOF文件中追加DEL命令

  • 访问放回nil值

AOF文件重写

和生成RDB文件一样,已经过期的键不会被重写入AOF文件中,因此,数据库包含过期键不会对AOF造成影响

复制功能

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

  • 当主服务器在删除一个过期键后,会显示地向所有从服务器发送一个DEL命令,通知从服务器去删除该键值对

  • 从服务器在执行客户端发送的读命令时,及时读取的是过期键,也不会进行删除,而是像处理未过期的键一样去处理,返回过期键里面对应的值对象

  • 从服务器只有在收到主服务器的DEL命令才会去删除键

数据库通知


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

//客户端在指定频道上发布信息

publish channel message

//客户端订阅频道

subscribe channel

在这里插入图片描述

Redis会自动发送上面所示的两种通知

  • 第一种为键空间通知

  • 第二种为键事件通知

foo指的就是键值对对象的key指,所以keyspce@0__foo其实就是频道名称,del是指对其执行的操作命令,或者keyspace@0:del是频道名称,foo就是其操作的键值对对象key值

不过因为数据库通知是会占用CPU的,所以默认会关闭,要在配置文件进行开启

在这里插入图片描述

键空间通知

键空间是数据库里面的属性,当用户在这个数据库里面进行对键值对的操作时候,Redis就会发送通知给keyspace@0频道,所有关注了keyspace@0频道的用户都会接收这个消息

举个栗子

首先将配置文件的notify-keyspace-events的值改为AK,标识开启键空间通知,并且接收所有类型

//关注了0号数据库的message对象

subscribe @keyspace@0:message

//开启另一个redis,创建message为键名的字符串对象

set message haha

在这里插入图片描述

键事件通知

与键空间通知不同,键空间通知是将对指定键的操作通知给订阅频道的客户端,而键事件通知是指将发送了指定事件的键值对对象的键名发送给订阅频道的客户端

举个栗子

首先将配置文件的notify-keyspace-events的值改为AE,标识开启接收所有键事件通知。

//订阅0号数据库的del事件

subscribe keyevent@0:del

//另一个数据库执行Del事件

del msg

在这里插入图片描述

notify-keyspace-events的配置

这里简单介绍一下这个配置,详细可以看配置文件的注释

  • AKE:服务器发送所有类型的键空间通知和键事件通知

  • AK:服务器发送所有类型的键空间通知

  • AE:服务器发送所有类型的键事件通知

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

  • EI:只发送和列表键有关的键空间通知

发送通知的实现原理

发送数据库通知的功能是由notify.c/notifyKeyspaceEvent函数去执行的

**void notifyKeyspaceEvent(int type,char event,robj key,int dbid);

  • type其实就是当前想要发送的通知的类型,程序会根据这个值去判断当前发送通知的类型是否跟配置文件里面的notify-keyspace-event匹配,从而决定通知是否发送

  • event是事件的名称,用字符指针来实现字符串,比如删除事件为DEL,过期事件为EXPIRE

  • key是产生事件的键对象

  • dbid是数据库号

当开启了数据库通知之后,当执行Redis命令之后,命令的实现函数在实现操作成功后都会调用notify-KeyspaceEvent函数,去判断是否需要发送通知

实现的伪代码

def notifyKeyspaceEvent(type,event,key,dbid);

//先判断是否符合配置文件的设定的要求

//如果不符合直接结束

if not(server.notify_keyspace_events & type) return;

//符合条件进行发送通知

//如果配置的要求是键空间,则发送键空间通知

if(server.notify_keyspace_events & REDIS_NOTIFY_KEYSPACE)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值