浅谈Redis对于过期键的三种清除策略

目录
  • Pre
  • Redis Key的超时设置处理
  • 被动删除
  • 主动删除
  • 当前已用内存超过maxmemory限定时,触发主动清理策略

对于过期键一般有三种删除策略

  • 定时删除:在设置键的过期时间的同时,创建一个定时器(timer),让定时器在键的过期时间来临时,立即执行对键的删除操作;
  • 惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,那就返回该键;
  • 定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于删除多少过期键,以及要检查多少个数据库,则由算法决定。

 下面我们来看看三种策略的优缺比较:

  • 定时删除策略对内存是最友好的:通过使用定时器,定时删除策略可以保证过期键会尽可能快地被删除,并释放过期键所占用的内存;但另一方面,定时删除策略的缺点是,他对CPU是最不友好的:在过期键比较多的情况下,删除过期键这一行为可能会占用相当一部分CPU时间,在内存不紧张但是CPU时间非常紧张的情况下,将CPU时间用在删除和当前任务无关的过期键上,无疑会对服务器的响应时间和吞吐量造成影响;
  • 惰性删除策略对CPU时间来说是最友好的:程序只会在取出键时才对键进行过期检查,这可以保证删除过期键的操作只会在非做不可的情况下进行;惰性删除策略的缺点是,它对内存是最不友好的:如果一个键已经过期,而这个键又仍然保留在数据库中,那么只要这个过期键不被删除,它所占用的内存就不会释放;
  • 定时删除占用太多CPU时间,影响服务器的响应时间和吞吐量;惰性删除浪费太多内存,有内存泄漏的危险。定期删除策略是前两种策略的一种整合和折中:
    • 定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对CPU时间的影响;
    • 通过定期删除过期键,定期删除策略有效地减少了因为过期键而带来的内存浪费;
    • 定期删除策略的难点是确定删除操作执行的时长和频率。

Pre

Redis-17Redis内存回收策略

Redis Key的超时设置处理

expire key seconds

单位是秒。返回1成功,0表示key已经设置过过期时间或者不存在。 如果想消除超时则使用persist key。如果希望采用绝对超时,则使用expireat命令。

ttl key 

返回设置过过期时间的key的剩余过期秒数 -1表示没有设置过过期时间,对于不存在的key,返回-2。

pexpire key 毫秒数

设置生命周期。

pttl  key

以毫秒返回生命周期。

被动删除

当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key.

举个例子, set 一个 过期时间为 600s的 key , 当 到了 600s后,redis 并不会执行删除, 为了性能,redis 会在你下次访问的时候 去删除 。

这样的话,我如果永远不访问,那不歇菜了么? 不要着急,Redis还有主动删除 。

主动删除

由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动淘汰一批已过期的key。

说白了,这就是定时任务干的活,防止有些key 一直占用内存。

当REDIS运行在主从模式时,只有主结点才会执行被动和主动这两种过期删除策略,然后把删除操作”del key”同步到从结点.

当前已用内存超过maxmemory限定时,触发主动清理策略

第三种策略的情况: 当前已用内存超过maxmemory限定时,会触发主动清理策略.

我们需要根据自身业务类型,选好maxmemory-policy(最大内存淘汰策略),设置好过期时间。如果不设置最大内存,当 Redis 内存超出物理内存限制时,内存的数据会开始和磁盘产生频繁的交换 (swap)会让 Redis 的性能急剧下降。

默认策略是volatile-lru,即超过最大内存后,在过期键中使用lru算法进行key的剔除,保证不过期数据不被删除,但是可能会出现OOM问题。

其他策略如下:

  • allkeys-lru:根据LRU算法删除键,不管数据有没有设置超时属性,直到腾出足够空间 为止
  • allkeys-random:随机删除所有键,直到腾出足够空间为止。
  • allkeys-random:随机删除所有键,直到腾出足够空间为止。
  • volatile-ttl:根据键值对象的ttl属性,删除最近将要过期数据。如果没有,回退到noeviction策略。
  • noeviction:不会剔除任何数据,拒绝所有写入操作并返回客户端错误信息"(error)。OOM command not allowed when used memory",此时Redis只响应读操作

记住: volatile 开头的策略,只清理过期的key , 而all开头的策略则不管你过不过期,都会清理。

总结

  • 当client主动访问key会先对key进行超时判断,过时的key会立刻删除。
  • 从节点不会过期扫描,从节点对过期的处理是被动的。 在主从复制环境中,由于上述原因存在已经过期但是没有删除的key,在主snapshot时并不包含这些key,因此在slave环境中我们往往看到dbsize较master是更小的。

如果clien永远都不再get那条key呢?

redis会在Master的后台,每秒10次的执行如下操作:

随机选取100个key校验是否过期,如果有25个以上的key过期了,立刻额外随机选取下100个key(不计算在10次之内)。可见,如果过期的key不多,它最多每秒回收200条左右,如果有超过25%的key过期了,它就会做得更多。

到此这篇关于浅谈Redis对于过期键的三种清除策略的文章就介绍到这了,更多相关Redis 过期键清除内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们! 

(0)

相关推荐

  • 浅谈Redis中的内存淘汰策略和过期键删除策略

    目录 8种淘汰策略 过期键的删除策略 总结 redis是我们现在最常用的一个工具,帮助我们建设系统的高可用,高性能. 而且我们都知道redis是一个完全基于内存的工具,这也是redis速度快的一个原因,当我们往redis中不断缓存数据的时候,其内存总有满的时候(而且内存是很贵的东西,尽量省着点用),所以尽可能把有用的数据,或者使用频繁的数据缓存在redis中,物尽其用. 那么如果正在使用的redis内存用完了,我们应该怎么取舍redis中已存在的数据和即将要存入的数据呢,我们要怎么处理呢? re

  • Redis 2.8-4.0过期键优化过程全纪录

    前言 之前 白馨(陌陌-技术保障部存储工程师 )在Redis技术交流群里,总结了一下Redis从2.8~4.0关于过期键相关的fix记录,非常有帮助,但有些东西未尽详细,本文将进行详细说明. 先从一个问题来看,运行环境如下: Redis: 2.8.19 db0:keys=10000000,expires=10000000 主从结构 从下图中可以看到,在从节点get hello非空,在主节点get hello为空,之后从节点get hello为空,经排查主从同步offset基本正常,但出现了主从不

  • 使用redis实现延迟通知功能(Redis过期键通知)

    Redis 过期监听场景 业务中有类似等待一定时间之后执行某种行为的需求 , 比如 30 分钟之后关闭订单 . 网上有很多使用 Redis 过期监听的 Demo redis配置 把notify-keyspace-events Ex 这一行的注释打开 项目demo工程 项目结构如下图 maven依赖 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apa

  • 浅谈Redis对于过期键的三种清除策略

    目录 Pre Redis Key的超时设置处理 被动删除 主动删除 当前已用内存超过maxmemory限定时,触发主动清理策略 对于过期键一般有三种删除策略 定时删除:在设置键的过期时间的同时,创建一个定时器(timer),让定时器在键的过期时间来临时,立即执行对键的删除操作: 惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键:如果没有过期,那就返回该键: 定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键.至于删除多少过期

  • 浅谈redis的过期时间设置和过期删除机制

    目录 一:设置过期时间 二:保存过期时间 三:移除过期时间 四:计算并返回剩余生存时间 五:过期键的删除策略 六:redis使用的策略 一:设置过期时间 redis有四种命令可以用于设置键的生存时间和过期时间: EXPIRE <KEY> <TTL> : 将键的生存时间设为 ttl 秒 PEXPIRE <KEY> <TTL> :将键的生存时间设为 ttl 毫秒 EXPIREAT <KEY> <timestamp> :将键的过期时间设为

  • 浅谈Redis处理接口幂等性的两种方案

    目录 一.接口幂等性 1.1.什么是接口幂等性 1.2.为什么需要实现幂等性 1.3.引入幂等性后对系统的影响 二.如何设计幂等 2.1.全局的唯一性ID 2.2.幂等设计的基本流程 三.接口幂等性常见解决方案 3.1.下游传递唯一请求编号 3.2.防重 Token 令牌 参考链接: 前言:接口幂等性问题,对于开发人员来说,是一个跟语言无关的公共问题.对于一些用户请求,在某些情况下是可能重复发送的,如果是查询类操作并无大碍,但其中有些是涉及写入操作的,一旦重复了,可能会导致很严重的后果,例如交易

  • 浅谈java中math类中三种取整函数的区别

    math类中三大取整函数 1.ceil 2.floor 3.round 其实三种取整函数挺简单的.只要记住三个函数名翻译过来的汉语便能轻松理解三大函数,下面一一介绍 1.ceil,意思是天花板,java中叫做向上取整,大于等于该数字的最接近的整数 例: math.ceil(13.2)=14 math.ceil(-13.2)=-13 2.floor,意思是地板,java中叫做向下取整,小于等于该数字的最接近的整数 例: math.floor(13.2)=13 math.floor(-13.2)=-

  • 浅谈MySQL8.0 异步复制的三种方式

    本实验中分别针对空库.脱机.联机三种方式,配置一主两从的mysql标准异步复制.只做整服务器级别的复制,不考虑对个别库表或使用过滤复制的情况. 实验环境 [root@slave2 ~]# cat /etc/hosts 192.168.2.138 master 192.168.2.192 slave1 192.168.2.130 slave2 mysql> select version(); +-----------+ | version() | +-----------+ | 8.0.16 |

  • 浅谈Java实现分布式事务的三种方案

    一.问题描述 用户支付完成会将支付状态及订单状态保存在订单数据库中,由订单服务去维护订单数据库.由库存服务去维护库存数据库的信息.下图是系统结构图: 如何实现两个分布式服务(订单服务.库存服务)共同完成一件事即订单支付成功自动减库存,这里的关键是如何保证两个分布式服务的事务的一致性. 尝试解决上边的需求,在订单服务中远程调用减库存接口,伪代码如下: 订单支付结果通知方法{ ​ 更新支付表中支付状态为"成功". ​ 远程调用减库存接口减库存. } 上边的逻辑说明: 1.更新支付表状态为本

  • 浅谈Spring解决循环依赖的三种方式

    引言:循环依赖就是N个类中循环嵌套引用,如果在日常开发中我们用new 对象的方式发生这种循环依赖的话程序会在运行时一直循环调用,直至内存溢出报错.下面说一下Spring是如果解决循环依赖的. 第一种:构造器参数循环依赖 表示通过构造器注入构成的循环依赖,此依赖是无法解决的,只能抛出BeanCurrentlyIn CreationException异常表示循环依赖. 如在创建TestA类时,构造器需要TestB类,那将去创建TestB,在创建TestB类时又发现需要TestC类,则又去创建Test

  • 浅谈.net core 注入中的三种模式:Singleton、Scoped 和 Transient

    从上篇内容不如题的文章<.net core 并发下的线程安全问题>扩展认识.net core注入中的三种模式:Singleton.Scoped 和 Transient 我们都知道在 Startup 的ConfigureServices 可以注入我们想要的服务,那么在注入的时候有三种模式可以选择,那么我们在什么时候选择什么样的模式呢? 在讲注入模式之前,我觉得很有必要了解服务生存期的概念! 服务生存期:ASP.NET Core 提供了一个内置的服务容器 IServiceProvider负责管理服

  • 浅谈Android Studio 解析XML的三种方法

    一丶概述 文件解析要求,json解析和xml解析,前面文章说过Json转实体类,这里就说说解析XML 内容: Android Studio 解析XML常见的三种方式:DOM PULL SAX (实现XML转实体类并打印输出) 效果演示: 二丶正文 SAX(Simple API for XML) 使用流式处理的方式,它并不记录所读内容的相关信息.它是一种以事件为驱动的XML API,解析速度快,占用内存少.使用回调函数来实现. 缺点是不能倒退. DOM(Document Object Model)

随机推荐