Redis高可用高性能缓存的应用系列03 - 缓存过期淘汰策略LRU、LFU(redis的高可用和高性能是怎么实现的?)
 南窗  分类:IT技术  人气:74  回帖:0  发布于1年前 收藏

概述

Redis高可用高性能缓存的应用系列的第3篇,主要介绍Redis缓存过期淘汰策略的知识点。

Redis过期键删除策略

Redis设置key时,都会设置一个过期时间,那么当过期时间到了都是怎么处理的?

Redis同时使用了惰性过期和定期过期两种方式的缓存淘汰策略。

  • 惰性过期:只有当这个key被访问时,才会判断是否过期,过期则要清理掉,他可以节省CPU的资源,但是会浪费内存的资源,会出现大量过的Key没有被访问过,从而不会被清除,导致内容占用越来越大。
  • 定期过期:每隔一段时间,扫描一定数量的设置了过期时间的key,假如过期了则进行删除操作。

定期过期的执行过程

Redis默认每秒进行10次过期扫描:

1.从过期字典中随机选择20个key

2.删除这20个key中已过期的

3.如果超过25%的key过期,则重复第一步

同时,为了保证业务不受影响,Redis还设置了扫描的时间上限,默认不会超过25ms

内存淘汰策略

1.假如内存不足时,Redis会根据设置的淘汰策略,删除一些不常用的数据,保证Redis的正常使用,所有的前提都是加入键的时候如果超过Redis内存设定的限制后,Redis采用的服务。

1.noeviction: 不会在写入,写入会报错。

2.allkeys-lru:首先通过LRU算法驱逐最久没有使用的键

3.volatile-lru:首先从设置了过期时间的键集合中驱逐没有最久使用的键

4.allkeys-random:从所有过期字典中的key随机删除

5.volatile-random:从过期键的集合中随机驱逐

6.volatile-ttl:从配置了过期时间的键中,驱逐马上就要过期的键

7.volatile-lfu:从配置了过期时间的键中驱逐使用频率最少得键

8.allkeys-lfu:从所有键中使用频率最少的键

LRU

根据最近被使用的时间,距离当前最远的数据优化被淘汰,当有新增key 或者是被访问时,元素会被追加在队尾,需要淘汰时从头部开始淘汰,这个是LRU的思想。

在Redis redisObject 中,维护了一个24位的时钟(有点类似于Cpu的频率),可以简单理解为Cpu对内存使用的时间戳,每个Key对应的也维护了同样24位的时间戳。

比如现在要进行LRU,首先拿到当前系统的时间钟,和Redis redisObject 内存的LRU时间钟对差值计算,差最大的进行淘汰,这里需要注意的是,全局时钟只有24位,按秒计算的话,最多可以存储194天,所以可能出现key时钟大于全局时钟的情况,但是Redis的LRU不会对全局的时钟进行比对,他会从设置了过期时间的key中进行比对。

struct redisObject {
    unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
                            * LFU data (least significant 8 bits frequency
                            * and most significant 16 bits access time). */
};

LFU

LRU只考虑了使用的时间,但是没有考虑Key使用的次数,Redis4.0 以后,新增了LFU的淘汰策略,根据使用时间和次数最为淘汰的权重。

LFU把之前LRU的24bit拆分成两部分,16bit的时间钟和8it的访问频率,8bit比较小,在源码的evict文件中给出了数据。

uint8_t LFULogIncr(uint8_t counter) {
    if (counter == 255) return 255;
    double r = (double)rand()/RAND_MAX;
    double baseval = counter - LFU_INIT_VAL;
    if (baseval < 0) baseval = 0;
    double p = 1.0/(baseval*server.lfu_log_factor+1);
    if (r < p) counter++;
    return counter;
}

讨论这个帖子(0)垃圾回帖将一律封号处理……