热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Redis中的过期元素是如何被处理的?「视频版」——面试突击002期

本文以面试问题「Redis中的过期元素是如何被处理的?」为切入点,用视频加图文的方式和大家聊聊Redis过期元素被处理的相关知识点。涉及的知识点过期删

本文以面试问题「Redis 中的过期元素是如何被处理的?」为切入点,用视频加图文的方式和大家聊聊 Redis 过期元素被处理的相关知识点。



涉及的知识点


  1. 过期删除策略有哪些?
  2. 这些过期策略有哪些优缺点?
  3. Redis 使用的是什么过期策略?
  4. Redis 是如何优化和执行过期策略的?

视频答案

点击查看视频内容:https://www.bilibili.com/video/av88741972/


图文答案

常见的过期策略:


  • 定时删除
  • 惰性删除
  • 定期删除

1)定时删除

在设置键值过期时间时,创建一个定时事件,当过期时间到达时,由事件处理器自动执行键的删除操作。


① 优点

保证内存可以被尽快的释放


② 缺点

在 Redis 高负载的情况下或有大量过期键需要同时处理时,会造成 Redis 服务器卡顿,影响主业务执行。


2)惰性删除

不主动删除过期键,每次从数据库获取键值时判断是否过期,如果过期则删除键值,并返回 null。


① 优点

因为每次访问时,才会判断过期键,所以此策略只会使用很少的系统资源。


② 缺点

系统占用空间删除不及时,导致空间利用率降低,造成了一定的空间浪费。


③ 源码解析

惰性删除的源码位于 src/db.c 文件的 expireIfNeeded 方法中,源码如下:

int expireIfNeeded(redisDb *db, robj *key) {// 判断键是否过期if (!keyIsExpired(db,key)) return 0;if (server.masterhost != NULL) return 1;/* 删除过期键 */// 增加过期键个数server.stat_expiredkeys++;// 传播键过期的消息propagateExpire(db,key,server.lazyfree_lazy_expire);notifyKeyspaceEvent(NOTIFY_EXPIRED,"expired",key,db->id);// server.lazyfree_lazy_expire 为 1 表示异步删除(懒空间释放),反之同步删除return server.lazyfree_lazy_expire ? dbAsyncDelete(db,key) :dbSyncDelete(db,key);
}
// 判断键是否过期
int keyIsExpired(redisDb *db, robj *key) {mstime_t when &#61; getExpire(db,key);if (when <0) return 0; /* No expire for this key *//* Don&#39;t expire anything while loading. It will be done later. */if (server.loading) return 0;mstime_t now &#61; server.lua_caller ? server.lua_time_start : mstime();return now > when;
}
// 获取键的过期时间
long long getExpire(redisDb *db, robj *key) {dictEntry *de;/* No expire? return ASAP */if (dictSize(db->expires) &#61;&#61; 0 ||(de &#61; dictFind(db->expires,key->ptr)) &#61;&#61; NULL) return -1;/* The entry was found in the expire dict, this means it should also* be present in the main dict (safety check). */serverAssertWithInfo(NULL,key,dictFind(db->dict,key->ptr) !&#61; NULL);return dictGetSignedIntegerVal(de);
}

所有对数据库的读写命令在执行之前&#xff0c;都会调用 expireIfNeeded 方法判断键值是否过期&#xff0c;过期则会从数据库中删除&#xff0c;反之则不做任何处理。


3&#xff09;定期删除

每隔一段时间检查一次数据库&#xff0c;随机删除一些过期键。

Redis 默认每秒进行 10 次过期扫描&#xff0c;此配置可通过 Redis 的配置文件 redis.conf 进行配置&#xff0c;配置键为 hz 它的默认值是 hz 10

需要注意的是&#xff1a;Redis 每次扫描并不是遍历过期字典中的所有键&#xff0c;而是采用随机抽取判断并删除过期键的形式执行的。

定期删除的执行流程&#xff1a;


① 优点

通过限制删除操作的时长和频率&#xff0c;来减少删除操作对 Redis 主业务的影响&#xff0c;同时也能删除一部分过期的数据减少了过期键对空间的无效占用。


② 缺点

内存清理方面没有定时删除效果好&#xff0c;同时没有惰性删除使用的系统资源少。


③ 源码解析

定期删除的核心源码在 src/expire.c 文件下的 activeExpireCycle 方法中&#xff0c;源码如下&#xff1a;

void activeExpireCycle(int type) {static unsigned int current_db &#61; 0; /* 上次定期删除遍历到的数据库ID */static int timelimit_exit &#61; 0; /* Time limit hit in previous call? */static long long last_fast_cycle &#61; 0; /* 上一次执行快速定期删除的时间点 */int j, iteration &#61; 0;int dbs_per_call &#61; CRON_DBS_PER_CALL; // 每次定期删除&#xff0c;遍历的数据库的数量long long start &#61; ustime(), timelimit, elapsed;if (clientsArePaused()) return;if (type &#61;&#61; ACTIVE_EXPIRE_CYCLE_FAST) {if (!timelimit_exit) return;// ACTIVE_EXPIRE_CYCLE_FAST_DURATION 是快速定期删除的执行时长if (start server.dbnum || timelimit_exit)dbs_per_call &#61; server.dbnum;// 慢速定期删除的执行时长timelimit &#61; 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100;timelimit_exit &#61; 0;if (timelimit <&#61; 0) timelimit &#61; 1;if (type &#61;&#61; ACTIVE_EXPIRE_CYCLE_FAST)timelimit &#61; ACTIVE_EXPIRE_CYCLE_FAST_DURATION; /* 删除操作的执行时长 */long total_sampled &#61; 0;long total_expired &#61; 0;for (j &#61; 0; j ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP)num &#61; ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP;// 从数据库中随机选取 num 个键进行检查while (num--) {dictEntry *de;long long ttl;if ((de &#61; dictGetRandomKey(db->expires)) &#61;&#61; NULL) break;ttl &#61; dictGetSignedInteger// 过期检查&#xff0c;并对过期键进行删除if (activeExpireCycleTryExpire(db,de,now)) expired&#43;&#43;;if (ttl > 0) {/* We want the average TTL of keys yet not expired. */ttl_sum &#43;&#61; ttl;ttl_samples&#43;&#43;;}total_sampled&#43;&#43;;}total_expired &#43;&#61; expired;if (ttl_samples) {long long avg_ttl &#61; ttl_sum/ttl_samples;if (db->avg_ttl &#61;&#61; 0) db->avg_ttl &#61; avg_ttl;db->avg_ttl &#61; (db->avg_ttl/50)*49 &#43; (avg_ttl/50);}if ((iteration & 0xf) &#61;&#61; 0) { /* check once every 16 iterations. */elapsed &#61; ustime()-start;if (elapsed > timelimit) {timelimit_exit &#61; 1;server.stat_expired_time_cap_reached_count&#43;&#43;;break;}}/* 每次检查只删除 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP/4 个过期键 */} while (expired > ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP/4);}// .......
}

activeExpireCycle 方法在规定的时间&#xff0c;分多次遍历各个数据库&#xff0c;从过期字典中随机检查一部分过期键的过期时间&#xff0c;删除其中的过期键。

这个函数有两种执行模式&#xff0c;一个是快速模式一个是慢速模式&#xff0c;体现是代码中的 timelimit 变量&#xff0c;这个变量是用来约束此函数的运行时间的。快速模式下 timelimit 的值是固定的&#xff0c;等于预定义常量 ACTIVE_EXPIRE_CYCLE_FAST_DURATION&#xff0c;慢速模式下&#xff0c;这个变量的值是通过 1000000*ACTIVE_EXPIRE_CYCLE_SLOW_TIME_PERC/server.hz/100 计算的。


总结

本文讲了常见的过期删除策略&#xff1a;


  • 定时删除
  • 惰性删除
  • 定期删除

Redis 采用的是惰性删除 &#43; 定期删除的组合策略&#xff0c;更多内容&#xff0c;详见视频部分。

关注下面二维码&#xff0c;订阅更多精彩内容。

Java中文社群公众号二维码


推荐阅读
  • Redis的默认端口、数据库使用和多端口配置
    本文介绍了Redis的默认端口、数据库使用和多端口配置的方法。通过选择不同的数据库和使用flushdb命令可以实现对不同数据库的访问和清除数据。同时,本文还介绍了在同一台机器上启用多个Redis实例的方法,并讨论了配置认证密码的步骤和注意事项。 ... [详细]
  • 安装mysqlclient失败解决办法
    本文介绍了在MAC系统中,使用django使用mysql数据库报错的解决办法。通过源码安装mysqlclient或将mysql_config添加到系统环境变量中,可以解决安装mysqlclient失败的问题。同时,还介绍了查看mysql安装路径和使配置文件生效的方法。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 本文介绍了关系型数据库和NoSQL数据库的概念和特点,列举了主流的关系型数据库和NoSQL数据库,同时描述了它们在新闻、电商抢购信息和微博热点信息等场景中的应用。此外,还提供了MySQL配置文件的相关内容。 ... [详细]
  • Linux下安装免费杀毒软件ClamAV及使用方法
    本文介绍了在Linux系统下安装免费杀毒软件ClamAV的方法,并提供了使用该软件更新病毒库和进行病毒扫描的指令参数。同时还提供了官方安装文档和下载地址。 ... [详细]
  • Redis API
    安装启动最简启动命令行输入验证动态参数启动配置文件启动常用配置通用命令keysbdsize计算key的总数exists判断是否存在delkeyvalue删除指定的keyvalue成 ... [详细]
  • 面试经验分享:华为面试四轮电话面试、一轮笔试、一轮主管视频面试、一轮hr视频面试
    最近有朋友去华为面试,面试经历包括四轮电话面试、一轮笔试、一轮主管视频面试、一轮hr视频面试。80%的人都在第一轮电话面试中失败,因为缺乏基础知识。面试问题涉及 ... [详细]
  • Redis通用指令及数据库操作详解
    本文详细介绍了Redis中的通用指令,包括key的基本操作、扩展操作和查询模式,以及数据库的基本操作和相关操作。同时还解决了key重复问题,并提供了解决方案。文章内容参考了黑马Redis教程。 ... [详细]
  • linux服务器时间同步失败解决方法
    linux服务器时间同步失败解决方法1、为什么会时间不同步:①计算机的时间是根据电脑晶振以固定频率震荡而产生的,由于晶振的不同或者老化,会 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文转载自:https:blog.csdn.netu924512005articledetails70655272详细了解FPGAselectIO是学习FPGA基础 ... [详细]
author-avatar
平凡的如果爱166
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有