介绍
在Redis中,我们可以为键值对设置有效期,现在面临一个问题,如果一个键值对过期了,那么我们应该怎么删除呢?
我们目前有三种方案:
- 定时删除:在设置键的过期时间的同时,为此键设置一个定时器timer,定时器在键的过期时间来临时,立即自动执行键的删除。
- 惰性删除:放任键不管,但是每次从获取该键时,都会检查此时的键是否过期,如果过期,则此时删除此键;如果没有过期,则返回。
- 定期删除:每隔一段时间,程序对数据库中所有的键检查一次,删除过期的键。
定时删除和定期删除是主动删除,而惰性删除是被动删除
接下来说一说这三种删除策略的特点,以及在Redis中是如何进行过期键删除的。
定时删除
优点:
定时删除对内存友好,通过使用定时器,可以保证过期键会立即尽可能地被删除,释放所占用的内存
缺点:
对CPU不友好,因为为每一个键都创建了一个定时器,那么键非常的情况下,定时器会占用过多CPU资源
除此之外,在Redis中,创建一个定时器还需要用到Redis中的时间事件,而对于时间事件的实现方式是无序列表,查找一个事件的时间复杂度是O(N),效率低,并不能高效地处理大量键过期删除。
惰性删除
优点:
对CPU支持友好
对键的删除并不会占用过多的CPU资源,而是随着键的访问才会对键进行过期检查。
缺点:
对内存不友好
一个键已经过期了,但是还驻留在内存中,那么只要这个键值对不删除,那么就会一直占用内存,可能会导致内存泄漏问题。
定期删除
先总结前两种策略:
- 定时删除占用太多的CPU资源,响应服务器的响应时间和吞吐量
- 惰性删除浪费太多内存,有内存泄漏的风险。
定期删除是对前两种策略的整合和折中: - 定期删除策略每隔一段时间执行一次删除操作,并且可以通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响。
- 定期删除每个一段时间就会对键进行检查,在短时间内不会有过多过期键堆积的问题。有效减少了内存浪费问题。
使用定期删除策略还需要考虑以下几个问题:
- 如果删除操作太频繁,或单次的时间太长,就会导致浪费CPU资源
- 如果删除操作执行次数太少,或单次执行的时间太短,导致不能一次性全部删除过期的键值对,内存中还会存在大量的过期键值对。
所以,必须根据服务器性能,合理调整这两个参数。
Redis中过期删除策略
Redis并没有定时删除的策略,实际使用的是惰性删除和定期删除两种策略,这两种策略配合使用,Redis可以合理地利用CPU和避免内存浪费之间取得平衡。
惰性删除的实现
Redis中惰性删除策略是由一个函数实现的,所有读写数据库的Redis命令在执行之前都会调用这个函数进行过期检查:
- 如果过期则删除
- 如果未过期,则不做任何操作,放行这次的命令
大致的流程:
定期删除策略的实现
定期删除策略在Redis中也是由一个函数实现的,Redis会周期性执行该函数,随机检查一部分key是否过期,并删除过期的键。
在规定时间内,此操作分多次执行,每次都会随机检查一部分key,过期则删除,随着多次执行,数据库中所有key都会被检查一遍