Redis缓存过期淘汰策略

news2024/11/16 21:21:56

文章目录

  • 1、如何设置 Redis 最大运行内存?
  • 2、过期删除策略
  • 3、内存淘汰策略

1、如何设置 Redis 最大运行内存?

在配置文件 redis.conf 中,可以通过参数 maxmemory 来设定最大运行内存,只有在 Redis 的运行内存达到了我们设置的最大运行内存,才会触发内存淘汰策略。

在这里插入图片描述
不同位数的操作系统,maxmemory 的默认值是不同的:

  • 在 64 位操作系统中,maxmemory 的默认值是 0,表示没有内存大小限制,那么不管用户存放多少数据到 Redis 中,Redis 也不会对可用内存进行检查,直到 Redis 实例因内存不足而崩溃也无作为。
  • 在 32 位操作系统中,maxmemory 的默认值是 3G,因为 32 位的机器最大只支持 4GB 的内存,而系统本身就需要一定的内存资源来支持运行,所以 32 位操作系统限制最大 3 GB 的可用内存是非常合理的,这样可以避免因为内存不足而导致 Redis 实例崩溃

生产上一般推荐Redis设置为内存为最大物理内存的四分之三

除了在配置文件中设置之外,还可以通过命令修改

config set maxmemory 10000   #表示设置内存大小我10000字节

可以使用以下命令来查看redis内存使用情况

config get maxmemory
info memory

如果Redis内存使用超出了设置的最大值会怎么样?
在这里插入图片描述
超过内存大小限制,直接不允许再进行插入操作

2、过期删除策略

常见的有三种过期删除策略:

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

优点:

可以保证过期 key 会被尽快删除,也就是内存可以被尽快地释放。因此,定时删除对内存是最友好的

缺点:

在过期 key 比较多的情况下,删除过期 key 可能会占用相当一部分 CPU 时间,在内存不紧张但 CPU 时间紧张的情况下,将 CPU 时间用于删除和当前任务无关的过期键上,无疑会对服务器的响应时间和吞吐量造成影响。所以,立即删除策略对 CPU 不友好,对内存很友好,用性能换取存储空间

惰性删除
不主动删除过期键,每次从数据库访问 key 时,都检测 key 是否过期,如果过期则删除该 key。

优点:

因为每次访问时,才会检查 key 是否过期,所以此策略只会使用很少的系统资源,因此,惰性删除策略对 CPU 时间最友好,对内存不太友好

缺点:

如果一个 key 已经过期,而这个 key 又仍然保留在数据库中,那么只要这个过期 key 一直没有被访问,它所占用的内存就不会释放,造成了一定的内存空间浪费,甚至可以将其看成内存泄漏。所以,惰性删除策略对内存不友好。

如果需要开启惰性淘汰,就在配置文件中进行相应的修改

lazyfree-lazy-eviction=yes

定期删除

每隔一段时间「随机」从数据库中取出一定数量的 key 进行检查,并删除其中的过期key。

优点:

通过限制删除操作执行的时长和频率,来减少删除操作对 CPU 的影响,同时也能删除一部分过期的数据减少了过期键对空间的无效占用。

缺点:

内存清理方面没有定时删除效果好,同时没有惰性删除使用的系统资源少。
难以确定删除操作执行的时长和频率。如果执行的太频繁,定期删除策略变得和立即删除策略一样,对CPU不友好;如果执行的太少,那又和惰性删除一样了,过期 key 占用的内存不会及时得到释放。

3、内存淘汰策略

Redis 内存淘汰策略共有八种,这八种策略大体分为「不进行数据淘汰」和「进行数据淘汰」两类策略。

(1)不进行数据淘汰的策略

noeviction(默认的内存淘汰策略) :它表示当运行内存超过最大设置内存时,不淘汰任何数据,这时如果有新的数据写入,则会触发 OOM,但是如果没用数据写入的话,只是单纯的查询或者删除操作的话,还是可以正常工作。

(2)进行数据淘汰的策略

针对「进行数据淘汰」这一类策略,又可以细分为「在设置了过期时间的数据中进行淘汰」和「在所有数据范围内进行淘汰」这两类策略。

在设置了过期时间的数据中进行淘汰:

volatile-random:随机淘汰设置了过期时间的任意键值;
volatile-ttl:优先淘汰更早过期的键值。
volatile-lru:淘汰所有设置了过期时间的键值中,最久未使用的键值;
volatile-lfu:淘汰所有设置了过期时间的键值中,最少使用的键值;

在所有数据范围内进行淘汰:

allkeys-random:随机淘汰任意键值;
allkeys-lru:淘汰整个键值中最久未使用的键值;
allkeys-lfu:淘汰整个键值中最少使用的键值。

如何查看当前 Redis 使用的内存淘汰策略?
可以使用 config get maxmemory-policy 命令,来查看当前 Redis 的内存淘汰策略

在这里插入图片描述

什么是 LRU 算法?
LRU 全称是 Least Recently Used 翻译为最近最少使用,会选择淘汰最近最少使用的数据。

传统 LRU 算法的实现是基于「链表」结构,链表中的元素按照操作顺序从前往后排列,最新操作的键会被移动到表头,当需要内存淘汰时,只需要删除链表尾部的元素即可,因为链表尾部的元素就代表最久未被使用的元素。

Redis 并没有使用这样的方式实现 LRU 算法,因为传统的 LRU 算法存在两个问题:

需要用链表管理所有的缓存数据,这会带来额外的空间开销;
当有数据被访问时,需要在链表上把该数据移动到头端,如果有大量数据被访问,就会带来很多链表移动操作,会很耗时,进而会降低 Redis 缓存性能。

Redis 是如何实现 LRU 算法的?

Redis 实现的是一种近似 LRU 算法,目的是为了更好的节约内存,它的实现方式是在 Redis 的对象结构体中添加一个额外的字段,用于记录此数据的最后一次访问时间。

当 Redis 进行内存淘汰时,会使用随机采样的方式来淘汰数据,它是随机取 5 个值(此值可配置),然后淘汰最久没有使用的那个。

Redis 实现的 LRU 算法的优点:

不用为所有的数据维护一个大链表,节省了空间占用;
不用在每次数据访问时都移动链表项,提升了缓存的性能;
但是 LRU 算法有一个问题,无法解决缓存污染问题,比如应用一次读取了大量的数据,而这些数据只会被读取这一次,那么这些数据会留存在 Redis 缓存中很长一段时间,造成缓存污染。

因此,在 Redis 4.0 之后引入了 LFU 算法来解决这个问题。

什么是 LFU 算法?

LFU 全称是 Least Frequently Used 翻译为最近最不常用,LFU 算法是根据数据访问次数来淘汰数据的,它的核心思想是“如果数据过去被访问多次,那么将来被访问的频率也更高”。

所以, LFU 算法会记录每个数据的访问次数。当一个数据被再次访问时,就会增加该数据的访问次数。这样就解决了偶尔被访问一次之后,数据留存在缓存中很长一段时间的问题,相比于 LRU 算法也更合理一些。

Redis 是如何实现 LFU 算法的?

LFU 算法相比于 LRU 算法的实现,多记录了「数据的访问频次」的信息。Redis 对象的结构如下:

typedef struct redisObject {
    ...
    // 24 bits,用于记录对象的访问信息
    unsigned lru:24;  
    ...
} robj;

Redis 对象头中的 lru 字段,在 LRU 算法下和 LFU 算法下使用方式并不相同。

在 LRU 算法中,Redis 对象头的 24 bits 的 lru 字段是用来记录 key 的访问时间戳,因此在 LRU 模式下,Redis可以根据对象头中的 lru 字段记录的值,来比较最后一次 key 的访问时间长,从而淘汰最久未被使用的 key。

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

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

相关文章

代码命名规范

日常编码中,代码的命名是个大的学问。能快速的看懂开源软件的代码结构和意图,也是一项必备的能力。那它们有什么规律呢? Java项目的代码结构,能够体现它的设计理念。Java采用长命名的方式来规范类的命名,能够自己表达…

消息称苹果Type-C口充电未设MFi限制,iOS17将更新Find My服务

根据国外科技媒体 iMore 报道,基于消息源 analyst941 透露的信息,苹果公司目前并未开发 MFi 限制。 根据推文信息内容,两款 iPhone 15 机型的最高充电功率为 20W,而 iPhone 15 Pro 机型的最高支持 27W 充电。 此前古尔曼表示苹…

Python趋势外推预测模型实验完整版

趋势外推预测模型实验完整版 实验目的 通过趋势外推预测模型(佩尔预测模型),掌握预测模型的建立和应用方法,了解趋势外推预测模型(佩尔预测模型)的基本原理 实验内容 趋势外推预测模型 实验步骤和过程…

第4章-虚拟机栈(多使用到jclasslib工具查看字节码)

虚拟机栈 简介 虚拟机栈的出现背景 由于跨平台性的设计,Java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的【如果设计成基于寄存器的,耦合度高,性能会有所提升,因为可以对具体的CPU架…

警惕免杀版Gh0st木马!

https://github.com/SecurityNo1/Gh0st2023 经过调查发现,这款开源的高度免杀版Gh0st木马目前正在大范围传播,据称可免杀多种主流杀软:开发者不仅制作了新颖的下载页面,还设法增加了搜索引擎的收录权重,吸引了许多免…

Python基础合集 练习17(类与对象)

class Dog: pass papiDog() print(papi) print(type(papi)) 构建方法 创建类过后可以定义一个特殊的方法。在python中构建方法是__init__(),init()必须包含一个self参数 class pig(): #def__init__(self) -> None: print(‘你好’) pipgpig() 属性和方法 cl…

JDBC详解(六):数据库事务(超详解)

JDBC详解(六):数据库事务(超详解) 前言一、数据库事务介绍二、JDBC事务处理三、事务的ACID属性1、数据库的并发问题2、四种隔离级别3、在MySql中设置隔离级别 前言 本博主将用CSDN记录软件开发求学之路上亲身所得与所…

MySQL基础——数据模型·数据库操作

♥️作者:小刘在C站 ♥️个人主页:小刘主页 ♥️每天分享云计算网络运维课堂笔记,努力不一定有收获,但一定会有收获加油!一起努力,共赴美好人生! ♥️树高千尺,落叶归根人生不易&…

开放原子训练营(第一季)铜锁探密:基于铜锁,在前端对登录密码进行加密,实现隐私数据保密性

本文将基于 铜锁(tongsuo)开源基础密码库实现前端对用户登录密码的加密,从而实现前端隐私数据的保密性。 首先,铜锁密码库是一个提供现代密码学算法和安全通信协议的开源基础密码库,在中国商用密码算法,例…

vcruntime140_1.dll无法继续执行代码怎么修复

vcruntime140_1.dll 是 Microsoft Visual C 程序集中的一个动态链接库文件。该文件提供了一些 C 运行时函数,这些函数是由许多应用程序使用的。当一个程序需要某个 DLL 文件时,它会首先在系统目录和程序所在目录中查找该 DLL 文件。如果系统或程序目录中…

《密码法》

第一章 总 则 第一条 为了规范密码应用和管理,促进密码事业发展,保障网络与信息安全,维护国家安全和社会公共利益,保护公民、法人和其他组织的合法权益,制定本法。 第二条 本法所称密码,是指采用特定变…

JavaSE基础(三)—— 程序流程控制、Random随机数

目录 一、顺序结构 二、分支结构 1. if 1.1 if分支有三种格式​编辑 2. switch 2.1 if、switch分支各自适合做什么业务场景 3. switch的穿透性 三、循环结构 1. for 循环​编辑 2. while 循环 2.1 什么时候用for循环,什么时候用while循环 3. do-while循…

探索抖音全域兴趣电商的特点与优势

抖音全域兴趣电商是抖音在电商领域的一项创新业务。它是一种全新的购物方式,通过抖音平台提供的社交化购物体验,将用户的兴趣、购物需求和商品展示相结合,为用户提供更为个性化、精准的购物体验。下面四川不若与众将对抖音全域兴趣电商进行一…

uboot start_armboot函数 第二阶段代码分析

1.1、start_armboot函数简介 这个函数整个构成了uboot启动的第二阶段。 1.2、uboot第二阶段做的事情 uboot第一阶段主要就是初始化了SoC内部的一些部件(譬如看门狗、时钟、串口…),然后初始化DDR并且完成重定位。那么,uboot的第…

Win10配置ESP32-IDF+VSCode开发环境

一、安装包下载: Git:Git for WindowsPython:Download Python | Python.org以Windows x86-64开头的是 64 位的 Python 安装程序;以Windows x86开头的是 32 位的 Python 安装程序。ESP-IDF(选择Offline版本&#xff09…

【微机原理】8088/8086的寻址方式

目录 一.指令的组成 二.操作数的寻址方式 1.立即数寻址 2.寄存器寻址方式 3.存储器寻址方式 (1)直接寻址 (2)寄存器间接寻址 (3)寄存器相对寻址方式 (4)基址变址寻址方式&#xff08…

基于zookeeper实现分布式锁

目录 zookeeper知识点复习 相关概念 java客户端操作 实现思路分析 基本实现 初始化链接 代码落地 优化:性能优化 实现阻塞锁 监听实现阻塞锁 优化:可重入锁 zk分布式锁小结 zookeeper知识点复习 Zookeeper(业界简称zk&#xff…

【Linux】多路转接--select、poll、epoll,非阻塞等待

1.IO的概念 IO等拷贝数据 等&#xff1a;发送缓冲区满了或者接受缓冲区没有数据&#xff0c;就需要等待 高效IO就是&#xff1a;减少单位时间内,"等"的比重 2. 阻塞IO和非阻塞IO 2.1.阻塞IO 阻塞等待会在read的地方等待 #include <iostream> #include &l…

JavaScript实现输入数字,输出是几月份的代码

以下为实现输入数字&#xff0c;输出是几月份的代码和运行截图 目录 前言 一、实现输入数字&#xff0c;输出是几月份的 1.1 运行流程及思想 1.2 代码段 1.3 JavaScript语句代码 1.4 运行截图 前言 1.若有选择&#xff0c;您可以在目录里进行快速查找&#xff1b; 2.本…

1699_simulink代码生成配置初级方案

全部学习汇总&#xff1a; GreyZhang/g_matlab: MATLAB once used to be my daily tool. After many years when I go back and read my old learning notes I felt maybe I still need it in the future. So, start this repo to keep some of my old learning notes servral …