1、如果一个键过期了,那么它什么时候会被删除呢?
这个问题有三种可能的答案,它们分别代表了三种不同的删除策略:
定时删除:在设置键的过期时间的同时,创建一个定时器(Timer),让定时器在键的过期时间来临时,立即执行对键的删除操作。
惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期的话就返回该键。
定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。
在这三种策略中,第一种和第三种为主动删除策略,而第二种为被动删除策略。
1.1定时删除
定时删除策略对内存是友好的,可以保证过期键会尽可能快的被删除,并释放过期内存。但是它的缺点是对CPU是最不友好的,在过期键比较多的情况下,删除过期键这一行为可能会占用相当一部分CPU时间,将CPU时间用在删除和当前任务无关的过期键上,无疑会对服务器的响应时间和吞吐量造成影响。除此之外,创建一个定时器需要用到Redis服务器中的时间事件,而当前时间事件的实现方式——无序链表,查找一个事件的时间复杂度为O(N)——并不能高效地处理大量时间事件。因此,要让服务器创建大量的定时器,从而实现定时删除策略,在现阶段来说不现实。
1.2惰性删除
惰性删除策略对CPU时间来说是最友好的:程序只会在取出键时才对键进行过期检查,这可以保证删除过期键的操作只会在非做不可的情况下进行,并且删除的目标仅限于当前处理的键。这种策略的缺点是,它对内存是最不友好的:如果一个键已经过期,而这个键又仍然保留在数据库中,那么只要这个过期键不被删除,它所占用的内存就不会释放。如果数据库中有非常多的过期键,而这些过期键又恰好没有被访问到,那么它们也许永远也不会被删除(除非用户手动执行flushdb),我们甚至可以将这种情况看作是一种内存泄漏。
1.3定期删除
定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响。除此之外,通过定期删除过期键,有效的减少了因为过期键而带来的内存浪费。而这种策略的难点是确定删除操作执行的时长和频率。删除操作太频繁或者太少都不合适。因此,如果采用定期删除策略的话,服务器必须根据情况,合理地设置删除操作的执行时长和执行频率。
Redis服务器实际使用的是惰性删除和定期删除两种策略:通过配合使用这两种策略,服务器可以很好地在合理使用CPU时间和避免浪费内存空间之间取得平衡。
- 内存回收策略
Redis的内存回收策略是指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间的数据。Redis支持6种策略,如下所示:
- noeviction
当内存不足以容纳新写入数据时,新写入操作会报错。 - allkeys-lru
当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。 - allkeys-random
当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。 - volatile-lru
当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。 - volatile-random
当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。 - volatile-ttl
当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。