首页 > 数据库 >[转帖]Redis中删除过期Key的三种策略

[转帖]Redis中删除过期Key的三种策略

时间:2024-06-19 13:43:13浏览次数:14  
标签:Key 删除 过期 redis maxmemory Redis 转帖 key

Redis对于过期键有三种清除策略
  • 被动删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key
  • 主动删除:由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动随机淘汰一批已过期的key
  • 当前已用内存超过maxmemory限定时,触发主动清理策略

被动删除

只有key被操作时(如GET),REDIS才会被动检查该key是否过期,如果过期则删除之并且返回NIL。 
1、这种删除策略对CPU是友好的,删除操作只有在不得不的情况下才会进行,不会对其他的expire key上浪费无谓的CPU时间。 
2、但是这种策略对内存不友好,一个key已经过期,但是在它被操作之前不会被删除,仍然占据内存空间。如果有大量的过期键存在但是又很少被访问到,那会造成大量的内存空间浪费。expireIfNeeded(redisDb *db, robj *key)函数位于src/db.c。 
但仅是这样是不够的,因为可能存在一些key永远不会被再次访问到,这些设置了过期时间的key也是需要在过期后被删除的,我们甚至可以将这种情况看作是一种内存泄露—-无用的垃圾数据占用了大量的内存,而服务器却不会自己去释放它们,这对于运行状态非常依赖于内存的Redis服务器来说,肯定不是一个好消息。

主动删除

先说一下时间事件,对于持续运行的服务器来说, 服务器需要定期对自身的资源和状态进行必要的检查和整理, 从而让服务器维持在一个健康稳定的状态, 这类操作被统称为常规操作(cron job)

在 Redis 中, 常规操作由 redis.c/serverCron 实现, 它主要执行以下操作

  • 更新服务器的各类统计信息,比如时间、内存占用、数据库占用情况等。
  • 清理数据库中的过期键值对。
  • 对不合理的数据库进行大小调整。
  • 关闭和清理连接失效的客户端。
  • 尝试进行 AOF 或 RDB 持久化操作。
  • 如果服务器是主节点的话,对附属节点进行定期同步。
  • 如果处于集群模式的话,对集群进行定期同步和连接测试。

Redis 将 serverCron 作为时间事件来运行, 从而确保它每隔一段时间就会自动运行一次, 又因为 serverCron 需要在 Redis 服务器运行期间一直定期运行, 所以它是一个循环时间事件: serverCron 会一直定期执行,直到服务器关闭为止。

在 Redis 2.6 版本中, 程序规定 serverCron 每秒运行 10 次, 平均每 100 毫秒运行一次。 从 Redis 2.8 开始, 用户可以通过修改 hz选项来调整 serverCron 的每秒执行次数, 具体信息请参考 redis.conf 文件中关于 hz 选项的说明也叫定时删除,这里的“定期”指的是Redis定期触发的清理策略,由位于src/redis.c的activeExpireCycle(void)函数来完成。

serverCron是由redis的事件框架驱动的定位任务,这个定时任务中会调用activeExpireCycle函数,针对每个db在限制的时间REDIS_EXPIRELOOKUPS_TIME_LIMIT内迟可能多的删除过期key,之所以要限制时间是为了防止过长时间 的阻塞影响redis的正常运行。这种主动删除策略弥补了被动删除策略在内存上的不友好。

因此,Redis会周期性的随机测试一批设置了过期时间的key并进行处理。测试到的已过期的key将被删除。典型的方式为,Redis每秒做10次如下的步骤:

  1. 随机测试100个设置了过期时间的key
  2. 删除所有发现的已过期的key
  3. 若删除的key超过25个则重复步骤1

这是一个基于概率的简单算法,基本的假设是抽出的样本能够代表整个key空间,redis持续清理过期的数据直至将要过期的key的百分比降到了25%以下。这也意味着在任何给定的时刻已经过期但仍占据着内存空间的key的量最多为每秒的写操作量除以4.

Redis-3.0.0中的默认值是10,代表每秒钟调用10次后台任务。

 

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

  • volatile-lru:只对设置了过期时间的key进行LRU(默认值)
  • allkeys-lru : 删除lru算法的key
  • volatile-random:随机删除即将过期key
  • allkeys-random:随机删除
  • volatile-ttl : 删除即将过期的
  • noeviction : 永不过期,返回错误

当mem_used内存已经超过maxmemory的设定,对于所有的读写请求,都会触发redis.c/freeMemoryIfNeeded(void)函数以清理超出的内存。注意这个清理过程是阻塞的,直到清理出足够的内存空间。所以如果在达到maxmemory并且调用方还在不断写入的情况下,可能会反复触发主动清理策略,导致请求会有一定的延迟。

清理时会根据用户配置的maxmemory-policy来做适当的清理(一般是LRU或TTL),这里的LRU或TTL策略并不是针对redis的所有key,而是以配置文件中的maxmemory-samples个key作为样本池进行抽样清理。

maxmemory-samples在redis-3.0.0中的默认配置为5,如果增加,会提高LRU或TTL的精准度,redis作者测试的结果是当这个配置为10时已经非常接近全量LRU的精准度了,并且增加maxmemory-samples会导致在主动清理时消耗更多的CPU时间,建议:

  • 尽量不要触发maxmemory,最好在mem_used内存占用达到maxmemory的一定比例后,需要考虑调大hz以加快淘汰,或者进行集群扩容。
  • 如果能够控制住内存,则可以不用修改maxmemory-samples配置;如果Redis本身就作为LRU cache服务(这种服务一般长时间处于maxmemory状态,由Redis自动做LRU淘汰),可以适当调大maxmemory-samples。

这里提一句,实际上redis根本就不会准确的将整个数据库中最久未被使用的键删除,而是每次从数据库中随机取5个键并删除这5个键里最久未被使用的键。上面提到的所有的随机的操作实际上都是这样的,这个5可以用过redis的配置文件中的maxmemeory-samples参数配置。

Replication link和AOF文件中的过期处理

为了获得正确的行为而不至于导致一致性问题,当一个key过期时DEL操作将被记录在AOF文件并传递到所有相关的slave。也即过期删除操作统一在master实例中进行并向下传递,而不是各salve各自掌控。这样一来便不会出现数据不一致的情形。当slave连接到master后并不能立即清理已过期的key(需要等待由master传递过来的DEL操作),slave仍需对数据集中的过期状态进行管理维护以便于在slave被提升为master会能像master一样独立的进行过期处理。

</article>

标签:Key,删除,过期,redis,maxmemory,Redis,转帖,key
From: https://www.cnblogs.com/jinanxiaolaohu/p/18256078

相关文章

  • [转帖]springboot中Hikari连接池常用参数含义(一)
    <divid="content_views"class="htmledit_views"><p>yml配置<br><imgalt=""height="235"src="https://img-blog.csdnimg.cn/7724916bc5d449b48114ed52462ba48d.png"......
  • [转帖]JDBC 驱动程序类型
    https://www.jianshu.com/p/fce9ac03a250 什么是JDBC驱动说白了JDBC驱动就是一组实现了JDBCAPI接口的Java类的集合,该接口用于与数据库服务器进行交互。例如,使用JDBC驱动程序可以让你打开数据库连接,并通过发送SQL或数据库命令,然后通过Java接收结果。JDK中的......
  • [转帖]深入理解JDBC的超时设置
     https://www.cnblogs.com/Chary/articles/14958848.html 这是最近读到的讲关于JDBC的超时问题最透彻的文章,原文是http://www.cubrid.org/blog/understanding-jdbc-internals-and-timeout-configuration ,网上现有的翻译感觉磕磕绊绊的,很多上下文信息丢失了,这里用我......
  • Redis 缓存
    文章目录安装redis启动redis简单使用redis安装Redis-Desktop-Manager配置pom文件配置application.properties配置Redis缓存管理器配置service层运行项目安装redis下载地址:https://github.com/tporadowski/redis/releases教程:https://blog.csdn.net/m0_62617719/article......
  • redis——P2:对P1的思考
    到P1结束,redis都已经是一个不错的服务了,具体体现在缓存应用程序需要的数据,甚至在内存爆满的条件下还可以提供服务,似乎目的已经达成。但是实际上可能会遇到一些极端的情况,比如宕机。如果redis宕机了怎么办?目前所有的数据都存储在内存当中,宕机意为着失去所有缓存的数据。前面说过我......
  • redis——P3:持久化
    虽然缓存功能已经实现,但是作为对外提供服务的软件开发者,不能只关注是否提供了正确的服务,稳定和快速恢复等等指标是同样非常非常重要的。考虑这样一个问题,redis确实因为不可抗力宕机了(假设我喜欢黑框框打开,然后手贱按了^C),于是瞬间redis里所有缓存全没了?这对于一个追求高性能、高可......
  • redis——基础服务
    首先为什么要做一个redis出来?数据库不够用了吗?考虑到原本的应用程序是客户端访问服务端,服务端访问业务数据需要去数据库去拿,而数据库是个持久化的应用程序,是需要磁盘IO的,这就导致了速度会慢,并且如果存在大量的访问,会导致数据库崩溃。除去导致崩溃这样严重且极端的情况,这点性能虽然......
  • 认识Redis
    认识RedisRedis是目前最受欢迎的NoSQL数据库之一;db-engines排名上,所有数据库类型排名第六,键值对数据库排名第一。Redis是用C语言编写的开源、支持多种数据结构、支持网络、基于内存、可选持久性的键值对内存型数据库,具备以下特征:基于内存运行、效率高单线程运行支持分布式......
  • 【面试八股总结】Redis数据结构及底层实现
    一、五种基本数据结构        Redis提供了丰富的数据类型,常见的有五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合)结构类型结构可存储值结构读写能力使用命令底层数据结构String字符串、整数或浮点数对字符串或字符串的一部分进行操作,对整数或浮点......
  • 采用java语言+Redis+RabbitMQ开发的 门诊his系统源码 一站式的门诊his系统 门诊业务流
    采用java语言+Redis+RabbitMQ开发的门诊his系统源码一站式的门诊his系统门诊业务流程医院信息系统(HIS系统)门诊业务是医院信息化建设的重要组成部分之一,它涵盖了医院门诊部门涉及的各项业务。HIS系统门诊业务的实施,可以实现医院门诊业务的信息化管理和数据化处理,提高医疗服......