Redis常用内存淘汰策略?

淘汰范围来说可以分为不淘汰任何数据、只从设置了到期时间的键中淘汰和从所有键中淘汰三类。而从淘汰算法来分,又主要分为 random(随机),LRU(最近最少使用),以及 LFU(最近最不常使用)三种。

内存总是有限的,因此当 Redis 内存超出最大内存时,就需要根据一定的策略去主动的淘汰一些 key,来腾出内存,这就是内存淘汰策略。我们可以在配置文件中通过 maxmemory-policy 配置指定策略。

与到期删除策略不同,内存淘汰策略主要目的则是为了防止运行时内存超过最大内存,所以尽管最终目的都是清理内存中的一些 key,但是它们的应用场景和触发时机是不同的。

算上在 4.0 添加的两种基于 LFU 算法的策略, Redis 一共提供了八种策略供我们选择:

  • noeviction,不淘汰任何 key,直接报错。它是默认策略**。**
  • volatile-random:从所有设置了到期时间的 key 中,随机淘汰一个 Key。
  • volatile-lru: 从所有设置了到期时间的 key 中,淘汰最近最少使用的 key。
  • volatile-lfu: 从所有设置了到期时间的 key 中,淘汰最近最不常用使用的 key(4.0 新增)。
  • volatile-ttl: 从所有设置了到期时间的 key 中,优先淘汰最早过期的 key。
  • allkeys-random:从所有 key中,随机淘汰一个键(4.0 新增)。
  • allkeys-lru: 从所有 key 中,淘汰最近最少使用的 key。
  • allkeys-lfu: 从所有 key 中,淘汰最近最不常用使用的键。

淘汰范围来说可以分为不淘汰任何数据、只从设置了到期时间的键中淘汰和从所有键中淘汰三类。而从淘汰算法来分,又主要分为 random(随机),LRU(最近最少使用),以及 LFU(最近最不常使用)三种。

其中,关于 LRU 算法,它是一种非常常见的缓存淘汰算法。我们可以简单理解为 Redis 会在每次访问 key 的时候记录访问时间,当淘汰时,优先淘汰最后一次访问距离现在最早的 key。

而对于 LFU 算法,我们可以理解为 Redis 会在访问 key 时,根据两次访问时间的间隔计算并累加访问频率指标,当淘汰时,优先淘汰访问频率指标最低的 key。相比 LRU 算法,它避免了低频率的大批量查询造成的缓存污染问题

顺带一提,只要是有类似缓存机制的应用或多或少都会面对这种问题,比如老生常谈的 MySQL 连表查询,在数据量大的时候也会造成缓存污染。

LRU 的实现

LRU 的全称为 Least Recently Used,也就是最近最少使用。一般来说,LRU 会从一批 key 中淘汰上次访问时间最早的 key。

它是一种非常常见的缓存回收算法,在诸如 Guava CacheCaffeine等缓存库中都提供了类似的实现。我们自己也可以基于 JDK 的 LinkedHashMap 实现支持 LRU 算法的缓存功能。

传统的 LRU 算法实现通常会维护一个链表,当访问过某个节点后就将该节点移至链表头部。如此反复后,链表的节点就会按最近一次访问时间排序。当缓存数量到达上限后,我们直接移除尾节点,即可移除最近最少访问的缓存。

近似 LRU

Redis 中的 LRU 是近似 LRU(NearlyLRU)。当每次访问 key 时,Redis 会在结构体中记录本次访问时间,而当需要淘汰 key 时,将会从全部数据中进行抽样,然后再移除样本中上次访问时间最早的 key。

它的特点是:

  • 仅当需要时再抽样,因而不需要维护全量数据组成的链表,这避免了额外内存消耗。
  • 访问时仅在结构体上记录操作时间,而不需要操作链表节点,这避免了额外的性能消耗。

当然,有利就有弊,这种实现方式也决定 Redis 的 LRU 是并不是百分百准确的,被淘汰的 key 未必真的就是所有 key 中最后一次访问时间最早的。

#a. 抽样大小

根据上述的内容,我们不难理解,当抽样的数量越大,LRU 淘汰 key 就越准确,相对的开销也更大。因此,Redis 允许我们通过 maxmemory-samples 配置采样数量(默认为 5),从而在性能和精度上取得平衡。

#b. 缓存污染

LRU 有个最大问题,就是它只认最近一次访问时间。而如果出现系统偶尔需要一次性读取大量数据的时候,会大规模更新 key 的最近访问时间,从而导致真正需要被频繁访问的 key 因为最近一次访问时间更早而被直接淘汰。这种情况被称为缓存污染

如何选择

软件工程没有银弹,我们不可能指望存在一个能完美适用于所有场景的内存淘汰策略。

在实际场景中,我们需要结合业务特点、数据量大小、数据的冷热……等多个维度来选择合适的淘汰策略。

比如:

  • 当使用 Redis 来缓存用户动态时,由于热门用户的动态相对于普通用户往往会被更高频的访问,因此我们可以选择基于 LRU 或者 LFU 算法的策略保证热点数据不会被轻易淘汰。
  • 当使用 Redis 缓存菜单树时,由于菜单树数据大部分情况下没有明确的热点区分,因此可以考虑使用随机淘汰策略平衡各个数据的访问频率。

当然,调整淘汰策略也只是优化方案的一种。条件允许的话,在特定情况下直接增加内存、将单机改为集群或者缓存预热同样可以带来显著的收益。

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

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

相关文章

Linux--LAMP 平台部署及应用

5.1 LAMP平台概述 LAMP架构是目前成熟的企业网站应用模式之一,指的是协同工作的一整套系统和相关软件,能够提供动态Web站点服务及其应用开发环境。LAMP是一个缩写词,具体包括Linux操作系统,Apache 网站服务器、MySQL数据库服务器&…

【人工智能 | 知识表示】问题规约法 谓词/符号逻辑,良好的知识表示是解题的关键!(笔记总结系列)

🤵‍♂️ 个人主页: AI_magician 📡主页地址: 作者简介:CSDN内容合伙人,全栈领域优质创作者。 👨‍💻景愿:旨在于能和更多的热爱计算机的伙伴一起成长!!&…

c#可变参数(params)关键字

通过使用 params 关键字,可以指定采用可变数量参数的方法参数。 可以发送参数声明中指定类型的参数的逗号分隔列表,也可以发送指定类型的参数数组。您也可以不发送任何参数。如果未发送任何参数,则参数列表的长度为零。 方法声明中的 param…

早上好,我的leetcode(第一期)

写在前面:每天早上到实验室早上昏昏欲睡,那不如写一题吧~ 文章目录 371. 两整数之和面试题08.05.递归乘法29.两数相除50.Pow(x,n)面试题 16.07. 最大数值2119. 反转两次的数字69. x 的平方根70.爬楼梯1631.最小体力消耗路径 371. 两整数之和 两整数之和…

基于ssm轻型卡车零部件销售平台源码和论文

随着信息化时代的到来,管理系统都趋向于智能化、系统化,轻型卡车零部件销售平台也不例外,但目前国内的市场仍都使用人工管理,市场规模越来越大,同时信息量也越来越庞大,人工管理显然已无法应对时代的变化&a…

Caused by: java.net.ConnectException: 拒绝连接: hadoop104/192.168.124.130:4142

项目场景:hadoop102接收消息,自定义拦截器,包含hello的发往hadoop103,不包含的发往hadoop104 报错原因: 原因1: 应该先开启接收方(服务端),hadoop103,hadoop104,最后开启hadoop10…

QDialog子类的使用

背景: 我用Qt designer实现了如下效果: 但在实际使用的时候,发现OK和Cancel按钮点是点不动的。 解决方法: 需要手动添加相关信号槽函数: connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(accept()));connect…

yarn或者pnpm第一次执行的时候遇到报错yarn : 无法加载文件......因为在此系统上禁止运行脚本

报错: yarn : 无法加载文件 C:\Users\rina2\AppData\Roaming\npm\yarn.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/http://go.microsoft.com/fwlink/?LinkID135170 中的 about_Execution_Policies。 解决方案&#xff1a…

AWS-CDN只能备用域名访问-使用Lambda@Edge(禁止分配的域名访问)

场景:cdn使用备用域名后,希望用户只能从备用域名访问,而不是自动分配的cdn域名,这也将是一个安全漏洞,被扫描到cdn域名访问刷流量等! 【建议部署前查看】参考链接: 1.官方cdn返回示例 2.lambdae…

算法训练第三十九天|62. 不同路径、63. 不同路径 II

62. 不同路径: 题目链接 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有…

云服务配置docker镜像容器以及常用操作命令

首先通过ssh进入云服务器。如何ssh进入云服务器。 简单讲解一下docker中镜像和容器,打个比方,镜像相当于印钱的那个模板,容器相当于从模板上拓下来的钱,不同的模板可以印出不同的钱。但容器被修改后也可以变成新的镜像&#xff0…

Postman中参数填写方式

Postman中参数填写和请求方法有关,一般接口用例请求方法GET与POST常用,所以主要是这两种请求方法请求参数填写 一、GET请求方法参数填写 1、直接在URL中填写请求参数,如直接在URL中填写: http://www.example.com:8089/userapi?unamelisi&…

c++_01_名字空间_复合类型_缺省参数_哑元函数

0 前言 C和C一样,都属于编译型语言 C和C一样,都属于强类型语言 C对C完全兼容,并提供更多面向对象的特性:语言风格更加简洁,类型检查更加严格 1 名字空间 namespace WHY?划分更精细的逻辑单元(逻辑空间)&…

Faulhaber 2.5代运动控制系统 25mNm/13W

2.5代控制系统; PWM输出; 四象限控制带; RS232或CANopen通信接口; 2250_BX4_CxD 选件,电缆和连接信息: 适配部件:

谷歌的开源供应链安全

本内容是对Go项目负责人Russ Cox 在 ACM SCORED 活动上演讲内容[1]的摘录与整理。 SCORED 是Software Supply Chain Offensive Research and Ecosystem Defenses的简称, SCORED 23[2]于2023年11月30日在丹麦哥本哈根及远程参会形式举行。 摘要 💡 谷歌在开源软件供应…

【面经】2024年软件测试面试题大全(持续更新)附答案

📢专注于分享软件测试干货内容,欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢交流讨论:欢迎加入我们一起学习!📢资源分享:耗时200小时精选的「软件测试」资…

YOLOv8使用自定义改进后的模型同时《加载官方预训练权重》教程,附代码

YOLOv8自定义改进后的模型同时《加载官方预训练权重》教程,附代码 💡该教程为改进YOLOv8指南,属于《芒果书》📚系列,包含大量的原创改进方式🚀 💡🚀🚀🚀内含改进源代码 按步骤操作运行改进后的代码即可💡更方便的统计更多实验数据,方便写作 YOLOv8自定义…

Spring boot basePackages 通配符* 找不到Bean

Spring boot basePackages 通配符* 找不到Bean 今天遇到了一个关于spring boot 组件ComponentScan 中basePackages 使用通配符* 找不到Bean的问题 目录结构中BussinessPerson与Dog类中都有标注有Component注解,结果扫描不到。 然后删除通配符,结果运行成…

C++相关闲碎记录(15)

1、string字符串 #include <iostream> #include <string> using namespace std;int main (int argc, char** argv) {const string delims(" \t,.;");string line;// for every line read successfullywhile (getline(cin,line)) {string::size_type beg…

ADUM1200ARZ数字隔离器:重新定义技术标准

ADUM1200ARZ数字隔离器成为技术进步领域的关键组件。其创新设计和多方面功能重新定义了数字隔离技术的格局&#xff0c;提供了满足不同工业需求的众多功能。让我们通过本文直观的了解ADUM1200ARZ的功能与技术标准。 窄体且符合ROHS&#xff1a;设定新基准 该数字隔离器采用窄体…