Redis 过期的数据会被立马删除么?大有玄机

68 篇文章 0 订阅
43 篇文章 0 订阅
Redis的过期策略包括定期删除和惰性删除,不会立即删除过期key。定期删除每秒运行,随机检查并删除部分过期key;惰性删除在访问key时检查是否过期并删除。从Redis 2.6开始,过期精度提升到1毫秒。Redis 7.0.0后,EXPIRE命令增加了选项。若过期key过多且无法通过定期和惰性删除处理,将触发内存淘汰机制。
摘要由CSDN通过智能技术生成

码哥,当 key 达到过期时间,Redis 就会马上删除么?

先说结论, 并不会立马删除 ,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 添加了选项: NX 、 XX 和 GT 、 LT 选项。

  • 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 会生成删除的指令记录到 AOF 和 slave 节点 。

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

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

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

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

### 回答1: Redis过期数据删除策略主要有两种:惰性删除和定期删除。 惰性删除是指在Redis中,当一个键过期后,它并不立即被删除,而是在客户端尝试访问这个键时,Redis检查这个键是否过期,如果过期了,就删除这个键。这种策略的优点是可以节省内存空间,缺点是可能导致过期键在一段时间内一直存在于内存中,占用内存空间。 定期删除是指Redis定期地扫描数据库中的键,删除已经过期的键。这种策略的优点是可以保证过期键及时被删除,缺点是占用一定的CPU资源和IO资源。 在Redis中,可以通过配置文件中的"maxmemory-policy"选项来选择过期数据删除策略,常用的策略有noeviction(不删除任何数据)、volatile-lru(删除最近最少使用的过期键)、volatile-ttl(删除最近过期的键)、allkeys-lru(删除最近最少使用的键,包括过期和未过期的键)等。 ### 回答2: Redis过期数据删除策略主要有以下几种: 1. 定期删除策略:Redis在指定的时间间隔内,随机抽取一部分过期的键进行删除。这种策略的优点是简单高效,适用于大多数的应用场景。 2. 惰性删除策略:当用户访问一个过期键时,Redis检测该键是否过期,如果过期立即删除。这种策略的优点是内存占用小,不影响正常的读写性能。 3. 定期和惰性删除策略的结合:Redis使用定期删除策略进行过期键的删除,同时在用户访问过期键时进行惰性删除。这种策略的优点是兼具定期删除和惰性删除的优点,能够更加高效地处理过期键。 总体来说,Redis过期数据删除策略主要侧重于通过定期删除和惰性删除两种方式来实现过期数据的清理,以保证Redis的内存使用效率和读写性能。用户可以根据具体的应用场景和需求选择合适的删除策略。 ### 回答3: Redis有三种删除策略来处理过期数据: 1. 惰性删除:当客户端尝试读取一个已过期的键时,Redis删除该键并返回空值。这种方式是最简单的删除策略,但可能导致较长时间的延迟,因为删除操作是在访问发生时触发的。 2. 定期删除Redis每隔一段时间,检查部分设置了过期时间的键,并删除其中已过期的键。默认情况下,Redis每秒检查十个随机键。通过设置`config`中的`hz`参数来调整检查频率。这种策略可以保证过期键的及时删除,但也产生一定的系统开销。 3. 延迟删除(LRU算法):Redis将每个键上的过期时间都记录在一个全局的列表中,并按照时间顺序对这个列表进行排序。当内存不足或者达到最大内存限制时,Redis从列表的最开头开始逐个检查键,并删除其中已过期的键。这种策略能够有效地回收内存,但可能导致删除操作的延迟。 这些删除策略可以根据具体的业务需求进行选择和调整。具体选择哪种策略取决于应用对内存和延迟的要求。例如,如果对内存比较敏感,可以使用定期删除或延迟删除策略;如果对延迟比较敏感,可以使用惰性删除策略。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值