Redis系列-Redis过期策略以及内存淘汰机制【6】

news2024/11/24 3:14:18

目录

  • Redis系列-Redis过期策略以及内存淘汰机制【6】
    • redis过期策略
    • 内存淘汰机制
    • 算法
      • LRU算法
      • LFU
    • 其他场景对过期key的处理
    • FAQ
      • 为什么不用定时删除策略?
    • Ref

个人主页: 【⭐️个人主页】
需要您的【💖 点赞+关注】支持 💯


Redis系列-Redis过期策略以及内存淘汰机制【6】

在这里插入图片描述

redis主要是基于内存来进行高性能、高并发的读写操作的。但既然内存是有限的,例如redis就只能使用10G,你写入了20G。这个时候就需要清理掉10G数据,保留10G数据。那应该保留哪些数据,清除哪些数据,为什么有些数据明明过期了,怎么还占用着内存?这都是由redis的过期策略来决定的。

在这里插入图片描述

redis过期策略

​ redis的过期策略就是:定期删除 + 惰性删除

定期删除,指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查是否过期,如果过期就删除。

🅰️ 100ms怎么来的?
在Redis的配置文件redis.conf中有一个属性"hz",默认为10

表示1s执行10次定期删除,即每隔100ms执行一次,可以修改这个配置值。

在这里插入图片描述
🅱️ 随机抽取一些检测,一些是多少?

同样是由redis.conf文件中的maxmemory-samples属性决定的,默认为5。
在这里插入图片描述

在Redis的配置文件redis.conf中有一个属性"hz",默认为10,表示1s执行10次定期删除,即每隔100ms执行一次,可以修改这个配置值。

​ 假设redis里放了10W个key,都设置了过期时间,你每隔几百毫秒就检查全部的key,那redis很有可能就挂了,CPU负载会很高,都消耗在检查过期的key上。注意,这里不是每隔100ms就遍历所有设置过期时间的key,那样就是一场性能灾难。实际上redis是每隔100ms就随机抽取一些key来检查和删除的。

​ 定期删除可能会导致很多过期的key到了时间并没有被删除掉。这个时候就可以用到惰性删除了。

惰性删除 是指在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间并且已经过期了,此时就会删除,不会给你返回任何东西。

​ 但即使是这样,依旧有问题。如果定期删除漏掉了很多过期的key,然后你也没及时去查,也就没走惰性删除。此时依旧有可能大量过期的key堆积在内存里,导致内存耗尽。

​ 这个时候就需要内存淘汰机制了。

内存淘汰机制

redis.conf中有一行配置 ,该配置就是配内存淘汰策略

# maxmemory-policy volatile-lru

redis·内存淘汰机制有以下几个:

  1. noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。这个一般很少用。
  2. allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key,这个是最常用的。
  3. allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。
  4. volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
  5. volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
  6. volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。
  7. allkeys-lfu,淘汰整个键值中最少使用的键值,这也就是我们常说的LRU算法。 【Redis4.0】
  8. volatile-lfu,淘汰所有设置了过期时间的键值中最少使用的键值【Redis4.0】

而在Redis4.0版本中又新增了2种淘汰策略:

allkeys-lfu,淘汰整个键值中最少使用的键值,这也就是我们常说的LRU算法。
volatile-lfu,淘汰所有设置了过期时间的键值中最少使用的键值
通过上面的内存淘汰策略可以看出,以 allkeys- 开头的表示从所有key中进行数据淘汰,而以 volatile- 开头的会从设置了过期时间的key中进行数据淘汰。

算法

  • LRU(Least Recently Used,最近最少使用),根据最近被使用的时间,离当前最远的数据优先被淘汰;
  • LFU(Least Frequently Used,最不经常使用),在一段时间内,缓存数据被使用次数最少的会被淘汰。

LRU算法

​ 上面的内存淘汰机制中,用到的是LRU算法。什么是LRU算法?LRU算法其实就是上面说的最近最少使用策略。

实现LRU算法,大概的思路如下:

1.​ 维护一个有序单链表,越靠近链表尾部的节点是越早之前访问的。当有一个新的数据被访问时,我们从链表头开始顺序遍历链表:
2. 如果此数据之前已经被缓存在链表中了,我们遍历得到这个数据对应的节点,并将其从原来的位置删除,然后再插入到链表的头部。
3. 如果此数据没有在缓存链表中,又可以分为两种情况:
- 如果此时缓存未满,则将此节点直接插入到链表的头部;
- 如果此时缓存已满,则链表尾节点删除,将新的数据节点插入链表的头部。

​ 这就就实现了LRU算法。

​ 当然我们也可以基于Java现有的数据结构LinkedHashMap手撸一个。LinkHashMap本质上是一个Map与双向链表的结合,比起上述的单链表,效率更高。代码如下:

class LRUCache<K, V> extends LinkedHashMap<K, V> {
    private final int CACHE_SIZE;

    /**
     * 传递进来最多能缓存多少数据
     *
     * @param cacheSize 缓存大小
     */
    public LRUCache(int cacheSize) {
        // true 表示让 linkedHashMap 按照访问顺序来进行排序,最近访问的放在头部,最老访问的放在尾部。
        super((int) Math.ceil(cacheSize / 0.75) + 1, 0.75f, true);
        CACHE_SIZE = cacheSize;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        // 当 map中的数据量大于指定的缓存个数的时候,就自动删除最老的数据。
        return size() > CACHE_SIZE;
    }
}

LFU

在Redis LFU算法中,为每个key维护了一个计数器,每次key被访问的时候,计数器增大,计数器越大,则认为访问越频繁。但其实这样会有问题,

1、因为访问频率是动态变化的,前段时间频繁访问的key,之后也可能很少再访问(如微博热搜)。为了解决这个问题,Redis记录了每个key最后一次被访问的时间,随着时间的推移,如果某个key再没有被访问过,计数器的值也会逐渐降低。

2、新生key问题,对于新加入缓存的key,因为还没有被访问过,计数器的值如果为0,就算这个key是热点key,因为计数器值太小,也会被淘汰机制淘汰掉。为了解决这个问题,Redis会为新生key的计数器设置一个初始值。

上面说过在Redis LRU算法中,会给每个key维护一个大小为24bit的属性字段,代表最后一次被访问的时间戳。在LFU中也维护了这个24bit的字段,不过被分成了16 bits与8 bits两部分:

16 bits 8 bits
±-------------------±-----------+

  • Last decr time | LOG_C |

±-------------------±----------+

其中高16 bits用来记录计数器的上次缩减时间,时间戳,单位精确到分钟。低8 bits用来记录计数器的当前数值。

在redis.conf配置文件中还有2个属性可以调整LFU算法的执行参数:lfu-log-factor、lfu-decay-time。其中lfu-log-factor用来调整计数器counter的增长速度,lfu-log-factor越大,counter增长的越慢。lfu-decay-time是一个以分钟为单位的数值,用来调整counter的缩减速度。

其他场景对过期key的处理

1、快照生成RDB文件时

过期的key不会被保存在RDB文件中。

2、服务重启载入RDB文件时

Master载入RDB时,文件中的未过期的键会被正常载入,过期键则会被忽略。Slave 载入RDB 时,文件中的所有键都会被载入,当主从同步时,再和Master保持一致。

3、AOF 文件写入时

因为AOF保存的是执行过的Redis命令,所以如果redis还没有执行del,AOF文件中也不会保存del操作,当过期key被删除时,DEL 命令也会被同步到 AOF 文件中去。

4、重写AOF文件时

执行 BGREWRITEAOF 时 ,过期的key不会被记录到 AOF 文件中。

5、主从同步时

Master 删除 过期 Key 之后,会向所有 Slave 服务器发送一个 DEL命令,Slave 收到通知之后,会删除这些 Key。

Slave 在读取过期键时,不会做判断删除操作,而是继续返回该键对应的值,只有当Master 发送 DEL 通知,Slave才会删除过期键,这是统一、中心化的键删除策略,保证主从服务器的数据一致性。

FAQ

为什么不用定时删除策略?

定时删除,用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。在大并发请求下,CPU要将时间应用在处理请求,而不是删除key,因此没有采用这一策略.

Ref

https://blog.csdn.net/yuanlong122716/article/details/104420880

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1187222.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

js:React中使用classnames实现按照条件将类名连接起来

参考文档 https://www.npmjs.com/package/classnameshttps://github.com/JedWatson/classnames 安装 npm install classnames示例 import classNames from "classnames";// 字符串合并 console.log(classNames("foo", "bar")); // foo bar//…

学之思开源考试系统部署至Centos7

学之思开源考试系统部署至Centos7 1、下载源码 源码下载&#xff1a; https://gitee.com/mindskip/xzs-mysql 数据库脚本下载&#xff1a; https://www.mindskip.net:999/ 2、项目打包 分别在\source\vue\xzs-student目录和source\vue\xzs-admin目录&#xff0c;执行前端打…

Improved Population Control for More Efficient Multimodal Optimizers

多模态优化 NC-VMO means ‘Niche-Clearing-based VMO’&#xff0c;ASD means ‘Adaptive Species Discovery’&#xff0c;HVcMO means ‘Clustering-based Variable Mesh Optimization’ N c A _c^A cA​是A的推荐种群规模&#xff0c;inc means ‘increment’&#xff0c;…

中国芯片产能加速增长,美芯销量下滑,难怪美芯和ASML都低头了

日前分析机构给出的数据指中国的芯片产量呈现加速增长的趋势&#xff0c;伴随的就是芯片进口在下滑&#xff0c;国产芯片的加速替代&#xff0c;已给美国芯片等海外芯片行业造成巨大的打击。 分析机构给出的数据指今年3-6月中国的芯片产能都在稳步增长&#xff0c;不过增长为个…

如何检测小红书账号是否被限流?哪些原因会导致账号被限流?

hi&#xff0c;同学们&#xff0c;本期是第5期AI运营技巧篇&#xff0c;文章底部准备了粉丝福利&#xff0c;看完后可领取&#xff01; 最近好多新手学员运营小红书账号&#xff0c;可能会遇到这样的问题&#xff1a;发布的内容小眼睛少得可怜&#xff1f;搜索不到自己的笔记&…

Qt开发环境搭建

Index of /official_releases/online_installers (qt.io)

Xmake v2.8.5 发布,支持链接排序和单元测试

Xmake 是一个基于 Lua 的轻量级跨平台构建工具。 它非常的轻量&#xff0c;没有任何依赖&#xff0c;因为它内置了 Lua 运行时。 它使用 xmake.lua 维护项目构建&#xff0c;相比 makefile/CMakeLists.txt&#xff0c;配置语法更加简洁直观&#xff0c;对新手非常友好&#x…

(六)库存超卖案例实战——使用mysql分布式锁解决“超卖”问题

前言 本节内容是关于使用分布式锁解决并发访问“超卖”问题的最终篇&#xff0c;在前面的章节中我们介绍了使用mysql的行锁、乐观锁、悲观锁解决并发访问导致的超卖问题&#xff0c;存在的问题是行锁、乐观锁、悲观锁不太灵活&#xff0c;需要和具体的业务耦合到一起&#xff…

盘点几种常用加密算法

文章目录 前言常用算法DES算法DES算法特点DES算法示例 AES算法AES算法特点AES算法示例 RSA算法RSA算法特点RSA算法示例 MD5算法MD5算法特点MD5算法示例 SHA算法SHA算法特点SHA算法示例 总结写在最后 前言 随着互联网的发展,信息安全问题日益受到重视。加密算法在保证信息安全传…

力扣算法-----一刷总结

之前学习算法题坚持不了几天就很容易放弃&#xff0c;一直没怎么系统的练习&#xff0c;偶然发现代码随想录居然推出了算法训练营&#xff0c;趁着时间比较足报了名跟着学习了两个月。 过去的两个月&#xff0c;中间伴着各种琐事&#xff0c;但还是坚持了下来&#xff0c;走过…

网络安全之CSRF漏洞原理和实战,以及CSRF漏洞防护方法

一、引言 总体来说CSRF属于一种欺骗行为&#xff0c;是一种针对网站的恶意利用&#xff0c;尽管听起来像跨站脚本&#xff08;XSS&#xff09;&#xff0c;但是与XSS非常不同&#xff0c;并且攻击方式几乎向佐。XSS利用站点内的信任用户&#xff0c;而CSRF则通过伪装来自受信任…

如何使用ArcGIS Pro制作个性三维地形图

制作三维地图制作的多了&#xff0c;想着能不能换个“口味”&#xff0c;恰好看见制作六边形蜂窝图&#xff0c;灵光一闪&#xff0c;想着将二者结合&#xff0c;将平滑的三维地形图改成柱状图&#xff0c;从结果来看还可以&#xff0c;这里将制作方法分享给大家&#xff0c;希…

基于51单片机太阳能热水器控制系统-proteus仿真-程序

、系统方案 系统设计将软件设计内容分为了六大模块&#xff0c;分别是蜂鸣器报警、水位检测、DS18B20模块、液晶显示、加热模块、按键模块&#xff0c;系统将其进行分别设计&#xff0c;接通电源之后&#xff0c;单片机分别向LCD1602液晶显示器、DS18B20模块、和按键发出初始化…

C【整数正序分解】

// 整数正序分解 #include <stdio.h> #include <stdlib.h>int main() {int x;scanf("%d", &x);// 13425/10000->1(int一个d)// 13425%10000->3425(这是x)// 10000/10-.1000(这是mask)int mask 1;int t x;while (t > 9){t / 10;mask * 10;…

安装dubbo-admin报错node版本和test错误

✅作者简介&#xff1a;CSDN内容合伙人、信息安全专业在校大学生&#x1f3c6; &#x1f525;系列专栏 &#xff1a;dubbo-admin安装 &#x1f4c3;新人博主 &#xff1a;欢迎点赞收藏关注&#xff0c;会回访&#xff01; &#x1f4ac;舞台再大&#xff0c;你不上台&#xff0…

JAVA安全之Log4j-Jndi注入原理以及利用方式

什么是JNDI&#xff1f; JDNI&#xff08;Java Naming and Directory Interface&#xff09;是Java命名和目录接口&#xff0c;它提供了统一的访问命名和目录服务的API。 JDNI主要通过JNDI SPI&#xff08;Service Provider Interface&#xff09;规范来实现&#xff0c;该规…

matlab中实现画函数图像添加坐标轴

大家好&#xff0c;我是带我去滑雪&#xff01; 主函数matlab代码&#xff1a; function PlotAxisAtOrigin(x,y); if nargin 2 plot(x,y);hold on; elsedisplay( Not 2D Data set !) end; Xget(gca,Xtick); Yget(gca,Ytick); XLget(gca,XtickLabel); YLget(gca,YtickLabel)…

csdn初始模板【自用】

这里写自定义目录标题 欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants 创建一个自定义列表如何创建一个…

C++ Qt 学习(五):Qt Web 编程

1. Chrome 技术介绍 大多数 web 技术都是基于 chrome&#xff0c;例如 CEF、QCefView 以及 QWebEngineView&#xff0c;这些都是在 native 界面里用来显示 html 网页&#xff0c;并且可以与 web 交互 例如常见的登录窗口、优酷的视频区域、WPS 的稻壳商城等&#xff0c;这些都…

npm 下载包失败解决方案

1.【问题描述】使用 npm 下载vue项目依赖包时失败&#xff0c;版本不一致。 【解决方法】使用 npm install --force npm install --force 是一个命令行指令&#xff0c;用于在 Node.js 环境中使用 npm&#xff08;Node Package Manager&#xff09;安装包或模块。–force 参数表…