Redis 的过期数据会被立马删除么?

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: Redis 的过期数据会被立马删除么?

码哥,当 key 达到过期时间,Redis 就会马上删除么?还有文末有送书福利么?

先说结论(ps:文末有福利):并不会立马删除。Redis 有两种删除过期数据的策略:

  • 定期选取部分数据删除;
  • 惰性删除;

该命令在 Redis 2.4 版本,过期时间并不是很精确,它可能在零到一秒之间。

从 Redis 2.6 开始,过期错误为 0 到 1 毫秒。

EXPIRE key seconds [ NX | XX | GT | LT] 指令可以将指定的 key 设置过期时间,如果没有设置过期时间, key 将一直存在,除非我们明确将其删除,比如执行 DEL 指令。

所谓”狡兔死,走狗烹“,没用了就干掉,跟 35 岁就“毕业”是一个道理。

好慌……

从 Redis 版本 7.0.0 开始:EXPIRE 添加了选项:NXXXGTLT 选项。

  • NX:当 key 没有过期时才设置过期时间;
  • XX:只有 key 已过期的时候才设置过期时间;
  • GT:仅当新的到期时间大于当前到期时间时才设置过期时间;
  • LT:仅在新到期时间小于当前到期时间才设置到过期时间。

过期与持久化

主从或者集群架构中,两台机器的时钟严重不同步,会有什么问题么?

key 过期信息是用 Unix 绝对时间戳表示的。

为了让过期操作正常运行,机器之间的时间必须保证稳定同步,否则就会出现过期时间不准的情况。

比如两台时钟严重不同步的机器发生 RDB 传输, slave 的时间设置为未来的 2000 秒,假如在 master 的一个 key 设置 1000 秒存活,当 Slave 加载 RDB 的时候 key 就会认为该 key 过期(因为 slave 机器时间设置为未来的 2000 s),并不会等待 1000 s 才过期。

机器时钟不同步导致过期混乱

惰性删除

惰性删除很简单,就是当有客户端的请求查询该 key 的时候,检查下 key 是否过期,如果过期,则删除该 key

比如当 Redis 收到客户端的GET movie:小泽#玛……利亚.rmvb 请求,就会先检查 key = movie:小泽#玛……利亚.rmvb 是否已经过期,如果过期那就删除。

删除过期数据的主动权交给了每次访问请求。

该实现通过 expireIfNeeded函数实现,源码路径:src/db.c

int expireIfNeeded(redisDb *db, robj *key, int force_delete_expired) {
   // key 没有过期,return 0
    if (!keyIsExpired(db,key)) return 0;
    if (server.masterhost != NULL) {
        if (server.current_client == server.master) return 0;
        if (!force_delete_expired) return 1;
    }
    if (checkClientPauseTimeoutAndReturnIfPaused()) return 1;
    /* Delete the key */
    deleteExpiredKeyAndPropagate(db,key);
    return 1;
}

定期删除

仅仅靠客户端访问来判断 key 是否过期才执行删除肯定不够,因为有的 key 过期了,但未来再也没人访问,这些数据要怎么删除呢?

不能让这些数据「占着茅坑不拉屎」。

所谓定期删除,也就是 Redis 默认每 1 秒运行 10 次(每 100 ms 执行一次),每次随机抽取一些设置了过期时间的 key,检查是否过期,如果发现过期了就直接删除。

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

具体步骤如下:

定时删除

  1. 从所有设置了过期时间的 key 集合中随机选择 20 个 key
  2. 删除「步骤 1」发现的所有过期 key 数据;
  3. 「步骤 2 」结束,过期的 key 超过 25%,则继续执行「步骤 1」。

删除的源码 expire.c 的 activeExpireCycle 函数实现

这也就意味着在任何时候,过期 key 的最大数量等于每秒最大写入操作量除以 4。

为啥不检查所有设置过期时间的 key?

你想呀,假设 Redis 里存放了 100 w 个 key,都设置了过期时间,每隔 100 毫秒就检查 100 w 个 key,CPU 全浪费在检查过期 key 上了,Redis 也就废了。

注意了:不管是定时删除,还是惰性删除。当数据删除后master会生成删除的指令记录到AOFslave节点

码哥,如果过期的数据太多,定时删除无法删除完全(每次删除完过期的 key 还是超过 25%),同时这些 key 也再也不会被客户端请求,也就是无法走惰性删除,会怎样?

会不会导致 Redis 内存耗尽,怎么破?

这个问题问得好,答案是走内存淘汰机制

今天就到这里,说太多的话,大家容易在知识的海量里呛死,保命要紧,至于内存淘汰机制详情,请看下回分解。

与实战

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
相关文章
|
4月前
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
4月前
|
数据采集 存储 NoSQL
基于Scrapy-Redis的分布式景点数据爬取与热力图生成
基于Scrapy-Redis的分布式景点数据爬取与热力图生成
274 67
|
10月前
|
NoSQL Redis
Redis的数据淘汰策略有哪些 ?
Redis 提供了 8 种数据淘汰策略,分为淘汰易失数据和淘汰全库数据两大类。易失数据淘汰策略包括:volatile-lru、volatile-lfu、volatile-ttl 和 volatile-random;全库数据淘汰策略包括:allkeys-lru、allkeys-lfu 和 allkeys-random。此外,还有 no-eviction 策略,禁止驱逐数据,当内存不足时新写入操作会报错。
1000 16
|
11月前
|
监控 NoSQL Java
场景题:百万数据插入Redis有哪些实现方案?
场景题:百万数据插入Redis有哪些实现方案?
132 1
场景题:百万数据插入Redis有哪些实现方案?
|
3月前
|
存储 缓存 NoSQL
告别数据僵尸!Redis实现自动清理过期键值对
在数据激增的时代,Redis如同内存管理的智能管家,支持键值对的自动过期功能,实现“数据保鲜”。通过`EXPIRE`设定生命倒计时、`TTL`查询剩余时间,结合惰性删除与定期清理策略,Redis高效维护内存秩序。本文以Python实战演示其过期机制,并提供最佳实践指南,助你掌握数据生命周期管理的艺术,让数据优雅退场。
241 0
|
6月前
|
存储 NoSQL 算法
Redis分片集群中数据是怎么存储和读取的 ?
Redis集群采用的算法是哈希槽分区算法。Redis集群中有16384个哈希槽(槽的范围是 0 -16383,哈希槽),将不同的哈希槽分布在不同的Redis节点上面进行管理,也就是说每个Redis节点只负责一部分的哈希槽。在对数据进行操作的时候,集群会对使用CRC16算法对key进行计算并对16384取模(slot = CRC16(key)%16383),得到的结果就是 Key-Value 所放入的槽,通过这个值,去找到对应的槽所对应的Redis节点,然后直接到这个对应的节点上进行存取操作
|
6月前
|
缓存 NoSQL 关系型数据库
Redis和Mysql如何保证数据⼀致?
1. 先更新Mysql,再更新Redis,如果更新Redis失败,可能仍然不⼀致 2. 先删除Redis缓存数据,再更新Mysql,再次查询的时候在将数据添加到缓存中 这种⽅案能解决1 ⽅案的问题,但是在⾼并发下性能较低,⽽且仍然会出现数据不⼀致的问题,⽐如线程1删除了 Redis缓存数据,正在更新Mysql,此时另外⼀个查询再查询,那么就会把Mysql中⽼数据⼜查到 Redis中 1. 使用MQ异步同步, 保证数据的最终一致性 我们项目中会根据业务情况 , 使用不同的方案来解决Redis和Mysql的一致性问题 : 1. 对于一些一致性要求不高的场景 , 不做处理例如 : 用户行为数据 ,
|
6月前
|
NoSQL Redis
Redis的数据淘汰策略有哪些 ?
Redis 提供 8 种数据淘汰策略: 淘汰易失数据(具有过期时间的数据) 1. volatile-lru(least recently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰 2. volatile-lfu(least frequently used):从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰 3. volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰 4. volatile-random:从已设置过期
|
6月前
|
NoSQL Redis
Redis的数据持久化策略有哪些 ?
Redis 提供了两种方式,实现数据的持久化到硬盘。 1. RDB 持久化(全量),是指在指定的时间间隔内将内存中的数据集快照写入磁盘。 2. AOF持久化(增量),以日志的形式记录服务器所处理的每一个写、删除操作 RDB和AOF一起使用, 在Redis4.0版本支持混合持久化方式 ( 设置 aof-use-rdb-preamble yes )
|
6月前
|
存储 NoSQL Redis
Redis的数据过期策略有哪些 ?
1. 惰性删除 :只会在取出 key 的时候才对数据进行过期检查。这样对 CPU 最友好,但是可能会造成太多过期 key 没有被删除。数据到达过期时间,不做处理。等下次访问该数据时,我们需要判断 a. 如果未过期,返回数据 b. 发现已过期,删除,返回nil 2. 定期删除 : 每隔一段时间抽取一批 key 执行删除过期 key 操作。并且,Redis 底层会通过限制删除操作执行的时长和频率来减少删除操作对 CPU 时间的影响。默认情况下 Redis 定期检查的频率是每秒扫描 10 次,用于定期清除过期键。当然此值还可以通过配置文件进行设置,在 redis.conf 中修改配置“hz”