【征服redis6】Redis的内存淘汰详解

目录

1.redis的基本策略

2.Redis中的缓存淘汰策略

 3.Redis内存不足的情况

 4.几种淘汰策略的实现原理

5.项目实践与优化策略

5.1 配置案例

5.2 项目优化策略参考


数据库存储会将数据保存到磁盘中,而Redis的核心数据是在内存中的,而Redis本身主要用来做缓存,当 Redis 的内存达到最大限制时,会发生什么情况?redis 会怎么处理呢?

Redis性能很高,官方给的数据 读:110000次/s,写 81000次/s。但是长期使用,Key会不断增加,Redis作为缓存使用,物理内存也会满,内存与硬盘交换(swap)虚拟内存也会被占满,频繁的IO操作会导致性能急剧下降。

在使用Redis时,我们一般会为Redis的缓存空间设置一个大小,不会让数据无限制地放入Redis缓存中。可以使用下面命令来设定缓存的大小,比如设置为4GB:

既然 Redis 设置了缓存的容量大小,那缓存被写满就是不可避免的。当缓存被写满时,我们需要考虑下面两个问题:决定淘汰哪些数据,如何处理那些被淘汰的数据?

进而, 我们可以提出几个连环炮问题:

第一问:如果不处理,让redis的内存达到最大,会出现什么情况

第二问:如果必须淘汰掉一些过期数据,该淘汰谁?

第三问:一种淘汰策略够吗?还有哪些常见的策略?不同策略分别适合什么类型的业务?

第四问:淘汰策略该如何配置?是否会对系统性能产生影响?

事实上,面试也经常是这样,从简单问题开始,用连环炮的方式不断递递进,直到我们的知识盲区。

1.redis的基本策略

redis的过期策略可以概括为两种情况:定期删除 + 惰性删除

定期删除:redis默认每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果有过期就删除。注意这里是随机抽取的。为什么要随机呢?你想一想假如 redis 存了几十万个 key ,每隔100ms就遍历所有的设置过期时间的 key 的话,就会给 CPU 带来很大的负载。

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

惰性删除:定期删除可能导致很多过期的key 到了时间并没有被删除掉。这时就要使用到惰性删除。在你获取某个key的时候,redis会检查一下,这个key如果设置了过期时间并且过期了,是的话就删除。

定期删除 + 惰性删除存在的问题。如果某个key过期后,定期删除没删除成功,然后也没再次去请求key,也就是说惰性删除也没生效。这时,如果大量过期的key堆积在内存中,redis的内存会越来越高,导致redis的内存块耗尽。那么就应该采用内存淘汰机制。

2.Redis中的缓存淘汰策略

介绍缓存策略之前,我们先看几种常见的通用缓存处理算法:

1.最近最少使用(Least Recently Used, LRU):LRU 策略会根据键的最近使用时间来判断其热度。当内存空间不足时,会优先淘汰最久未使用的键,即最近最少被使用的键。

2.先进先出(First In, First Out, FIFO):FIFO 策略按照键的插入顺序来决定淘汰顺序。最先插入的键会被最先淘汰。

3.最少使用(Least Frequently Used, LFU):LFU 策略根据键被访问的频率来决定淘汰顺序。访问次数较少的键会被优先淘汰。

4.随机(Random):随机策略会随机选择要淘汰的键。

Redis提供了8种缓存淘汰策略,如下:

1、noeviction:不进行淘汰数据。一旦缓存被写满,再有写请求进来,Redis就不再提供服务,而是直接返回错误。Redis 用作缓存时,实际的数据集通常都是大于缓存容量的,总会有新的数据要写入缓存,这个策略本身不淘汰数据,也就不会腾出新的缓存空间,我们不把它用在 Redis 缓存中。
2、volatile-ttl:在设置了过期时间的键值对中,移除即将过期的键值对。
3、volatile-random:在设置了过期时间的键值对中,随机移除某个键值对。
4、volatile-lru:在设置了过期时间的键值对中,移除最近最少使用的键值对。
5、volatile-lfu:在设置了过期时间的键值对中,移除最近最不频繁使用的键值对
6、allkeys-random:在所有键值对中,随机移除某个key。
7、allkeys-lru:在所有的键值对中,移除最近最少使用的键值对。
8、allkeys-lfu:在所有的键值对中,移除最近最不频繁使用的键值对。

虽然看起来很多,但其实很简单。:

  1. noeviction就是不淘汰。
  2. volatile打头的就是从设置了过期时间的元素中移除一些 ,相对应的allkeys就是从全部键中选择。很明显前者速度快,但是不彻底,后者正好相反。
  3. 以lru为后缀的就是使用最近最少使用的策略,以lfu就是最近最不频繁的策略,random就是随机选。

通常情况下推荐优先使用 allkeys-lru 策略。这样可以充分利用 LRU 这一经典缓存算法的优势,把最近最常访问的数据留在缓存中,提升应用的访问性能。 如果你的业务数据中有明显的冷热数据区分,建议使用 allkeys-lru 策略。 如果业务应用中的数据访问频率相差不大,没有明显的冷热数据区分,建议使用 allkeys-random 策略,随机选择淘汰的数据就行。 如果没有设置过期时间的键值对,那么 volatile-lru,volatile-lfu,volatile-random 和 volatile-ttl 策略的行为, 和 noeviction 基本上一致。但是一般来说,allkeys-lruvolatile-lru是使用最广泛的策略。

 3.Redis内存不足的情况

Redis故障,个人经验不是很多,这里通过查阅整理了几种常见的redis内存不足的提示信息和原因解释,我们一起来看一下:

错误信息解释
OOM command not allowed when used memory Redis 的内存已经耗尽,无法执行当前命令。
Redis out of memoryRedis 已经耗尽了可用的内存,无法继续存储更多的数据。如果内存不足时,读数据也可能失败。
Max number of clients reached Redis 已经达到最大连接数限制,无法接受更多的客户端连接。
命令执行缓慢当 Redis 的内存接近饱和状态时,性能可能会下降。由于 Redis 需要进行内存淘汰操作来释放空间,这可能会导致命令执行的延迟增加。
内存淘汰,命中率下降为了腾出内存空间,Redis 会根据配置的内存淘汰策略清除一些键。这可能导致一些数据被删除,从而影响应用程序的行为,例如缓存命中率下降等。
连接失败当 Redis 内存不足以处理更多的客户端连接时,新的连接请求可能会被拒绝或延迟处理。这可能导致连接失败或长时间等待。

 4.几种淘汰策略的实现原理

在Redis的设计中,内存淘汰的实现原理与其数据结构和管理机制紧密关联,不同的内存淘汰策略有不同的实现方式。 一般来说,volatile-*策略适合大部分键值对都设置了过期时间的场景,而*lru策略则适合数据的重要性随时间逐渐降低的场景。当然,这些策略都不是定死的,可能需要根据实际情况进行调整和优化。

首先,当我们开启Redis的maxmemory策略并设置了相应的内存上限后,Redis就会在达到这个上限时触发数据淘汰操作。这个操作是如何进行的呢?它主要依赖于Redis的内存淘汰策略。

我们以allkeys-lru策略为例,这个策略的原理是什么呢?

LRU代表Least Recently Used,即最近最少使用。Redis为每个存储在内存中的key都维护了一个LRU标识,这个标识用于记录该key最后一次被访问的时间。当Redis需要淘汰数据时,它会从所有的key中挑选一部分key,检查它们的LRU标识,然后淘汰其中最少被访问的key。

这就好比我们收拾房间,当空间不足时,我们会选择几乎不用的东西进行淘汰,以便腾出空间。

同理,volatile-lru策略也是基于LRU原理,只不过它只会考虑那些设置了过期时间的key。

allkeys-random和volatile-random策略则是在所有key或者设置了过期时间的key中随机选择一个进行淘汰,就像是“闭眼摸象”。

volatile-ttl策略则是在设置了过期时间的key中找出生存时间(TTL)最短的进行淘汰,也就是“谁生命短,谁先走”。

我们再次描述一下每种策略的淘汰方式:

  1. volatile-ttl策略则是在设置了过期时间的key中找出生存时间(TTL)最短的进行淘汰,也就是“谁生命短,谁先走”。
  2. noeviction:实现原理十分简单,就是当内存达到上限时,对于所有的写操作都返回错误。
  3. allkeys-lru:它的实现基于Redis的数据结构和LRU(Least Recently Used,最近最少使用)策略。在Redis中,每个键值对都有一个LRU字段,表示这个键值对上一次被访问的时间。当内存达到上限时,Redis会观察一部分键值对的LRU字段,选择其中LRU值最小(即最久未被访问)的键值对进行淘汰。
  4. volatile-lru:与allkeys-lru类似,只不过它只对设置了过期时间的键值对进行观察和淘汰。
  5. allkeys-random:每当需要淘汰数据时,Redis随机选取一部分键值对,然后从中随机淘汰一个。这种方式的优点是简单且开销较小,缺点是淘汰的数据可能是重要的数据。
  6. volatile-random:与allkeys-random类似,只是它只对设置了过期时间的键值对进行随机淘汰。
  7. volatile-ttl:这个策略的实现也依赖Redis的数据结构。每个设置了过期时间的键值对都有一个ttl(time to live,生存时间)字段。当内存达到上限时,Redis会观察一部分设置了过期时间的键值对的ttl字段,选择其中ttl值最小(即最快过期)的键值对进行淘汰。

Redis中的LRU算法并没有严格按照常规的LRU算法的方式实现,而是基于LRU算法的思想做了自己的优化。我们知道,实现LRU算法时,需要将所有的数据按照访问时间距离当前时间的长短排序放到一个双向链表中,基于这个链表实现数据的淘汰。但Redis中存储的数据量是非常庞大的,如果要基于常规的LRU算法,就需要把所有的key全部放到这个双向链表中,这样就会导致这个链表非常非常大,不止需要提供更多的内存来存放这个链表结构,而且操作这么庞大的链表的性能也是比较差的。

所以,Redis中的LRU算法是这样实现的:首先定义一个淘汰池,这个淘汰池是一个数组(大小为16),然后触发淘汰时会根据配置的淘汰策略,先从符合条件的key中随机采样选出5(可在配置文件中配置)个key,然后将这5个key按照空闲时间排序后放到淘汰池中,每次采样之后更新这个淘汰池,让这个淘汰池里保留的总是那些随机采样出的key中空闲时间最长的那部分key。需要删除key时,只需将淘汰池中空闲时间最长的key删掉即可。

为了方便理解它的思想放上一张图:原始地址
 

5.项目实践与优化策略

5.1 配置案例

当你配置 Redis 的淘汰策略时,你可以通过编辑 Redis 配置文件来实现。
。可以根据需要将 maxmemory-policy 设置为你选择的淘汰策略,例如 allkeys-lru、volatile-lfu 等。同时,你还可以使用 maxmemory 配置项来设置 Redis 的最大内存限制。rdbcompression 用于启用在内存中存储数据时的压缩,它减少了数据占用的内存空间。其次,rdbcompression 用于在进行 RDB 快照持久化时启用压缩,以减小生成的 RDB 文件的大小。

# 当达到最大内存限制时,Redis 的淘汰策略
# 可选值:noeviction(禁止淘汰), allkeys-lru(LRU算法), allkeys-lfu(LFU算法), allkeys-random(随机淘汰),
#        volatile-lru(LRU算法,仅针对设置了过期时间的键), volatile-lfu(LFU算法,仅针对设置了过期时间的键),
#        volatile-random(随机淘汰,仅针对设置了过期时间的键)
# 默认值:noeviction
maxmemory-policy noeviction# Redis 的最大内存限制(以字节为单位)。
# 当达到最大内存限制时,Redis 将根据淘汰策略进行键的淘汰。
# 默认值:0(无限制)
maxmemory 102400# 启用压缩存储
# 开启压缩存储可以减少存储数据所占用的内存空间,但会增加 CPU 负载。
# 默认值:no
rdbcompression yes# 保存 RDB 文件时启用压缩
# 当进行 RDB 快照持久化时,启用压缩可以减少 RDB 文件的大小。
# 默认值:no
rdbcompression yes

5.2 项目优化策略参考

在项目中,我们可以参考如下原则来优化:

定时删除(TTL):可以为 Redis 中的键设置过期时间(Time To Live,TTL),让键在一定时间后自动过期并被删除。这样可以确保过期的键及时被清除,释放内存空间。

延迟删除(Lazy Expire):延迟删除是一种优化手段,当键过期时并不立即删除,而是在访问该键时才进行删除操作。这可以减少删除操作的开销,并在实际需要时进行键的清除。

内存碎片整理(Memory Defragmentation):在 Redis 中,当删除一些键后,可能会导致内存出现碎片化。这些碎片化的内存空间无法被有效利用。内存碎片整理是一种优化手段,通过重新分配内存来整理碎片化的内存空间,以提高内存的利用率。

压缩存储(Memory Compression):Redis 4.0 版本引入了内存压缩(Memory Compression)功能,使用 LRU 算法对键进行压缩,以减少内存使用。压缩存储可以在某些场景下显著降低内存占用。

内存分配器优化:Redis 使用的内存分配器可以影响其性能和内存管理。选择适合的内存分配器,如 jemalloc,可以提高 Redis 的性能和内存利用率。
 

redis缓存在使用的时候还会存在很多问题,其中最常见的,也是面试经常考的就是:击穿, 穿透, 雪崩, 污染四个问题。这几个概念是什么意思 ,以及如何解决在这里有比较好的解释了,我们就不细说了。

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

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

相关文章

安全狗方案入选工信部《2023年工业和信息化领域数据安全典型案例名单》

近日,工业和信息化部网络安全管理局公布了2023年工业和信息化领域数据安全典型案例名单。 安全狗与厦门卫星定位应用股份有限公司、中移 (上海) 信息通信科技有限公司联合申报的智慧交通云数据安全与隐私保障典型案例也成功入选。 厦门服云信息科技有限公司&#…

Vue-24、Vue过滤器

1、效果 2、过滤器实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>过滤器</title><script type"text/javascript" src"https://cdn.jsdelivr.net/npm/vue2/dist/vue.…

OpenCV-Python(45):立体图像中的深度地图

基础 在OpenCV中&#xff0c;深度地图通常是通过计算立体视觉&#xff08;stereo vision&#xff09;或结构光&#xff08;structured light&#xff09;技术得到的。立体视觉是通过将两个或多个摄像机&#xff08;或图像&#xff09;的视角结合起来&#xff0c;计算物体的深度…

Kafka 的架构

实验过程 1.三个虚拟机中解压kafka软件包 tar -zxvf kafka_2.11-1.1.1.tgz 2.修改 3 个节点配置文件 在 zookeeper 节点&#xff0c;进入 kafka_2.11-1.1.1/config 目录下&#xff0c;编辑 server.properties 文件 [rootdb1 ~]# cd kafka_2.11-1.1.1/config [rootdb1 con…

智能路由器 端口映射 (UPnP) Padavan内网端口映射配置方法

新版本Padavan 4.4内核的端口映射配置和老版本的不太一样,因为新版本默认是启用的 UPnP端口映射, 同时默认使用的是 IGD UPnP自动端口映射, UPnP名词解释: UPnP通用即插即用&#xff0c;是一组协议的统称&#xff0c;是一种基于TCP/IP、UDP和HTTP的分布式、开放体系&#xff…

P9847 [ICPC2021 Nanjing R] Crystalfly 题解 (SPJ)

[ICPC2021 Nanjing R] Crystalfly 传送门&#xff1f; 题面翻译 给定一个 n ( 1 ≤ n ≤ 1 0 5 ) n(1\le n\le10^5) n(1≤n≤105) 个节点的树&#xff0c;每个节点上有 a i a_i ai​ 只晶蝶。派蒙最初在 1 1 1 号节点&#xff0c;并获得 1 1 1 号节点的所有晶蝶&#xf…

NetSuite学习笔记 - 中心

一、什么是中心&#xff1f; 对于每个用户&#xff0c;NetSuite 会根据用户的指定角色显示一组可变的标签页面&#xff0c;称为中心。通俗来讲呢&#xff0c;NetSuite的中心其实就是我们常说的“导航菜单”。 只是在我过去常见的系统中&#xff0c;导航菜单一般都是固定的&am…

Elasticsearch Windows部署-ELK技术栈

1、下载Elasticsearch、kibana、logstash 本文不介绍ELK相关原理知识&#xff0c;只记录部署操作过程 下载地址Past Releases of Elastic Stack Software | Elastic 选择同一版本&#xff0c;这里选择是当前最新版本8.11.3 解压放在同目录下&#xff0c;方便后续操作与使用 …

浅入浅出Spring架构设计

浅入浅出Spring架构设计 前言 为什么需要Spring? 什么是Spring? 对于这样的问题&#xff0c;大部分人都是处于一种朦朦胧胧的状态&#xff0c;说的出来&#xff0c;但又不是完全说的出来&#xff0c;今天我们就以架构设计的角度尝试解开Spring的神秘面纱。 本篇文章以由浅…

RK3566 linux加入uvc app

SDK中external/uvc_app/目录提供了将板卡模拟成uvc camera的功能。 一、buildroot使能uvc_app 1、进入到buildroot目录 在sdk目录下执行以下命令&#xff1a; cd buildroot 2、选择defconfig 执行命令&#xff1a; source build/envsetup.sh 输入数字然后回车选择板卡&…

两数之和(Hash表)[简单]

优质博文&#xff1a;IT-BLOG-CN 一、题目 给定一个整数数组nums和一个整数目标值target&#xff0c;请你在该数组中找出"和"为目标值target的那两个整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元…

工具推荐 |Devv.ai — 最懂程序员的新一代 AI 搜索引擎

介绍 伴随 GPT 的出现&#xff0c;我们可以看到越来越多的 AI 产品&#xff0c;其中也不乏针对程序员做的代码生成工具。 今天介绍的这款产品是一款针对中文开发者的 AI 搜索引擎&#xff0c;Devv.ai 使用 Devv.ai 的使用非常简单&#xff0c;就是传统的搜索场景&#xff…

JVM:类加载机制

JVM&#xff1a;类加载机制 1. 什么是类加载机制2. 类加载的过程(生命周期)2.1 加载2.2 校验&#xff08;验证&#xff09;2.3 准备2.n 六种情况对类进行“初始化” 1. 什么是类加载机制 Java虚拟机把描述类的数据从Class文件加载到内存&#xff0c;并对数据进行校验、转换解析…

数字化赋能TPM:开启智能生产新篇章

随着科技的快速发展&#xff0c;数字化已经成为企业提升生产效率、优化管理的重要手段。对于设备密集型的制造业而言&#xff0c;传统的TPM&#xff08;全员生产维护&#xff09;方式已经难以满足现代生产的需求。如何将数字化技术与TPM相结合&#xff0c;赋能TPM&#xff0c;提…

机器学习:线性回归模型的原理、应用及优缺点

一、原理 线性回归是一种统计学和机器学习中常用的方法&#xff0c;用于建立变量之间线性关系的模型。其原理基于假设因变量&#xff08;或响应变量&#xff09;与自变量之间存在线性关系。 下面是线性回归模型的基本原理&#xff1a; 模型拟合&#xff1a; 通过最小二乘法&…

2024华数杯国际数学建模B题思路+代码+模型+论文

2024华数杯国际数学建模B题思路代码模型论文&#xff1a;1.17上午第一时间更新&#xff0c;详细内容见文末名片 问题B&#xff1a;光伏电 背景 中国的电力构成包括传统的能源发电&#xff08;如煤炭、石油和天然气&#xff09;、可再生能源发电 &#xff08;如水力发电、风能…

SpringMVC 文件上传和下载

文章目录 1、文件下载2、文件上传3. 应用 Spring MVC 提供了简单而强大的文件上传和下载功能。 下面是对两者的简要介绍&#xff1a; 文件上传&#xff1a; 在Spring MVC中进行文件上传的步骤如下&#xff1a; 在表单中设置 enctype“multipart/form-data”&#xff0c;这样…

Linux网络文件共享服务之NFS

目录 一、NFS简介 1、NFS协议 2、NFS存储 3、NFS原理 4、NFS相关软件介绍 5、NFS配置文件 二、exportfs和showmount命令 三、搭建NFS服务器 1、搭建过程 ​2、客户端权限问题 2.1 权限参数说明 2.2 配置客户端的读写权限 2.3 创建文件的属主和属组权限 2.4 客户端…

供应链|库存定位的高效策略:如何巧妙调换安全库存换取服务速度?

论文作者&#xff1a;Hanzhang Qin, David Simchi-Levi, Ryan Ferer, Jonathan Mays, Ken Merriam, Megan Forrester, Alex Hamrick 论文解读者&#xff1a;马玺渊 王艺桦 编者按 本次解读的文章发表于 Production and Operations Management&#xff0c;原文信息&#xff1a;…

vs2022配置OpenCV测试

1&#xff0c;下载Opencv安装包 OpenCV官网下载地址&#xff1a;Releases - OpenCV 大家可以按需选择版本进行下载&#xff0c;官网下载速度还是比较慢的&#xff0c;推荐大家使用迅雷进行下载 下载安装包到自定义文件夹下 双击安装 按以下图示进行安装 2、 添加环境变量 打…