概述
Redis高可用高性能缓存的应用系列的第3篇,主要介绍Redis缓存过期筛选战略和内存筛选战略回收的LRU和LFU的知识点进行说明。
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;
}