redis--内存淘汰机制

本文详细介绍了Redis的内存淘汰机制,包括为何需要内存淘汰、不同淘汰策略的解析,如LRU、LFU、随机和TTL策略。在内存超出限制时,Redis会依据设定的策略删除数据,确保服务的正常运行。此外,还探讨了两种删除失效主键的方法:消极方法(在访问时检测并删除)和积极方法(定期扫描并删除)。最后,讨论了当内存超过maxmemory限制时的主动清理策略和数据置换过程。
摘要由CSDN通过智能技术生成

一、为什么要有内存淘汰机制

redis是一个内存数据库,在内存空间不足的时候,为了保证命中率,就会选择一定的数据淘汰策略

二、redis配置

我目前试用的redis版本为6.0.3
在这里插入图片描述

1、最大内存参数

在这里插入图片描述

将内存使用限制设置为指定的字节数。
当内存达到限制时,Redis将尝试删除键。根据所选的回收策略(参见maxmemory-policy)。
如果Redis不能根据策略删除键,或者如果策略是设置为’noeviction’, Redis将开始回复错误命令
会使用更多的内存,如SET、LPUSH等,并将继续来响应像GET这样的只读命令。
当使用Redis作为LRU或LFU缓存时,这个选项通常是有用的为实例设置硬内存限制(使用’noeviction’策略)。

2、内存淘汰策略

有以下8种淘汰策略:
在这里插入图片描述

  • volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
  • volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
  • volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
  • volatile-lfu:从已设置过期时间的数据集挑选使用频率最低的数据淘汰。
  • allkeys-lru:从数据集中挑选最近最少使用的数据淘汰
  • allkeys-lfu:从数据集中挑选使用频率最低的数据淘汰。
  • allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  • no-enviction(驱逐):禁止驱逐数据,这也是默认策略。意思是当内存不足以容纳新入数据时,新写入操作就会报错,请求可以继续进行,线上任务也不能持续进行,采用no-enviction策略可以保证数据不被丢失。

总结一下就是大约有4种。lru,lfu,random,ttl。
lru:最近最少使用淘汰
lfu:最少使用频率最低淘汰
random:随机
ttl:将要过期淘汰

三、怎么淘汰?淘汰机制是什么?

1、删除失效主键

redis淘汰,也就是释放内存,从而有内存空间可以保存新的key。redis删除失效主键的方法主要有两种。

  • (1)、消极方法

在主键被访问时如果发现它已经失效,那么就删除它。redis在实现GET、MGET、HGET、LRANGE等所有涉及到读取数据的命令时都会调用 expireIfNeeded,它存在的意义就是在读取数据之前先检查一下它有没有失效,如果失效了就删除它。

int expireIfNeeded(redisDb *db, robj *key) {
    //获取主键的失效时间
    long long when = getExpire(db,key);
    //假如失效时间为负数,说明该主键未设置失效时间(失效时间默认为-1),直接返回0
    if (when < 0) return 0;
    //假如Redis服务器正在从RDB文件中加载数据,暂时不进行失效主键的删除,直接返回0
    if (server.loading) return 0;
    /*假如当前的Redis服务器是作为Slave运行的,那么不进行失效主键的删除,因为Slave
    上失效主键的删除是由Master来控制的,但是这里会将主键的失效时间与当前时间进行
    一下对比,以告知调用者指定的主键是否已经失效了*/
    if (server.masterhost != NULL) {
        return mstime() > when;
    }
    /*如果以上条件都不满足,就将主键的失效时间与当前时间进行对比,如果发现指定的主键
    还未失效就直接返回0*/
    if (mstime() <= when) return 0;
    /*如果发现主键确实已经失效了,那么首先更新关于失效主键的统计个数,然后将该主键失
    效的信息进行广播,最后将该主键从数据库中删除*/
    server.stat_expiredkeys++;
    propagateExpire(db,key);
    return dbDelete(db,key);
}

expireIfNeeded函数中调用的另外一个函数propagateExpire,这个函数用来在正式删除失效主键,并且广播告诉其他地方,目的地有俩:AOF文件,将删除失效主键的这一操作以DEL Key的标准命令格式记录下来;另一个就是发送到当前Redis服务器的所有Slave,同样将删除失效主键的这一操作以DEL Key的标准命令格式告知这些Slave删除各自的失效主键。

void propagateExpire(redisDb *db, robj *key) {
    robj *argv[2];
    //shared.del是在Redis服务器启动之初就已经初始化好的一个常用Redis对象,即DEL命令
    argv[0] = shared.del;
    argv[1] = key;
    incrRefCount(argv[0]);
    incrRefCount(argv[1]);
    //检查Redis服务器是否开启了AOF,如果开启了就为失效主键记录一条DEL日志
    if (server.aof_state != REDIS_AOF_OFF)
        feedAppendOnlyFile(server.delCommand,db->id,argv,2);
    /*检查Redis服务器是否拥有Slave,如果是就向所有Slave发送DEL失效主键的命令,这就是
    上面expireIfNeeded函数中发现自己是Slave时无需主动删除失效主键的原因了,因为它
    只需听从Master发送过来的命令就OK了*/
    if (listLength(server.slaves))
        replicationFeedSlaves(server.slaves,db->id,argv,2);
    decrRefCount(argv[0]);
    decrRefCount(argv[1]);
}
  • (2)、积极方法

周期性地探测,发现失效就删除。消极方法的缺点是,如果key 迟迟不被访问,就会占用很多内存空间,所以才有积极方式。

  • (3)、主动删除

当内存超过maxmemory限定时,触发主动清理策略,该策略由启动参数的配置决定。

2、淘汰数据的量

为了避免频繁的触发淘汰策略,每次会淘汰掉一批数据,淘汰的数据的大小其实是和置换的大小来确定的,如果置换的数据量大,淘汰的肯定也多。

3、置换策略

1、客户端执行一条新命令,导致数据库需要增加数据(比如set key value)
2、Redis会检查内存使用,如果内存使用超过maxmemory,就会按照置换策略删除一些key
3、新的命令执行成功

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值