Redis 的过期数据会被立马删除么?
wptr33 2025-01-05 20:32 20 浏览
先说结论(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 添加了选项: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,检查是否过期,如果发现过期了就直接删除。
注意:并不是一次运行就检查所有的库,所有的键,而是随机检查一定数量的键。
具体步骤如下:
定时删除
- 从所有设置了过期时间的 key 集合中随机选择 20 个 key;
- 删除「步骤 1」发现的所有过期 key 数据;
- 「步骤 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 内存耗尽,怎么破?
这个问题问得好,答案是走内存淘汰机制。
今天就到这里,说太多的话,大家容易在知识的海量里呛死,保命要紧,至于内存淘汰机制详情,请看下回分解。
- 上一篇:Redis原理—5.性能和使用总结
- 下一篇:面试题分享:Redis怎么实现分布式锁
相关推荐
- 一篇文章带你了解PHP的学习使用(php的教程)
-
ThinkPHP5实战...
- 在memcached管理php的session(memcached libevent)
-
PHP的session(会话管理)一般是以文件形式进行,而在多个Web服务器之间进行session管理时memecached会比文件管理方式更加方便。在这里介绍如何使用memcached管理PHP的s...
- php传值和传引用的区别(php 传值和传引用)
-
php传值:在函数范围内,改变变量值得大小,都不会影响到函数外边的变量值。PHP传引用:在函数范围内,对值的任何改变,在函数外部也有所体现,因为传引用传的是内存地址。传值:和copy是一样的。【打个比...
- PHP 常量详解教程(php常量和变量)
-
常量类似变量,但是常量一旦被定义就无法更改或撤销定义。PHP常量常量是单个值的标识符(名称)。在脚本中无法改变该值。有效的常量名以字符或下划线开头(常量名称前面没有$符号)。注释:与变量不同,常...
- php自学零基础入门小知识(php新手入门教程)
-
我们就把PHP入门当成一个苹果吧!一口一口的吃掉他!不啰嗦了!开始了1、嵌入方法:类似ASP的<%,PHP可以是<?php或者是<?,结束符号是?>,当然您也可以自己指定。2、...
- PHP 语法详解(php语法大全)
-
PHP脚本在服务器上执行,然后向浏览器发送回纯HTML结果。基础PHP语法PHP脚本可放置于文档中的任何位置。PHP脚本以<?php开头,以?>结尾:<?php...
- PHP笔记(一)PHP基础知识(php必背知识点)
-
创建PHP程序PHP代码框架<?php>2.文件命名规则...
- PHP 8新特性之Attributes(注解),你掌握了吗?
-
PHP8的Alpha版本,过几天就要发布了,其中包含了不少的新特性,当然我自己认为最重要的还是JIT,这个我从2013年开始参与,中间挫折无数,失败无数后,终于要发布的东东。不过,今天呢,我不打算谈J...
- PHP基本语法之标记与注释(php注释规范)
-
1、标记由于PHP是嵌入式脚本语言,它在实际开发中经常会与HTML内容混在一起,所以为了区分HTML与PHP代码,需要使用标记对PHP代码进行标识。如:<html>...
- php注解(PHP注解 性能)
-
目标了解和使用php注解,如果你已经掌握其他一种具有注解的语言,例如:java、python等,你在本文中只需要了解点语法就行。示例php8以前的版本,注解写在注释里,如果你掌握其他语言的注解,你是不...
- 数据丢失?别慌!MySQL备份恢复攻略
-
想象一下,某个晴朗的午后,你正享受着咖啡,突然接到紧急电话:你的网站或APP彻底挂了!系统崩溃,界面全白。虽然心头一紧,但你或许还能安慰自己:系统崩溃只是暂停服务,数据还在,修复修复就好了。然而,如果...
- MySQL 日志:undo log、redo log、binlog
-
今天来和大家分享MySQL的三个日志文件,可以说MySQL的多数特性都是围绕日志文件实现,而其中最重要的有以下三种:...
- MySQL三大日志:binlog、redolog、undolog全解析
-
binlog概述在MySQL数据库中,binlog可是个相当重要的存在,它的全称为binarylog,也就是二进制日志。它就像是数据库的“记忆本”,记录了所有的DDL(数据定义语言)和...
- 1、MySQL数据库介绍(mysql数据库简单介绍)
-
1.1数据库的核心定义数据库的本质数据库乃存储数据对象之容器,涵盖如下关键组件:表(Table)...
- MySQL 日志双雄:实时监控与历史归档实战优化
-
MySQL日志双雄:实时监控+历史归档实战用这招让你家日志系统再也不卡不爆炸MySQL十亿级日志处理:从洪峰到归档全攻略手把手教你用MySQL搞定ELK级日志监控在微服务架构大行其道的今天,日志系统早...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
因果推断Matching方式实现代码 因果推断模型
-
git pull命令使用实例 git pull--rebase
-
面试官:git pull是哪两个指令的组合?
-
git 执行pull错误如何撤销 git pull fail
-
git pull 和git fetch 命令分别有什么作用?二者有什么区别?
-
git fetch 和git pull 的异同 git中fetch和pull的区别
-
git pull 之后本地代码被覆盖 解决方案
-
还可以这样玩?Git基本原理及各种骚操作,涨知识了
-
git命令之pull git.pull
-
- 最近发表
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)