【Redis18】Redis进阶:内存回收策略

news/2024/10/30 13:34:47/

Redis进阶:内存回收策略

今天的内容很偏理论,不过也只是对于官方文档的一个补充而已,所以大家也不必有很大的心理负担。理论的东西,多看几遍就理解了,读书百遍其义自现嘛。即使不理解,当八股文背下来也没啥坏处。

内存过期回收算法

目前市面上,你能听到的过期回收算法基本就是两种,一个叫 LRU 一个叫 LFU 。当然,还有别的算法,不过我也不知道,不知为不知,咱们就先来学习知道的东西。

它们俩都是内存管理的一种页面置换算法。就是说,把没用的内存页转换出来,或者说是淘汰掉。假如说,如果我们没有这样的淘汰机制,那么内存里的数据一直存在,最后的结果是啥?当然就是内存被撑爆了。

一般情况下,我们会为缓存数据设置过期时间,但是,假如所有数据都没有设置过期时间呢?这样的数据一直放着撑爆内存是早晚的事嘛。所以说,我们就需要有一种过期回收的淘汰机制,避免内存无限制的增长最终导致服务完全不可用。

LRU:最近最少使用算法(Least Recently Used),意思就是直接淘汰最长时间没有被使用的内存页。

LFU:最不经常使用算法(Least Frequently Used),淘汰一段时间内的,使用次数最少的内存页。

在 Redis4.0 之前,Redis 只支持 LRU ,同时 LRU 也是 Memcached 的默认算法。但是,LRU 有一个很严重的问题,那就是一个 N 久不被使用的页,突然被使用了一下,它就变成最新的数据了。然后可能又是过 N 久才会使用到一次。而 LFU 则是在一定时间范围内对访问数据进行了限定。因此,如果是热点数据比较多,使用LFU 会更好一些。而热点不那么明显,或者热点数据总量并不多的话,使用 LRU 也是完全没问题的,并且这也是多数缓存系统所推荐的算法。

那么在 Redis 中如何来进行相关的配置呢?我们一个一个来看。

maxmemroy

这个配置之前其实我们也讲过,它是设置当前 Reids 实例最大可用内存限制。比如我们设置成 100MB 的话,那么当前这个实例中就只能存放 100MB 的数据。如果不设置它的话,就会一直向系统申请内存,也就是以整个机器和系统的可用内存为边界的。

通常情况下,我们会单独用一台机器专门部署 Redis ,所以这个值可设可不设。通过 CONFIG 相关的命令也可以进行运行时的配置。比如我本地就没有设置这个值

127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "0"

maxmemory-policy

在之前的文章中,其实我们已经学过这个配置,当时是讲一个 LFU 相关的命令,不知道大家还记得不,文章在这里 Redis基础学习:通用命令(二)https://mp.weixin.qq.com/s/eiMRo_iJv0EjgGCBFTrfLg 。

当时我们是为了演示 OBJECT FREQ 命令查看到 LFU 算法的引用计数情况来修改的这个配置。它的实际意思就是当达到 maxmemory 设置的最大内存之后,使用何种方式进行内存的回收淘汰。具体可设置的值包括下面几种:

  • noeviction: 内存达到限制后,新添加进来的值不会被保存。如果是做了主从的数据库,则对主库适用。

  • allkeys-lru: 保留最近使用的,删除最近最少使用的。(LRU)

  • allkeys-lfu: 保留使用频率高的,删除使用频率低的。(LFU)

  • volatile-lru: 删除在过期集合中的最少使用的。(LRU)

  • volatile-lfu: 删除在过期集合中的使用频率低的。(LFU)

  • allkeys-random: 随机删除,为新添加的数据腾出空间。

  • volatile-random: 随机删除在过期集合中的。

  • volatile-ttl: 删除使用频率最低的,并在过期集合中的,并删除最短生存时间的。

啥叫过期集合?在我们 DEL 一条数据后,这条数据所在的内存页并不是马上就被回收淘汰的。这些数据会进入到一个过期集合中,或者说是相关的 KEY 会被设置为已经过期的。

在 Redis 中,EXPIRE 这类命令能关联到一个有额外内存开销的 KEY 。当 KEY 执行过期操作时,Redis 会确保按照规定时间删除它们。

上面带 volatile 的都是优先去处理这些过期集合中的数据,另外 Reids 也会在后台有一个线程专门去处理已经过期的 KEY ,但是,内存是页的,假设当前的 KEY 所在的页全部都过期了,那么这个内存页就会直接被回收,所以,如果这个内存页中还有其它的数据是没有过期的,那么这个内存页是不会被回收的。因此,如果你发现 Redis 占用的内存大于了设置的 maxmemory 时也不要惊讶。此外,如果所有的 KEY 都没有设置过期时间,那么这些配置和 noeviction 是没啥区别的。

怎么配置?

127.0.0.1:6379> CONFIG GET maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"

默认情况下,maxmemory-policy 走的是 noeviction 这个配置。也就是没有任何算法来处理,就是添加不了新数据了。具体要配置那种,还是要根据业务情况来定。

  • 有热点数据,肯定是 allkeys-lfu ,当然 allkeys-lru 也没问题。数据小,碎片化多,用 allkeys-lfu ,大的文章之类的单个 KEY 的数据比较大,可以考虑 allkeys-lru 。

  • 随机访问,或者循环访问,直接就 allkeys-random 好了。

  • 大部分业务数据都有设置过期时间,那就 volatile-ttl 。

回收的工作过程

对于回收的操作,可以分几步来看:

  • 客户端运行添加命令

  • Redis 检查内存使用情况,如果大于 maxmemory 的限制,则根据 maxmemory-policy 的策略进行淘汰

  • 执行命令

也就是说,当内存到达 maxmemory 的边界时,我们会不断的在这个边界范围内来回跳转,超过它,然后回收后又返回到限制内。如果有某个命令导致大量的内存被使用,那么内存限制就会被明显的超过。

总结

很理论吧?还好内容也不多,一定要好好消化一下哦。在 Redis 中,LRU 和 LFU 也是采用的近似算法,有兴趣的同学可以通过下面的链接去官网进行更深入的研究。

参考文档:

https://redis.io/docs/manual/eviction/


http://www.ppmy.cn/news/62108.html

相关文章

操作系统原理 —— 线程的概念、实现方式、多线程模型(十)

什么是线程,为什么要引入线程? 有的进程可能需要 “同时” 做很多事情,而传统的进程只能串行的执行一系列的程序,为此,引入了 “线程” ,来增加并发度。 可以把线程理解为 轻量级进程,线程是可…

什么是分布式事务

目录 分布式事务基础 事务 本地事务 分布式事务 分布式事务的场景 分布式事务解决方案 全局事务 优点 缺点 可靠消息服务 第一步 :消息由系统A投递到中间件 超时访问机制 最大努力通知 第一步:消息由系统A投递到中间件 第二步:消息…

ruby环境中的irb

IRB代表Interactive Ruby,它是 Ruby 解释器的一个交互性组件,用于编写 Ruby 代码并动态地执行这些代码进行测试和调试。IRB提供了一个命令行界面,让用户能够输入 Ruby 代码和表达式,获得相应的输出,以及与 Ruby 代码进…

用Jmeter进行接口自动化测试的工作流程你知道吗?

目录 测试流程 接口测试相关文档管理规范 接口测试要点 测试流程 在测试负责人接受到测试任务后,应该按照以下流程规范完成测试工作。 2.1 测试需求分析 产品开发负责人在完成某产品功能的接口文档编写后,在核对无误后下发给对应的接口测试负责人…

全景丨0基础学习VR全景制作,平台篇第16章:热点功能-图片

大家好,欢迎观看蛙色VR官方——后台使用系列课程! 功能说明 应用场景 热点,指在全景作品中添加各种类型图标的按钮,引导用户通过按钮产生更多的交互,增加用户的多元化体验。 图片热点,即点击热点后弹出单张…

Qt5.9学习笔记-事件(二) 自定义事件

⭐️我叫忆_恒心,一名喜欢书写博客的在读研究生👨‍🎓。 如果觉得本文能帮到您,麻烦点个赞👍呗! 近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧,喜欢的小伙伴给个三…

python 进程间通信 Queue()、Pipe()、manager.list()、manager.dict()、manager.Queue()

👨‍💻个人简介: 深度学习图像领域工作者 🎉总结链接: 链接中主要是个人工作的总结,每个链接都是一些常用demo,代码直接复制运行即可。包括: &am…

苹果备忘录误删了怎么恢复?恢复备忘录的3个方法!

案例:苹果删除的备忘录怎么恢复? 【友友们,苹果备忘录删除的备忘录在哪里可以恢复?有什么方法吗?】 苹果备忘录是日常生活中经常使用的一种记录方式,它可以帮助我们记录生活琐事、工作事项以及其他需要记录…