阅读 156

Redis从入门到放弃系列(七) 过期、内存淘汰策略

Redis从入门到放弃系列(七) 过期、内存淘汰策略

本文例子基于:5.0.4

过期策略

Redis对于设置了过期时间的key的过期策略有两种

  • 惰性删除
  • 定时随机删除

惰性删除

惰性删除的时机在于当你要获取该key的时候再去做判断.这里我以String类型作为演示画图:

string获取key流程
GitHub,Social Coding

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优先移除)

写在最后

端午三天就这样过去啦~愿各位看官好好休息,然后继续起来搬砖~hhhhh

关注下面的标签,发现更多相似文章
评论