Redis从入门到放弃系列(七) 过期、内存淘汰策略
本文例子基于:5.0.4
过期策略
Redis对于设置了过期时间的key的过期策略有两种
- 惰性删除
- 定时随机删除
惰性删除
惰性删除的时机在于当你要获取该key的时候再去做判断.这里我以String类型作为演示画图:
int expireIfNeeded(redisDb *db, robj *key) {
if (!keyIsExpired(db,key)) return 0;
/* If we are running in the context of a slave, instead of
* evicting the expired key from the database, we return ASAP:
* the slave key expiration is controlled by the master that will
* send us synthesized DEL operations for expired keys.
*
* Still we try to return the right information to the caller,
* that is, 0 if we think the key should be still valid, 1 if
* we think the key is expired at this time. */
if (server.masterhost != NULL) return 1;
/* Delete the key */
server.stat_expiredkeys++;
propagateExpire(db,key,server.lazyfree_lazy_expire);
notifyKeyspaceEvent(NOTIFY_EXPIRED,
"expired",key,db->id);
return server.lazyfree_lazy_expire ? dbAsyncDelete(db,key) :
dbSyncDelete(db,key);
}
我们发现,当key有设置了过期时间,然后key已经过期的话,那么redis会判断是否开启了lazyfree_lazy_expire
,如果开启的话,那么异步删除.没有则同步直接删除.(4.0之后的特性,当大key删除的时候非常有用)
定时随机删除
当有了惰性删除之后,满足了一部分的需求,可是在实际应用中,会存在有过期而没有被访问到的key,这样就会平白的占据着内存.那么redis是通过怎样去解决的呢?
redis会有一个定时任务,每秒跑10次。
- 随机选择设置了过期时间的20个key进行过期检测
- 删除所有已经过期的keys
- 如果超过25%的密钥过期,请从步骤1重新开始。
由于redis是单线程,如果任由上面定时随机删除策略的话,那么当有大量的key过期的时候,redis会存在无法处理客户端请求的情况?不不不,其实redis在做定时随机删除的时候,有一个限制,就是设置扫描时间的上限,默认至多为25ms(timelimit = 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100;),所以当客户端请求到来时,服务器正处于过期扫描期间,客户端会等到至多25ms然后进行其业务处理.
那么如果redis设置超时时间过短的话,有可能出现大量超时连接,为了避免这个问题,建议是在设置过期时间是时候,加多一个随机范围,避免大量的key同时过期~
当有做主从的时候,从库是不会开启定时随机删除的,都是依赖master开启的aof文件中增加一条del命令,然后从库去执行该语句实现删除该过期key
内存淘汰策略
我们知道redis是纯内存数据库,如果redis使用超出了内存限制的时候,便会产生swap行为. 使用磁盘来操作相比内存来说,性能下降的不是一丁半点。 这时候我们需要设置redis最大使用内存
maxmemory <bytes>
通过设置maxmemory,当使用内存超过maxmemory的时候,redis提供了几种可选的策略来控制内存的使用量
- noeviction (当内存不足以容纳新写入数据时,新写入操作会报错)
- allkeys-lru (当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key)
- allkeys-random (当内存不足以容纳新写入数据时,在键空间中,随机移除某个key)
- volatile-lru (当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key)
- volatile-random (当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key)
- volatile-ttl (当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除)