目录

过期删除策略和内存淘汰策略有什么区别?

介绍一下Redis 内存淘汰策略

不进行数据淘汰

进行数据淘汰策略

在设置了过期时间的数据中进行淘汰

在所有数据范围内进行淘汰

介绍一下Redis过期删除策略

惰性删除

定期删除

一段时间是多久

抽查多少key

定期删除流程

Redis的缓存失效会不会立即删除?

那为什么我不过期立即删除?


过期删除策略和内存淘汰策略有什么区别?

过期删除策略:删除过期的键值内容,redis采用的是惰性删除+过期删除

惰性删除:Redis 不会主动去扫描并删除已过期的键,而是在客户端访问这个键的时候(比如读 / 写操作),才会先调用 expireIfNeeded 检查它是否过期。如果已经过期,就执行删除(同步或异步,取决于配置),然后返回 null;如果没过期,就正常处理请求。

内存淘汰策略:是内存满了的时候redis触发的策略,来淘汰一些不必要的内存资源,腾出空间,保存新的内容

介绍一下Redis 内存淘汰策略

32位的操作系统中maxmemory最大是3GB内存,因32位机器最大支持4GB的内存资源, 加上操作系统本身占用的内存资源,3GB是最大可用内存,这样样可以防止redis实例因内存不足而崩溃

内存淘汰策略分为8种,细分为不进行数据淘汰进行数据淘汰

img

不进行数据淘汰

neoviction:即在运行内存超过设置的最大内存时,不删除键值、而是返回错误不能新增,但是删除和查询还是可以的

进行数据淘汰策略

分为为「在设置了过期时间的数据中进行淘汰」和「在所有数据范围内进行淘汰」

在设置了过期时间的数据中进行淘汰

volatile-random:随机淘汰设置了过期时间的键值

volatitle-ttl:优先淘汰更早过期的键值

volatile-lfu(least frequently used):淘汰最小频率的使用的键值

volatitle-lru(least recently used):淘汰最近使用的使用最少的,就是最久未用的

在所有数据范围内进行淘汰

allkeys-random:所有数据进行随机淘汰

allkeys-lfu:所有数据里淘汰使用频率最小的键值

allkeys-lru:所有数据里淘汰最久未用的键值

介绍一下Redis过期删除策略

redis采用惰性删除+定期删除策略,以求在合理使用cpu和内存资源之间做平衡

惰性删除

惰性删除策略由db.c文件实现:

int expireIfNeeded(redisDb *db, robj *key) {
    // 判断 key 是否过期
    if (!keyIsExpired(db,key)) return 0;
    ....
    /* 删除过期键 */
    ....
    // 如果 server.lazyfree_lazy_expire 为 1 表示异步删除,反之同步删除;
    return server.lazyfree_lazy_expire ? dbAsyncDelete(db,key) :
                                         dbSyncDelete(db,key);
}

每次redis访问key或修改之前,都会用expireIfNeeded检测是否过期

若过期了,就删除这个key,异步/同步删除key根据lazyfree_lazy_expire的参数配置决定(redis4.0开始提供参数)

同步删除:就是删除key之后再给前端返回null,但是如果key的值过于大可能就会响应很慢

异步删除:标记这个值,先给前端返回null,再在后台慢慢删除key

img

定期删除

定期删除是一段时间随机抽查一定数量的key,看是否过期,过期就删除

一段时间是多久

在redis里默认是hz 10 ,也就是每秒十次检查key,时间可以在redis.conf里面配置修改,需要注意的是,key不是全量检测,而是随机性抽查部分key

抽查多少key

定期删除的代码实现在expire.c里面,代码里的方法写死了为20个key每次

定期删除流程

1.先随机抽查20个key

2.检测是否有过期的key,过期则删除

3.过期的key如果数量超过了4,也就是20个的25%,则会再次抽查,直到过期的数量少于25%为止

过期删除为了防止陷入循环过度,设置了循环最大时长,默认为25ms

伪代码如下:

do {
    //已过期的数量
    expired = 0;
    //随机抽取的数量
    num = 20;
    while (num--) {
        //1. 从过期字典中随机抽取 1 个 key
        //2. 判断该 key 是否过期,如果已过期则进行删除,同时对 expired++
    }
    
    // 超过时间限制则退出
    if (timelimit_exit) return;

  /* 如果本轮检查的已过期 key 的数量,超过 25%,则继续随机抽查,否则退出本轮检查 */
} while (expired > 20/4);

流程如下

img

Redis的缓存失效会不会立即删除?

不会,redis删除采用惰性删除+定期删除策略

惰性删除:缓存过期后不会主动删除,而是访问时判断是否过期之后再删除

定期删除:一段时间后抽查key是否过期,过期则删除

那为什么我不过期立即删除?

如果过期的key比较多 ,删除key就需要消耗cpu大量时间,如果在内存充足而cpu时间比较紧张的情况下,cpu时间用在的删除过期key和无关的任务上,会严重拖慢服务器响应速度,降低系统吞吐量,所以立即删除并不友好

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐