【分布式微服务云原生】《Redis 缓存污染问题全解析及淘汰策略深度探索》

《Redis 缓存污染问题全解析及淘汰策略深度探索》

摘要:本文将深入探讨 Redis 中的缓存污染问题,包括其定义、产生的影响以及解决方法。同时,详细介绍 Redis 支持的多种缓存淘汰策略,帮助读者更好地理解和应用 Redis 缓存,提升系统性能。读者将从本文中获得关于 Redis 缓存优化的实用知识和技巧。

关键词:Redis、缓存污染、缓存淘汰策略、LRU、LFU、noeviction、volatile-random、volatile-ttl、volatile-lru、volatile-lfu、allkeys-lru、allkeys-random、allkeys-lfu

一、缓存污染问题的定义与影响

  1. 定义
    • 缓存污染问题说的是缓存中一些只会被访问一次或者几次的数据,被访问完后,再也不会被访问到,但这部分数据依然留存在缓存中,消耗缓存空间。
  2. 影响
    • 缓存污染会随着数据的持续增加而逐渐显露,随着服务的不断运行,缓存中会存在大量的永远不会再次被访问的数据。
    • 缓存空间是有限的,如果缓存空间满了,再往缓存里写数据时就会有额外开销,影响 Redis 性能。这部分额外开销主要是指写的时候判断淘汰策略,根据淘汰策略去选择要淘汰的数据,然后进行删除操作。

二、解决缓存污染问题的方法

解决缓存污染问题,实际上就是配置缓存淘汰策略,要把不会再被访问的数据筛选出来并删除掉,为后续写入的数据腾空间。

三、Redis 支持的缓存淘汰策略

(一)策略分类

Redis 支持的缓存淘汰策略可以分为两类:

  1. volatile开头的淘汰策略是在设置了过期时间的数据中进行淘汰,共有四种。
  2. allkeys开头的淘汰策略是在所有数据中进行淘汰,共有三种。

(二)具体策略详解

  1. noeviction
    • 该策略是 Redis 的默认策略。在这种策略下,一旦缓存被写满了,再有写请求来时,Redis 不再提供服务,而是直接返回错误。
    • 这种策略不会淘汰数据,所以无法解决缓存污染问题。一般生产环境不建议使用。其他七种规则都会根据自己相应的规则来选择数据进行删除操作。
  2. volatile-random
    • 在设置了过期时间的键值对中,进行随机删除。
    • 因为是随机删除,无法把不再访问的数据筛选出来,所以可能依然会存在缓存污染现象,无法解决缓存污染问题。
  3. volatile-ttl
    • 这种算法在判断淘汰数据时参考的指标比随机删除时多进行一步过期时间的排序。
    • Redis 在筛选需删除的数据时,越早过期的数据越优先被选择。
  4. volatile-lru
    • 会使用 LRU 算法筛选设置了过期时间的键值对。
    • LRU 算法的全称是 Least Recently Used,按照最近最久未被使用的原则来筛选数据。
    • Redis 优化的 LRU 算法实现:Redis 会记录每个数据的最近一次被访问的时间戳。在 Redis 在决定淘汰的数据时,第一次会随机选出 N 个数据,把它们作为一个候选集合。接下来,Redis 会比较这 N 个数据的 lru 字段,把 lru 字段值最小的数据从缓存中淘汰出去。通过随机读取待删除集合,可以让 Redis 不用维护一个巨大的链表,也不用操作链表,进而提升性能。Redis 选出的数据个数 N,通过配置参数 maxmemory-samples 进行配置。个数 N 越大,则候选集合越大,选择到的最久未被使用的就更准确,N 越小,选择到最久未被使用的数据的概率也会随之减小。
  5. volatile-lfu
    • 会使用 LFU 算法选择设置了过期时间的键值对。
    • LFU 算法:LFU 缓存策略是在 LRU 策略基础上,为每个数据增加了一个计数器,来统计这个数据的访问次数。当使用 LFU 策略筛选淘汰数据时,首先会根据数据的访问次数进行筛选,把访问次数最低的数据淘汰出缓存。如果两个数据的访问次数相同,LFU 策略再比较这两个数据的访问时效性,把距离上一次访问时间更久的数据淘汰出缓存。
    • Redis 的 LFU 算法实现:当 LFU 策略筛选数据时,Redis 会在候选集合中,根据数据 lru 字段的后 8bit 选择访问次数最少的数据进行淘汰。当访问次数相同时,再根据 lru 字段的前 16bit 值大小,选择访问时间最久远的数据进行淘汰。
    • Redis 只使用了 8bit 记录数据的访问次数,而 8bit 记录的最大值是 255,这样在访问快速的情况下,如果每次被访问就将访问次数加一,很快某条数据就达到最大值 255,可能很多数据都是 255,那么退化成 LRU 算法了。所以 Redis 为了解决这个问题,实现了一个更优的计数规则,并可以通过配置项,来控制计数器增加的速度。
      • 参数 lfu-log-factor:用计数器当前的值乘以配置项 lfu_log_factor 再加 1,再取其倒数,得到一个 p 值;然后,把这个 p 值和一个取值范围在(0,1)间的随机数 r 值比大小,只有 p 值大于 r 值时,计数器才加 1。
      • 参数 lfu-decay-time:控制访问次数衰减。LFU 策略会计算当前时间和数据最近一次访问时间的差值,并把这个差值换算成以分钟为单位。然后,LFU 策略再把这个差值除以 lfu_decay_time 值,所得的结果就是数据 counter 要衰减的值。
      • lfu-log-factor设置越大,递增概率越低,lfu-decay-time设置越大,衰减速度会越慢。我们在应用 LFU 策略时,一般可以将 lfu_log_factor 取值为 10。如果业务应用中有短时高频访问的数据的话,建议把 lfu_decay_time 值设置为 1。可以快速衰减访问次数。volatile-lfu 策略是 Redis 4.0 后新增。
  6. allkeys-lru
    • 使用 LRU 算法在所有数据中进行筛选。
    • 具体 LFU 算法跟上述 volatile-lru 中介绍的一致,只是筛选的数据范围是全部缓存。
  7. allkeys-random
    • 从所有键值对中随机选择并删除数据。
    • volatile-random 跟 allkeys-random 算法一样,随机删除就无法解决缓存污染问题。
  8. allkeys-lfu
    • 使用 LFU 算法在所有数据中进行筛选。
    • 具体 LFU 算法跟上述 volatile-lfu 中介绍的一致,只是筛选的数据范围是全部缓存。allkeys-lfu 策略是 Redis 4.0 后新增。

(三)策略对比表格

策略名称淘汰范围淘汰方式能否解决缓存污染问题
noeviction无特定范围不淘汰数据
volatile-random设置了过期时间的数据随机删除可能无法解决
volatile-ttl设置了过期时间的数据按过期时间排序淘汰可能部分解决
volatile-lru设置了过期时间的数据LRU 算法相对较好地解决
volatile-lfu设置了过期时间的数据LFU 算法较好地解决
allkeys-lru所有数据LRU 算法相对较好地解决
allkeys-random所有数据随机删除无法解决
allkeys-lfu所有数据LFU 算法较好地解决

(四)Java 代码示例

以下是使用 Jedis 连接 Redis 并设置缓存淘汰策略为allkeys-lru的示例代码:

import redis.clients.jedis.Jedis;

public class RedisExample {
    public static void main(String[] args) {
        Jedis jedis = new Jedis("localhost", 6379);
        // 设置缓存淘汰策略为 allkeys-lru
        jedis.configSet("maxmemory-policy", "allkeys-lru");
        jedis.set("key1", "value1");
        jedis.set("key2", "value2");
        System.out.println(jedis.get("key1"));
        System.out.println(jedis.get("key2"));
        jedis.close();
    }
}

(五)LRU 算法流程图

开始
数据访问
数据是否在缓存中
更新最近访问时间
判断缓存是否已满
将数据放入缓存
根据 LRU 算法选择要淘汰的数据
淘汰数据
结束

四、总结与建议

Redis 4.0 之前一共实现了 6 种内存淘汰策略分别是 noeviction、volatile-random、volatile-ttl、volatile-lru、allkeys-lru、allkeys-random,在 4.0 之后,又增加了 2 种策略,分别是 allkeys-lfu,volatile-lfu。建议优先使用 allkeys-lru 策略。使用 allkeys 开头的策略,在所有数据中进行选择,防止客户端因不规范等原因,随意设置的缓存数据,没配置超时时间。还可以利用 LRU 这一经典缓存算法的优势,把最近最常访问的数据留在缓存中,提升应用的访问性能。

内容详情
缓存污染问题定义缓存中一些只会被访问一次或者几次的数据,被访问完后,再也不会被访问到,但仍留存在缓存中消耗空间。
缓存污染问题影响数据持续增加时,缓存中存在大量不再被访问的数据,影响 Redis 性能。
解决方法配置缓存淘汰策略,筛选并删除不会再被访问的数据。
Redis 淘汰策略分类volatile 开头在设置过期时间的数据中淘汰,allkeys 开头在所有数据中淘汰。
具体淘汰策略noeviction、volatile-random、volatile-ttl、volatile-lru、volatile-lfu、allkeys-lru、allkeys-random、allkeys-lfu。
策略对比不同策略在淘汰范围、淘汰方式和解决缓存污染问题能力上有所不同。
Java 代码示例使用 Jedis 设置缓存淘汰策略为 allkeys-lru。
LRU 算法流程图展示 LRU 算法的数据访问和淘汰流程。
总结与建议优先使用 allkeys-lru 策略,利用 LRU 算法优势提升性能。

嘿,小伙伴们!关于 Redis 的缓存污染问题和淘汰策略就介绍到这里啦。如果你有更好的见解或者经验,欢迎在评论区分享哦!让我们一起把 Redis 用得更溜吧!😉

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【UE5】通过程序化网格体组件实现剖切功能

效果 步骤 1. 新建两个Actor类蓝图,分别命名为“BP_CutActor”、“BP_CutPlane”,分别表示被剖切的网格体和剖切的片面。 2. 打开“BP_CutActor”(被剖切的网格体),添加静态网格体组件、程序化网格体组件,…

(三)第一个Qt程序“Qt版本的HelloWorld”

一、随记 我们在学习编程语言的时候,各种讲解编程语言的书籍中通常都会以一个非常经典的“HelloWorld”程序展开详细讲解。程序虽然简短,但是“麻雀虽小,五脏俱全”,但是却非常适合用来熟悉程序结构、规范,快速形成对编…

原型模式和建造模式的区别

原型模式(Prototype Pattern)和建造者模式(Builder Pattern)虽然都是创建型设计模式,但它们的应用场景和实现方式有着显著的区别。以下是二者的详细对比: 1. 意图和应用场景 原型模式: 意图&a…

【论文阅读】2022 TChecker Precise Static Inter-Procedural Analysis for Detecting

总览 “TChecker: Precise Static Inter - Procedural Analysis for Detecting Taint - Style Vulnerabilities in PHP Applications” 由香港中文大学的 Changhua Luo、Penghui Li 和 Wei Meng 撰写。论文介绍了 TChecker 工具,用于检测 PHP 应用中的污点式漏洞&am…

【Linux】为什么环境变量具有全局性?共享?写时拷贝优化?

环境变量表具有全局性的原因: 环境变量表之所以具有全局性的特征,主要是因为它们是在进程上下文中维护的,并且在大多数操作系统中,当一个进程创建另一个进程(即父进程创建子进程)时,子进程会继承…

动态路由:RIP实验

1.划分IP 2.配置环回 3.接口配置IP地址 4.进入RIP中,关闭手工汇总,选择版本号,宣告 5.ping命令查看是否全网通 6.在R3上配置缺省路由 [R3-rip-1]default-route originate 在边界路由器上下发缺省 7.为了安全配置手工认证 [R1-Gigab…

qt QVariant详解

QVariant是Qt框架中一个功能强大的变体类,它提供了一种通用的方式来存储Qt对象及其他类的值,能够以类似于指针的方式存储任意类型的值。 一、 主要特性 通用性:QVariant可以存储几乎所有数据类型,包括基本数据类型(如…

刷题小记9:回溯

回溯算法模板: void backtracking(参数) {if (终止条件) {存放结果;return;}for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {处理节点;backtracking(路径,选择列表); // 递归回溯,撤销处理…

html+vue实现动态复杂table

1、效果 2、代码 <div style"overflow: scroll; width: 100%;height: calc(100% - 80px);"><table class"table table-bordered" style"width: auto;table-layout: fixed;"><thead style"position: sticky;top: -1px;z-inde…

【C++干货篇】——类和对象的魅力(四)

【C干货篇】——类和对象的魅力&#xff08;四&#xff09; 1.取地址运算符的重载 1.1const 成员函数 将const修饰的成员函数称之为const成员函数&#xff0c;const修饰成员函数放到成员函数参数列表的后面。const实际修饰该成员函数隐含的this指针&#xff08;this指向的对…

IDEA如何查看所有的断点(Breakpoints)并关闭

前言 我们在使用IDEA开发Java应用时&#xff0c;基本上都需要进行打断点的操作&#xff0c;这方便我们排查BUG&#xff0c;也方便我们查看设计的是否正确。 不过有时候&#xff0c;我们不希望进入断点&#xff0c;这时候除了点击断点关闭外&#xff0c;有没有更快速的方便关闭…

深入浅出剖析重量级文生图模型Flux.1

24年8月&#xff0c;Flux.1的发布又一次火爆整个AI绘图领域&#xff0c; 号称AI文生图的“新标杆”&#xff0c;刷新AI图像领域的新格局。 Flux是一款由Black Forest Labs开发的尖端AI图像生成工具&#xff0c;旨在通过先进的技术将文本提示转化为高质量的图像。Flux AI支持多…

利用 OBS 推送 WEBRTC 流到 smart rtmpd

webrtc whip 推流 & whep 拉流简介 RFC 定义 通用的 webrtc 对于 SDP 协议的交换已经有对应的 RFC 草案出炉了。这就是 WHIP( push stream ) & WHEP ( pull stream ) . WHIP RFC Link: https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html WHEP RFC Link:…

总分441数一149专137东南大学820信号数电考研经验电子信息与通信工程电路原920专业基础综合,真题,大纲,参考书。

一. 写在前面的话 本人是23年考生&#xff0c;本科就读于西电电子信息工程&#xff0c;以441分总分&#xff08;数学一149&#xff0c;英语83&#xff0c;专业课820&#xff08;原920信号和数电专业基础综合&#xff09;137&#xff0c;政治73&#xff09;考上东南信院电路与系…

虚拟机(VMwara Workstation17)保姆级别的安装(附软件获取途径)

文章目录 一、虚拟机的作用二、虚拟机的获取三、虚拟机的安装步骤四、总结 一、虚拟机的作用 压根不需要给自己的电脑重装系统&#xff0c;就可以使用Linux系统。简单来说就是虚拟出一个计算机&#xff0c;安装Linux系统&#xff0c;便于学习和工作 关于虚拟机的介绍&#xf…

初识Linux · 预备文件系统

目录 前言&#xff1a; 看看物理磁盘 了解磁盘的存储结构 对磁盘进行逻辑抽象 前言&#xff1a; 我们在上文探讨的问题都是基于文件是被打开的情况&#xff0c;那么对于文件没有被打开的情况&#xff0c;我们是没有探讨过的&#xff0c;而本文作为文件系统的预备知识&…

多ip访问多网站

1.前提配置 关防火墙 关selinux 2.安装web服务程序nginx 3.当前主机添加多地址&#xff08;ip a&#xff09; 4.自定义nginx配置文件通过多地址区分多网站 /etc/nginx/conf.d/test_ip.conf server { #标记为一个虚拟主机} 5.根据配置在主机创建数据文件 6.重启服务加载配…

【ROS2】构建导航工程

1、ROS小车组成 ROS小车由三大件组成:运动底盘、ROS主控、导航传感器。 1.1 运动底盘 运动底盘的硬件由车轮、电机(带编码器)、电机驱动器、STM32控制器、电池等组成。 涉及的知识点主要为:STM32单片机程序、机器人运动学分析 1)STM32单片机程序 单片机程序框架如下:…

Modbus TCP报错:Response length is only 0 bytes

问题描述&#xff1a; 使用modbus_tk库&#xff0c;通过Modbus tcp连接PLC时&#xff0c;python中的一个报错信息&#xff1a; Response length is only 0 bytes报错原因&#xff1a; 与Modbus TCP 服务端建立连接后没有断开&#xff0c;继续作为长连接使用&#xff0c;客户端…

vue3 + ts + element-plus 二次封装 el-dialog

实现效果&#xff1a; 组件代码&#xff1a;注意 style 不能为 scoped <template><el-dialog class"my-dialog" v-model"isVisible" :show-close"false" :close-on-click-modal"false" :modal"false"modal-class&…