过期策略
一、设置过期时间
redis有四种命令可以用于设置键的生存时间和过期时间:
EXPIRE : 将键的生存时间设为 ttl 秒
PEXPIRE :将键的生存时间设为 ttl 毫秒
EXPIREAT :将键的过期时间设为 timestamp 所指定的秒数时间戳
PEXPIREAT : 将键的过期时间设为 timestamp 所指定的毫秒数时间戳.
expire <KEY> <TTL> : 将键的生存时间设为 ttl 秒
Pexpire <KEY> <TTL> :将键的生存时间设为 ttl 毫秒
expireAt <KEY> <timestamp> :将键的过期时间设为 timestamp 所指定的秒数时间戳
PexpireAt <KEY> <timestamp>: 将键的过期时间设为 timestamp 所指定的毫秒数时间戳.
二、过期策略
上面设置了过期时间,那么键到期以后,怎么处理这些键呢?处理方式也就是过期策略,常用的过期策略有:定时删除、惰性删除、定期删除。
-
定时删除
每个键设置过期时间后都创建一个定时器,到达过期时间就会立即对Key进行删除。
该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。 -
惰性删除
只在访问一个key时,才会判断该key是否已过期,过期则清除。
该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。 -
定期删除
每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。
redis默认每个100ms检查,是否有过期的key,有过期key则删除。需要说明的是,redis不是每个100ms将所有的key检查一次,而是随机抽取进行检查(如果每隔100ms,全部key进行检查,redis岂不是卡死)。
因此,如果只采用定期删除策略,会导致很多key到时间没有删除。
所以redis应该采用惰性删除+定期删除的方式
● 假设Redis当前存放30万个key,并且都设置了过期时间,如果你每隔100ms就去检查这全部的key,CPU负载会特别高,最后可能会挂掉。
● 因此,redis采取的是定期过期,每隔100ms就随机抽取一定数量的key来检查和删除的。
● 但是呢,最后可能会有很多已经过期的key没被删除。这时候,redis采用惰性删除。在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间并且已经过期了,此时就会删除。
但是如果定期删除漏掉了很多过期的key,然后也没走惰性删除。就会有很多过期key积在内存内存。难道redis直接这样挂掉?并不会,因为Redis会用8种内存淘汰策略保护自己。
淘汰策略
一、设置淘汰策略
应该为Redis指定一种有效的数据淘汰策略以配合maxmemory设置,避免在内存使用满后发生写入失败的情况。
在redis.conf 文件中对以下内容进行配置
maxmemory-policy volatile-lru
二、淘汰策略
淘汰策略是在内存不足以容纳新写入的数据时执行淘汰数据的策略
策略 | 描述 |
---|---|
volatile-lru | 从已设置过期时间的数据集中挑选最近最少使用的数据淘汰 |
volatile-ttl | 从已设置过期时间的数据集中挑选离过期时间最近的数据淘汰 |
volatile-random | 从已设置过期时间的数据集中选择任意数据淘汰 |
allkeys-lru | 从所有数据集中挑选最近最少使用的数据淘汰 |
allkeys-random | 从所有数据集中任意选择数据进行淘汰 |
noeviction | 默认策略,当内存不足以容纳新写入数据时,新写入操作会报错。 |
**ps:**如果没有设置 expire 的key, 不满足先决条件(prerequisites); 那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行为, 和 noeviction(不删除) 基本上一致。