Redis过期键策略
注意:hash结构不能为每个key单独设置过期时间,只能为整个键设置过期时间(整个散列表)
Redis 的过期键删除策略
Redis 服务器使用的是惰性删除和定期删除两种策略:通过配合使用这两种删除策略,服务器可以很好地在合理使用 CPU 时间和避免浪费内存空间之间取得平衡。
惰性删除策略的实现
过期键的惰性删除策略由 db.c/expireIfNeeded 函数实现,所有读写数据库的 Redis 命令在执行之前都会调用 expireIfNeeded 函数对输入键进行检查:
- 如果输入键已经过期,那么 expireIfNeeded 函数将输入键从数据库中删除。
- 如果输入键未过期,那么 expireIfNeeded 函数不做动作。
expireIfNeeded 函数就像一个过滤器,它可以在命令真正执行之前,过滤掉过期的输入键,从而避免命令接触到过期键。
定期删除策略的实现
过期键的定期删除策略由 redis.c/activeExpireCycle 函数实现,每当 Redis 的服务器周期性操作 redis.c/serverCron 函数执行时,activeExpireCycle 函数就会被调用,它在规定的时间内,分多次遍历服务器中的各个数据库,从数据库的 expires 字典中随机检查一部分键的过期时间,并删除其中的过期键。
activeExpireCycle 函数的工作模式可以总结如下:
- 函数每次运行时,都从一定数量的数据库中取出一定数量的随机键进行检查,并删除其中的过期键。
- 全局变量 current_db 会记录当前 activeExpireCycle 函数检查的进度,并在下一次 activeExpireCycle 函数调用时,接着上一次的进度进行处理。比如说,如果当前 activeExpireCycle 函数在遍历 10 号数据库时返回了,那么下次 activeExpireCycle 函数执行时,将从 11 号数据库开始查找并删除过期键。
- 随着 activeExpireCycle 函数的不断执行,服务器中的所有数据库都会被检查一遍,这时函数将 current_db 变量重置为 0,然后再次开始新一轮的检查工作。
AOF、RDB 和复制功能对过期键的处理
redis的数据是在内存中来完成的,但是一旦redis的服务器重启,数据就会丢失。所以需要一种数据恢复机制。
redis的数据恢复机制有两种,一种通过AOF(Append only file)文件,另一种是通过RDB快照的方式。
AOF的写入方式:
aof的日志写入方式和mysql的不太一样,mysql采用的是wal(write ahead log) 写前日志,而 redis的aof的写入方式是 数据先写入到内存中去,然后再写入到日志中去。
生成 RDB 文件
在执行 SAVE 命令或者 BGSAVE 命令创建一个新的 RDB 文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到新创建的 RDB 文件中。
例如,如果数据库中包含三个键 k1、k2、k3,并且 k2 已经过期,那么当执行 SAVE 命令或者 BGSAVE 命令时,程序只会将 k1 和 k3 的数据保存到 RDB 文件中,而 k2 则会被忽略。
因此,数据库中包含过期键不会对生成新的 RDB 文件造成影响。
载入 RDB 文件
在启动 Redis 服务器时,如果服务器开启了 RDB 功能,那么服务器将对 RDB 文件进行载入:
如果服务器以主服务器模式运行,那么在载入 RDB 文件时,程序会对文件中保存的键进行检查,未过期的键会被载入到数据库中,而过期键则会被忽略,所以过期键对载入 RDB 文件的主服务器不会造成影响。
如果服务器以从服务器模式运行,那么在载入 RDB 文件时,文件中保存的所有键,不论是否过期,都会被载入到数据库中。不过,因为主从服务器在进行数据同步的时候,从服务器的数据库就会被清空,所以一般来讲,过期键对载入 RDB 文件的从服务器也不会造成影响。
例如,如果数据库中包含三个键 k1、k2、k3,并且 k2 已经过期,那么当服务器启动时:
如果服务器以主服务器模式运行,那么程序只会将 k1 和 k3 载入到数据库,k2 会被忽略。
如果服务器以从服务器模式运行,那么 k1、k2 和 k3 都会被载入到数据库。
AOF 文件写入
当服务器以 AOF 持久化模式运行时,如果数据库中的某个键已经过期,但它还没有被惰性删除或者定期删除,那么 AOF 文件不会因为这个过期键而产生任何影响。当过期键被惰性删除或者定期删除之后,程序会向 AOF 文件追加(append)一条 DEL 命令,来显式地记录该键已被删除。
例如,如果客户端使用 GETmessage 命令,试图访问过期的 message 键,那么服务器将执行以下三个动作:
- 从数据库中删除 message 键。
- 追加一条 DELmessage 命令到 AOF 文件。
- 向执行 GET 命令的客户端返回空回复。
AOF 文件重写
和生成 RDB 文件时类似,在执行 AOF 重写的过程中,程序会对数据库中的键进行检查,已过期的键不会被保存到重写后的 AOF 文件中。
例如,如果数据库中包含三个键 k1、k2、k3,并且 k2 已经过期,那么在进行重写工作时,程序只会对 k1 和 k3 进行重写,而 k2 则会被忽略。因此,数据库中包含过期键不会对 AOF 重写造成影响。