在设置键的过期时间的同时,创建一个定时器,让定时器在键过期时立即执行对键的删除操作。
定时删除策略可以保证过期键在第一时间删除,并释放所占内存,但是缺点也很明显:如果过期键比较多,删除键的过程会占用 CPU 的时间,对服务器的响应时间与吞吐量造成影响。
不管键的过期时间,每次从键空间中获取键时,检查取得的键是否过期,如果没有过期,则返回该键,如果过期,则删除该键,并返回空。
惰性删除不会在删除无关的过期键上花费时间,对 CPU 时间相对友好,但是对 CPU 内存来说就很不友好了,如果内存在大量的非活跃过期键,这些键会一直占用 CPU 内存,直至获取时才会释放。
每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键,至于时间周期,检查的数据库个数由算法决定。
定期删除策略是上面两种策略的整合和折中,如果采用定期删除策略,必须根据实际情况,合理的设置删除操作的执行时长和执行效率。
Redis 采用的是惰性删除和定期删除两种策略。
Redis 惰性删除策略由 expireIfNeeded
函数实现,所有读写数据库命令执行前都会调用该函数对输入键进行检查,如果输入键已过期,将输入键从数据库中删除,如果未过期,则什么也不做。
Redis 定期删除策略由 activeExpireCycle
函数实现,当 Redis 服务器周期性操作 serverCrib
函数时,该函数就会被调用,它在规定的时间内,分多次遍历服务器中的各个数据库,从 expires
字典中随机检查一部分键的过期时间,如果过期则删除。
对于执行 SAVE
,BGSAVE
命令创建 RDB 文件时,程序会对过期键进行检查,已经过期的键不会被保存到新创建的 RDB 文件中。
服务器启动载入 RDB 文件时,分两种情况:
- 主服务器模式:忽略过期键
- 从服务器模式:保存所有键,主服务器在进行数据同步时,从服务器的数据库会被清空,因此,过期键对载入 RDB 文件的从服务器而言不会受到影响
如果 Redis 服务器以 AOF 持久化模式运行,如果某个键已过期,且还没有被惰性删除或者定期删除,那么 AOF 文件不会有任何影响。当过期键被删除时,程序会向 AOF 文件中追加一条 DEL
命令,表明该键被删除。
AOF 重写过程中,程序会对数据库中的键进行检查,过期键不会被保存到重写后的 AOF 文件中。
复制模式下分两种情况:
- 主服务器删除一个键,会显示向所有从服务器发送一个
DEL
命令,告知从服务器删除这个过期键 - 从服务器在执行客户端发送的请求,即使改建过期,也不会删除,从服务器只有在接收到主服务器发来的
DEL
命令才会处理过期键
《Redis 设计与实现》 黄建宏 著