Redis过期删除策略&内存淘汰策略

文章内容是学习过程中的知识总结,如有纰漏,欢迎指正

文章目录

前言

一、设置Redis键过期时间

二、Redis过期时间的判定

三、过期删除策略有哪些

四、Redis过期删除策略(惰性删除+定期删除)

五、内存淘汰策略

LRU算法 

LFU算法

总结


前言

  • 如何设置Redis键的过期时间?
  • 设置完一个键的过期时间后,到了这个时间,这个键还能获取到么?假如获取不到那这个键还占据着内存吗?
  • 如何设置Redis的内存大小?当内存满了之后,Redis有哪些内存淘汰策略?我们又该如何选择?

让我们带着这几个问题开始本篇内容的学习


以下是本篇文章正文内容

一、设置Redis键过期时间

Redis提供了四个命令来设置过期时间(生存时间)。

  ①、EXPIRE :表示将键 key 的生存时间设置为 ttl 秒。

  ②、PEXPIRE :表示将键 key 的生存时间设置为 ttl 毫秒。

  ③、EXPIREAT :表示将键 key 的生存时间设置为 timestamp 所指定的秒数时间戳。

  ④、PEXPIREAT :表示将键 key 的生存时间设置为 timestamp 所指定的毫秒数时间戳。

PS:在Redis内部实现中,前面三个设置过期时间的命令最后都会转换成最后一个PEXPIREAT 命令来完成。

另外补充两个知识点:

 一、移除键的过期时间

 PERSIST :表示将key的过期时间移除。

 二、返回键的剩余生存时间

 TTL :以秒的单位返回键 key 的剩余生存时间。

 PTTL :以毫秒的单位返回键 key 的剩余生存时间。

二、Redis过期时间的判定

在Redis内部,每当我们设置一个键的过期时间时,Redis就会将该键带上过期时间存放到一个过期字典中。当我们查询一个键时,Redis便首先检查该键是否存在过期字典中,如果存在,那就获取其过期时间。然后将过期时间和当前系统时间进行比对,比系统时间大,那就没有过期;反之判定该键过期。

三、过期删除策略有哪些

通常删除某个key,我们有如下三种方式进行处理。

①、定时删除

  在设置某个key 的过期时间同时,我们创建一个定时器,让定时器在该过期时间到来时,立即执行对其进行删除的操作。

②、惰性删除

  设置该key 过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key。

③、定期删除

  每隔一段时间,我们就对一些key进行检查,删除里面过期的key。

四、Redis过期删除策略(惰性删除+定期删除)

Redis的过期删除策略就是:惰性删除和定期删除两种策略配合使用

惰性删除:Redis的惰性删除策略由 db.c/expireIfNeeded 函数实现,所有键读写命令执行之前都会调用 expireIfNeeded 函数对其进行检查,如果过期,则删除该键,然后执行键不存在的操作;未过期则不作操作,继续执行原有的命令。

定期删除:由redis.c/activeExpireCycle 函数实现,函数以一定的频率运行,每次运行时,都从一定数量的数据库中取出一定数量的随机键进行检查,并删除其中的过期键。

注意并不是一次运行就检查所有的库,所有的键,而是随机检查一定数量的键

定期删除函数的运行频率,在Redis2.6版本中,规定每秒运行10次,大概100ms运行一次。在Redis2.8版本后,可以通过修改配置文件redis.conf 的 hz 选项来调整这个次数。

算法如下:

1.采样ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP(redis参数,默认20)个数的key,并将其中过期的key全部删除;

2.如果超过25%的key过期了,则重复删除的过程,直到过期key的比例降至25%以下

思考:会不会存在某些永远使用不到的键,并且多次定期删除也没选定到进行删除的key?

五、内存淘汰策略

①、设置Redis最大内存

在配置文件redis.conf 中,可以通过参数 maxmemory 来设定最大内存:

不设定该参数默认是无限制的,但是通常会设定其为物理内存的四分之三

②、设置内存淘汰方式

当现有内存大于 maxmemory 时,便会触发redis主动淘汰内存方式,通过设置 maxmemory-policy

有如下几种淘汰方式:

  • volatile-lru:设置了过期时间的key使用LRU算法淘汰;
  • allkeys-lru:所有key使用LRU算法淘汰;
  • volatile-lfu:设置了过期时间的key使用LFU算法淘汰;
  • allkeys-lfu:所有key使用LFU算法淘汰;
  • volatile-random:设置了过期时间的key使用随机淘汰;
  • allkeys-random:所有key使用随机淘汰;
  • volatile-ttl:设置了过期时间的key根据过期时间淘汰,越早过期越早淘汰;
  • noeviction:默认策略,当内存达到设置的最大值时,所有申请内存的操作都会报错(如set,lpush等),只读操作如get命令可以正常执行;
* LRU、LFU和volatile-ttl都是近似随机算法;

使用下面的参数maxmemory-policy配置淘汰策略:

#配置文件
maxmemory-policy noeviction
 
#命令行
127.0.0.1:6379> config get maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"
127.0.0.1:6379> config set maxmemory-policy allkeys-random
OK
127.0.0.1:6379> config get maxmemory-policy
1) "maxmemory-policy"
2) "allkeys-random"

在缓存的内存淘汰策略中有*FIFO、LRU、LFU*三种,其中LRU和LFU是Redis在使用的

FIFO是最简单的淘汰策略,遵循着先进先出的原则,这里简单提一下:

LRU算法 

LRU(Least Recently Used)表示最近最少使用,该算法根据数据的历史访问记录来进行淘汰数据,其核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高”。

LRU算法的常见实现方式为链表:

新数据放在链表头部 ,链表中的数据被访问就移动到链头,链表满的时候从链表尾部移出数据

而在Redis中使用的是近似LRU算法,为什么说是近似呢?Redis中是随机采样5个(可以修改参数maxmemory-samples配置)key,然后从中选择访问时间最早的key进行淘汰,因此当采样key的数量与Redis库中key的数量越接近,淘汰的规则就越接近LRU算法。但官方推荐5个就足够了,最多不超过10个,越大就越消耗CPU的资源。

但在LRU算法下,如果一个热点数据最近很少访问,而非热点数据近期访问了,就会误把热点数据淘汰而留下了非热点数据,因此在Redis4.x中新增了LFU算法。

在LRU算法下,Redis会为每个key新增一个3字节的内存空间用于存储key的访问时间;

LFU算法

LFU(Least Frequently Used)表示最不经常使用,它是根据数据的历史访问频率来淘汰数据,其核心思想是“如果数据过去被访问多次,那么将来被访问的频率也更高”。

LFU算法反映了一个key的热度情况,不会因LRU算法的偶尔一次被访问被误认为是热点数据。

LFU算法的常见实现方式为链表:

新数据放在链表尾部 ,链表中的数据按照被访问次数降序排列,访问次数相同的按最近访问时间降序排列,链表满的时候从链表尾部移出数据。

Redis在实现LFU策略的时候,只是把原来24bit大小的LRU字段,又进一步拆分成了两部分

  • Idt:lru字段的前16bit,表示数据的访问时间戳

  • counter值:lru字段的后8bit,表示数据的访问次数

    总结:当LFU策略筛选数据时,Redis会在候选集合中,根据数据lru字段的后8bit选择访问次数最少的数据进行淘汰。当访问次数相同时,再根据lru字段的前16bit值大小,选择访问时间最久远的数据进行淘汰


总结

Redis过期删除策略是采用惰性删除和定期删除这两种方式组合进行的,惰性删除能够保证过期的数据我们在获取时一定获取不到,而定期删除设置合适的频率,则可以保证无效的数据及时得到释放,而不会一直占用内存数据。

但是我们说Redis是部署在物理机上的,内存不可能无限扩充的,当内存达到我们设定的界限后,便自动触发Redis内存淘汰策略,而具体的策略方式要根据实际业务情况进行选取。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值