如果你发现,平时在操作 Redis 时,并没有延迟很大的情况发生,但在某个时间点突然出现一波延时,其现象表现为:变慢的时间点很有规律,例如某个整点,或者每间隔多久就会发生一波延迟。如果是出现这种情况,那么你需要排查一下,业务代码中是否存在设置大量 key 集中过期的情况。
在学习Redis缓存的时候我们说过,可以通过expire命令给Redis的key设置TTL(存活时间):
可以发现,当key的TTL到期以后,再次访问name返回的是nil,说明这个key已经不存在了,对应的内存也得到释放。从而起到内存回收的目的。
Redis本身是一个典型的key-value内存存储数据库,因此所有的key、value都保存在之前学习过的Dict结构中。不过在其database结构体中,有两个Dict:一个用来记录key-value;另一个用来记录key-TTL。
Redis之所以性能强,最主要的原因就是基于内存存储。然而单节点的Redis其内存大小不宜过大,会影响持久化或主从同步性能。
当内存使用达到上限时,就无法存储更多数据了。为了解决这个问题,Redis提供了一些策略实现内存回收:
Redis主要有2种过期数据回收策略:
惰性删除
周期删除
内存淘汰:就是当Redis内存使用达到设置的上限时,主动挑选部分key删除以释放更多内存的流程。
这个删除旧数据的逻辑也是需要消耗时间的,而具体耗时的长短,要取决于你配置的淘汰策略:
allkeys-lru
:不管 key 是否设置了过期,淘汰最近最少访问的 key
volatile-lru
:只淘汰最近最少访问、并设置了过期时间的 key
allkeys-random
:不管 key 是否设置了过期,随机淘汰 key
volatile-random
:只随机淘汰设置了过期时间的 key
allkeys-ttl
:不管 key 是否设置了过期,淘汰即将过期的 key
noeviction
:不淘汰任何 key,实例内存达到 maxmeory 后,再写入新数据直接返回错误
allkeys-lfu
:不管 key 是否设置了过期,淘汰访问频率最低的 key(4.0+版本支持)
volatile-lfu
:只淘汰访问频率最低、并设置了过期时间 key(4.0+版本支持)
比较容易混淆的有两个:
Redis的数据都会被封装为RedisObject结构:
最后用一副图来描述当前的这个流程吧