redis 过期策略
Redis是key-value类缓存数据库,我们在设置Redis中缓存的key时可以设置过期时间。
那么Redis是如何处理过期的key 呢?
这就要谈到Redis的过期策略了。
过期策略通常有以下三种:
定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。
优点:可以立即清除过期的数据,保证内存被尽快释放;
缺点:会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。
惰性删除:只有当访问一个key时,才会判断该key是否已过期,过期则清除。
优点:可以最大化地节省CPU资源。
缺点:极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。
定期删除:每隔一定的时间(默认是每隔 100ms),会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。
优点:通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。(expires字典会保存所有设置了过期时间的key的过期时间数据,其中,key是指向键空间中的某个键的指针,value是该键的毫秒精度的UNIX时间戳表示的过期时间。键空间是指该Redis集群中保存的所有键。)
缺点:在内存友好方面,不如"定时删除",在CPU时间友好方面,不如"惰性删除"
Redis中同时使用了惰性删除和定期删除两种过期策略。
假设 redis 里放了 100w 个 key,都设置了过期时间,如果每隔100毫秒,就检查 100w 个 key,那redis简直没法玩了, cpu 性能全部消耗在检查过期 key 上了,所以不可能每隔 100ms 就遍历所有的设置过期时间的 key。实际上 redis 是每隔 100ms 随机抽取一些 key 来检查和删除的。
但是定期删除可能会导致很多过期 key 到了时间并没有被删除掉,那怎么办呢?答案是惰性删除。就是说在获取某个 key 的时候,redis 会检查一下 ,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。
但是实际上这还是有问题的,如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期 key 堆积在内存里,导致 redis 内存块耗尽了,怎么办?
这就要提到内存淘汰机制了。
内存淘汰机制
redis 内存淘汰机制有以下几个:
- noeviction: 当内存不足以容纳新写入数据时,新写入操作会报错。
- allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key(这个是最常用的)。
- allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 key。
- volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 key。
- volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 key。
- volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 key 优先移除。