当一个键处于过期的状态,其实在 Redis 中这个内存并不是实时就被从内存中进行摘除,而是 Redis 通过一定的机制去把一些处于过期键进行移除,进而达到内存的释放,那么当一个键处于过期,Redis 会在什么时候去删除?
几时被删除存在三种可能性,这三种可能性也代表了 Redis 的三种不同的删除策略 。
- 定时删除:在设置键过去的时间同时,创建一个定时器,让定时器在键过期时间来临,立即执行对键的删除操作 。
- 惰性删除:放任键过期不管,但是每次从键空间获取键时,都会检查该键是否过期,如果过期的话,就删除该键 。
- 定期删除:每隔一段时间,程序都要对数据库进行一次检查,删除里面的过期键,至于要删除多少过期键,由算法而定 。
设置键的过期时间,创建定时器,一旦过期时间来临,就立即对键进行操作 。
这种对内存是友好的,但是对 CPU 的时间是最不友好的,特别是在业务繁忙,过期键很多的时候,删除过期键这个操作就会占据很大一部分 CPU 的时间 。
要知道 Redis 是单线程操作,在内存不紧张而 CPU 紧张的时候,将 CPU 的时间浪费在与业务无关的删除过期键上面,会对 Redis 的服务器的响应时间和吞吐量造成影响 。
另外,创建一个定时器需要用到 Redis 服务器中的时间事件,而当前时间事件的实现方式是无序链表,时间复杂度为 O(n),让服务器大量创建定时器去实现定时删除策略,会产生较大的性能影响,所以,定时删除并不是一种好的删除策略 。
②惰性删除
与定时删除相反,惰性删除策略对 CPU 来说是最友好的,程序只有在取出键的时候才会进行检查,是一种被动的过程 。
与此同时,惰性删除对内存来说又是最不友好的,一个键过期,只要不再被取出,这个过期键就不会被删除,它占用的内存也不会被释放 。
很明显,惰性删除也不是一个很好的策略,Redis 是非常依赖内存和较好内存的,如果一些长期键长期没有被访问,就会造成大量的内存垃圾,甚至会操成内存的泄漏 。
在对执行数据写入时,通过 expireIfNeeded 函数对写入的 Key 进行过期判断 。
其中 expireIfNeeded 在内部做了三件事情,分别是:
- 查看 Key 是否过期 。
- 向 Slave 节点传播执行过去 Key 的动作 。
- 删除过期 Key 。
上面两种删除策略,无论是定时删除和惰性删除,这两种删除方式在单一的使用上都存在明显的缺陷,要么占用太多 CPU 时间,要么浪费太多内存 。
定期删除策略是前两种策略的一个整合和折中:
- 定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时间和频率来减少删除操作对 CPU 时间的影响 。
- 通过合理的删除执行的时长和频率,来达到合理的删除过期键 。
Redis 可谓博大精深,简单的七连问只是盲人摸象,这次只是摸到了一根象鼻子,还应该顺着鼻子向下摸,下次可能摸到了一只象耳朵 。
只要愿意往下深入去了解去摸索,而不只应用不思考,总有一天会把 Redis 这只大象给摸透了 。
作者:陈于喆,注:部分章节参考和引用黄健宏 《Redis 设计与实现》
简介:十余年的开发和架构经验,国内较早一批微服务开发实施者 。曾任职国内互联网公司网易和唯品会高级研发工程师,后在创业公司担任技术总监/架构师,目前在洋葱集团任职技术研发副总监 。负责技术部门研发体系建设,团建建设,人才培养,推动整个技术架构演进以及升级,带领技术团队构建微服务架构体系、平台架构体系、自动化运维体系 。
陈于喆来源:51CTO技术栈
推荐阅读
- 面试问Redis集群,被虐的不行了
- 光动能是西铁城好还是卡西欧好?我有话要说
- 咖啡入门常识及意式咖啡豆分享
- 前5个基于Redis的Java对象
- 一款免费的Redis桌面客户端:RediNav
- Redis 图形化工具
- 瞬间几千次的重复提交,我用Spring Boot+Redis扛住了
- Redis如何清除过期key? 一篇文章带你走近源码!
- Centos7 搭建LTMP环境PHP、Tengine、Mysql、Supervisord、Redis
- Redis内存分析工具--rdr安装与使用
