【redis】使用redis作为缓存时所注意事项

缓存更新策略

在 Redis 缓存中,缓存的更新策略主要有**定期生成(定时更新)实时生成(即时更新)**两种方式。不同的策略适用于不同的业务场景,涉及性能、数据一致性和系统负载等方面的权衡。


1. 定期生成(定时更新)

是什么?

定期生成指的是按照固定的时间间隔,主动更新缓存,而不是在数据发生变化时立即更新。这种方式适用于数据变化不频繁、对实时性要求不高的场景。

优点:

降低数据库压力:缓存可以批量更新,避免频繁查询数据库。
提高查询性能:查询时直接读取缓存,响应速度快。
数据一致性较好(相对于长期不更新的缓存):定期更新可以保证数据不会长期过时。

缺点:

数据可能不够实时:在缓存下一次更新前,数据可能已经变化,但缓存仍然返回旧数据。
不适合高实时性业务:如果业务需要频繁变更数据,定期更新可能导致缓存数据滞后。
可能会引起短时流量冲击:如果所有缓存数据同时更新,可能会对数据库造成瞬间压力。

常见实现方式:

  • 定时任务更新缓存Time-based Refresh

    • 使用 Spring Task、Quartz、Crontab 等定时任务,每隔一段时间刷新缓存。
    • 例如,每 10 分钟更新一次缓存:
      @Scheduled(fixedRate = 600000) // 每 10 分钟执行一次
      public void updateCache() {// 查询数据库并更新缓存List<Data> dataList = databaseService.getData();redisTemplate.opsForValue().set("cache:data", dataList);
      }
      

  • 数据库变更时触发缓存更新Database-triggered Refresh

    • 监听 数据库变更事件(MySQL Binlog、PostgreSQL 触发器),检测到数据变化后批量刷新缓存。
  • 异步任务更新

    • 使用消息队列(Kafka、RabbitMQ)通知服务更新缓存,避免定时任务导致的瞬时数据库压力过大。
适用场景:

📌 统计数据、排行榜、热门商品列表等(更新频率较低,数据稍有延迟也无大问题)。
📌 日志分析、报表数据等(数据量大,但对实时性要求不高)。


2. 实时生成(即时更新)

是什么?

实时生成指的是数据发生变更时立即更新缓存,确保缓存数据始终是最新的。这种方式适用于对数据一致性要求高、变更较频繁的场景。

优点:

数据实时性高:缓存的数据始终与数据库保持一致,适用于高实时性需求的应用。
避免缓存不一致问题:数据库变更后立即同步缓存,减少数据不匹配的情况。

缺点:

更新成本高:每次数据变更都需要更新缓存,可能会导致数据库压力增大。
可能导致缓存频繁更新:对于高频变更的数据,频繁更新可能会导致 Redis 负载过重,甚至影响整体性能。
并发问题:多个并发请求可能会导致缓存不一致缓存击穿,需要加锁或使用双写策略。

常见实现方式:

  1. 数据库更新时主动更新缓存Write-through Strategy

    • 在 **数据更新(新增、修改、删除)**时,同时更新数据库和缓存
      public void updateData(Data data) {databaseService.updateData(data); // 更新数据库redisTemplate.opsForValue().set("cache:data:" + data.getId(), data); // 同步更新缓存
      }
      

    • 适用于数据变更不频繁,且一致性要求较高的场景。
  2. 缓存淘汰(Cache Eviction)

    • 在数据库更新后,删除缓存,让下一次查询时重新加载数据:
      public void updateData(Data data) {databaseService.updateData(data); // 更新数据库redisTemplate.delete("cache:data:" + data.getId()); // 删除缓存
      }
      

    • 适用于缓存数据不是热点,数据变更后不需要立即被查询的情况。
  3. 订阅数据库变更Event-based Strategy

    • 使用 消息队列(Kafka、RabbitMQ)Redis 订阅/发布机制,监听数据库变更事件,变更后更新缓存。
  4. 分布式锁(避免缓存并发写入问题)

    • 解决多个请求同时更新缓存导致数据不一致的问题:
      RLock lock = redissonClient.getLock("cache:lock:data:" + data.getId());
      try {if (lock.tryLock(5, TimeUnit.SECONDS)) {databaseService.updateData(data);redisTemplate.opsForValue().set("cache:data:" + data.getId(), data);}
      } finally {lock.unlock();
      }
      

    • 适用于高并发写入场景,防止缓存同时被多个请求覆盖。
适用场景:

📌 订单系统、支付系统、库存管理等(数据必须实时更新,不能有延迟)。
📌 直播、弹幕系统(数据实时变化,需要确保一致性)。


总结:定期生成 vs. 实时生成

策略定期生成(定时更新)实时生成(即时更新)
数据实时性低(有一定延迟)高(数据库更新即缓存更新)
数据库压力低(定期批量更新)高(频繁更新缓存)
缓存命中率高(查询时直接命中缓存)可能较低(某些情况需删除缓存)
适用场景排行榜、统计数据、报表等订单、库存、支付等高一致性业务

总结

  • 定期生成(定时更新) 适用于数据变化不频繁对实时性要求不高的场景,如排行榜、日志分析等。
  • 实时生成(即时更新) 适用于数据变化频繁对一致性要求高的场景,如支付、库存、订单管理等。
  • 在实际应用中,可以结合两种策略,例如:
    • 定期更新 + 变更触发更新:大部分数据定期刷新,关键数据实时更新。
    • 读时更新 + 写时淘汰:查询时自动更新缓存,写入时删除缓存,防止数据不一致。

合理选择缓存更新策略,可以有效提升系统性能,降低数据库压力,并保证数据的一致性。

Redis 作为缓存,存储空间有限,因此需要淘汰数据来保证新数据的存入。Redis 提供了多种缓存淘汰策略(Eviction Policy),用于决定哪些数据需要被删除。下面介绍几种常见的淘汰策略,包括它们的适用场景和优缺点。


缓存淘汰策略

1. 不淘汰策略

1.1 noeviction(拒绝写入)

概念:

当 Redis 内存占满时,不会删除任何已有数据,而是直接返回错误,拒绝新的写入请求。

适用场景:
  • 适用于严格不能丢数据的场景,如任务队列(消息队列)、金融交易等。
  • 适用于 Redis 作为纯数据存储而非缓存时。
优缺点:

数据不会被误删除,保证数据完整性。
可能导致写入失败,影响系统稳定性。


2. 基于 TTL(过期时间)的淘汰策略

2.1 volatile-lru(最近最少使用,TTL 限定)

概念:
  • 只淘汰**设置了过期时间(TTL)**的键。
  • 在这些键中,优先删除最近最少使用(LRU, Least Recently Used)的数据。
适用场景:
  • 适用于部分数据可丢弃的场景,比如 session、短期缓存数据。
  • 适用于需要自动过期控制,但仍希望尽可能保留热点数据的情况。
优缺点:

优先保留常用数据,减少缓存击穿的概率。
如果大部分 key 没有 TTL,可能导致 Redis 直接拒绝写入(相当于 noeviction)。


2.2 volatile-ttl(优先淘汰即将过期的键)

概念:
  • 只淘汰**设置了过期时间(TTL)**的键。
  • 其中剩余寿命最短的键优先被删除。
适用场景:
  • 适用于对数据有明确的生命周期需求的业务,如订单缓存、验证码缓存等。
优缺点:

优先删除即将过期的数据,保证短期缓存的更新。
可能误删仍然有价值的热点数据。


3. 基于数据访问频率的淘汰策略

3.1 allkeys-lru(全局最近最少使用)

概念:
  • 无视 TTL,从所有键中(包括没有设置 TTL 的键),优先淘汰最近最少使用的键。
适用场景:
  • 适用于热点数据更新频繁的场景,如推荐系统、排行榜、搜索结果缓存等。
优缺点:

可以确保常用数据长期保留,提高缓存命中率。
如果热点数据突然减少访问,可能会被错误淘汰。


3.2 allkeys-random(全局随机淘汰)

概念:
  • 无视 TTL,在所有 key 中随机删除某些数据。
适用场景:
  • 适用于缓存数据均匀访问,不需要特定优先级的场景。
优缺点:

简单高效,减少淘汰策略的计算开销。
不够智能,可能淘汰热点数据,降低缓存命中率。


4. 基于数据访问频次的淘汰策略

4.1 volatile-lfu(基于访问频率,TTL 限定)

概念:
  • 只淘汰设置了 TTL 的 key
  • 访问次数最少的键优先被删除(LFU, Least Frequently Used)。
适用场景:
  • 适用于需要根据访问次数保留数据的业务,如热点文章缓存、用户历史记录等。
优缺点:

能够长期保留高频访问数据,淘汰低频数据。
如果大部分数据没有 TTL,可能导致 Redis 拒绝写入(类似 noeviction)。


4.2 allkeys-lfu(全局最不常使用淘汰)

概念:
  • 无视 TTL,从所有键中优先淘汰访问次数最少的键
适用场景:
  • 适用于热点数据访问有明显差异的情况,如新闻热点推荐、热门产品缓存等。
优缺点:

能保留长期热点数据,提高缓存命中率。
短期热点数据可能无法及时替换,导致数据更新滞后。


总结

策略机制适用场景优点缺点
noeviction拒绝写入不能丢数据(消息队列、金融)数据安全容易写满导致错误
volatile-lru仅淘汰 TTL 数据,LRU需自动过期,保留热点数据减少缓存击穿仅适用于部分数据有 TTL
volatile-ttl仅淘汰 TTL 数据,剩余寿命短的优先订单缓存、验证码优先清理即将失效的缓存可能误删热点数据
allkeys-lru全局 LRU 淘汰访问频率高的缓存(推荐系统)提高缓存命中率可能误删突然冷却的热点数据
allkeys-random随机淘汰数据访问均匀的缓存计算开销小可能淘汰重要数据
volatile-lfu仅淘汰 TTL 数据,访问最少的优先需要根据访问频率保留数据长期热点数据保留仅适用于有 TTL 的 key
allkeys-lfu全局 LFU 淘汰热点明显的数据(新闻、直播)缓存命中率高短期热点更新慢

如何选择淘汰策略?

1. 数据不能丢失(消息队列、金融)

noeviction(拒绝写入)

2. 仅淘汰过期数据(业务数据自动失效)

volatile-lru(保留热点)
volatile-ttl(优先清理快过期数据)

3. 需要智能保留高频访问数据

allkeys-lru(最近最少使用淘汰)
allkeys-lfu(最少使用淘汰)

4. 访问数据均匀,不关心淘汰顺序

allkeys-random(随机删除)

5. 业务需要权衡 LRU 和 LFU

  • 短期热点多,选 LRU
  • 长期热点多,选 LFU

结论

  • 如果数据有 TTL,且希望优先淘汰冷数据,选 volatile-lru / volatile-lfu
  • 如果所有数据都可以被淘汰,选 allkeys-lru / allkeys-lfu
  • 如果只允许写满后拒绝写入,选 noeviction
  • 如果对淘汰规则无特别要求,选 allkeys-random

正确选择淘汰策略,可以有效提高缓存命中率,降低数据库压力,保障系统稳定性。

常见缓存问题

在 Redis 中,缓存预热、缓存穿透、缓存雪崩和缓存击穿是常见的缓存问题。下面分别描述它们的概念及解决方案:


1. 缓存预热(Cache Warming)

是什么?

缓存预热是指在系统启动或运行之前,提前将热点数据加载到缓存中,以减少数据库的查询压力,提高系统访问速度。

如何解决?
  • 手动加载:在服务启动时,手动将热点数据写入缓存。
  • 定时刷新:通过定时任务(如 Spring Task、Quartz 等)定期加载热点数据到缓存。
  • 数据变更同步:监听数据库更新(如 MySQL binlog、Redis 订阅发布机制),在数据变化时同步更新缓存。
  • 批量加载:使用 Redis 的 pipelinemset 命令批量写入缓存,提高加载效率。

2. 缓存穿透(Cache Penetration)

是什么?

缓存穿透指的是大量请求查询不存在的数据,导致每次请求都要查询数据库,缓存完全失效,给数据库带来巨大压力。

如何解决?
  • 缓存空值:如果查询的数据不存在,可以将空值(如 null{})存入缓存,并设置较短的过期时间,避免重复查询数据库。
  • 布隆过滤器(Bloom Filter):使用布隆过滤器提前判断某个 key 是否可能存在,如果一定不存在,则直接返回,不查询数据库。
  • 参数校验:在请求层对参数进行校验,避免无效请求进入系统。
  • 限流与黑名单:对异常请求 IP 进行封禁或限流,避免恶意攻击。

3. 缓存雪崩(Cache Avalanche)

是什么?

缓存雪崩指的是大量缓存同时失效,导致短时间内大量请求直接打到数据库,造成数据库压力激增,甚至宕机。

如何解决?
  • 缓存过期时间随机化:为缓存设置不同的过期时间,避免大量缓存同时失效,例如使用 TTL = 基础时间 ± 随机时间
  • 热点数据提前预加载:在缓存即将过期前,主动刷新缓存,保证热点数据始终可用。
  • 双层缓存:使用 Redis + 本地缓存(如 Caffeine、Guava Cache),降低对 Redis 的依赖。
  • 流量削峰
    • 限流:使用限流算法(如令牌桶、漏桶)限制访问速率。
    • 降级:当数据库压力过大时,返回默认值或降级处理。

4. 缓存击穿(Cache Breakdown)

是什么?

缓存击穿指的是某个热点 key 突然失效,导致大量并发请求直接打到数据库,造成数据库短时间内压力剧增。

如何解决?
  • 设置热点数据永不过期:对于热点数据,直接不设置过期时间,而是由业务逻辑主动更新缓存。
  • 互斥锁(分布式锁)
    • 当缓存失效时,多个请求只允许一个线程查询数据库并更新缓存,其他线程等待缓存更新完成后再读取。
    • 具体实现:使用 SETNX(Redis 分布式锁) 或 Redisson。
  • 提前刷新缓存
    • 通过异步线程提前更新即将过期的热点缓存,防止突然失效。
    • 例如:使用 Redis + 过期监听,在 key 即将过期前主动更新缓存。

总结

问题现象解决方案
缓存预热缓存刚启动时,没有数据手动加载、定时刷新、监听数据变更
缓存穿透查询的 key 在数据库中不存在,每次都查数据库缓存空值、布隆过滤器、参数校验、黑名单
缓存雪崩大量 key 同时失效,数据库压力激增过期时间随机化、双层缓存、限流、降级
缓存击穿某个热点 key 失效,大量请求打到数据库热点数据永不过期、分布式锁、提前刷新

这四个缓存问题都是分布式系统中必须重点关注的,合理的缓存策略可以有效提升系统的性能和稳定性。

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

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

相关文章

html-表格标签

一、表格标签 1. 表格的主要作用 表格主要用于显示&#xff64;展示数据,因为它可以让数据显示的非常的规整,可读性非常好&#xff61;特别是后台展示数据 的时候,能够熟练运用表格就显得很重要&#xff61;一个清爽简约的表格能够把繁杂的数据表现得很有条理&#xff61; 总…

ROS2-话题学习

强烈推荐教程&#xff1a; 《ROS 2机器人开发从入门到实践》3.2.2订阅小说并合成语音_哔哩哔哩_bilibili 构建功能包 # create package demo_python_pkg ros2 pkg create --build-type ament_python --license Apache-2.0 demo_python_pkg 自己写的代码放在./demo_python_pkg/…

Java在小米SU7 Ultra汽车中的技术赋能

目录 一、智能驾驶“大脑”与实时数据 场景一&#xff1a;海量数据的分布式计算 场景二&#xff1a;实时决策的毫秒级响应 场景三&#xff1a;弹性扩展与容错机制 技术隐喻&#xff1a; 二、车载信息系统&#xff08;IVI&#xff09;的交互 场景一&#xff1a;Android Automo…

Oracle RAC配置原理详解:构建高可用与高性能的数据库集群

在现代企业级应用中&#xff0c;数据库的高可用性和高性能是至关重要的。Oracle Real Application Clusters&#xff08;RAC&#xff09;是Oracle数据库提供的一种集群解决方案&#xff0c;能够将多个数据库实例部署在不同的服务器上&#xff0c;实现负载均衡和故障切换&#x…

ESP8266TCP客户端(单连接TCP Client)

单连接TCP Client 电脑作为服务器&#xff0c;8266作为客户端 1.配置WiFi模式 ATCWMODE3 //softAPstation mode 相应&#xff1a;ok 2.连接路由器 ATCWJAP“SSID”&#xff0c;“password” //SSID就是wifi的名字&#xff0c; password WIFI密码 响应&#xff…

【Linux】软硬连接与动静态库

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;linux笔记仓 目录 01.软硬连接02.动静态库静态库&#xff08;Static Library&#xff09;动态库&#xff08;Dynamic Library&#xff09; 03.动态库加载 01.软硬连接 我们先看一下它的用法 这个是…

关于Springboot 应配置外移和Maven个性化打包一些做法

期望达到的效果是每次更新服务器端应用只需要更新主程序jar 依赖jar单独分离。配置文件独立存放于文件夹内&#xff0c;更新程序并不会覆盖已有的配置信息。 一、配置外移 1、开发环境外移 做法&#xff1a;在项目同级或者上级创建config文件夹放置配置文件&#xff0c;具体m…

阿里云操作系统控制台——解决服务器磁盘I/O故障

目录 引言 需求介绍 操作系统使用实例 获得的帮助与提升 建议 引言 你的云服务器是否遇到过系统响应变慢、服务超时&#xff0c;或者进程卡顿、磁盘空间不足、系统日志频繁告警的问题&#xff1f;这些情况在日常运维中并不少见&#xff0c;尤其是在 高负载或资源紧张时&a…

【英伟达AI论文】多模态大型语言模型的高效长视频理解

摘要&#xff1a;近年来&#xff0c;基于视频的多模态大型语言模型&#xff08;Video-LLMs&#xff09;通过将视频处理为图像帧序列&#xff0c;显著提升了视频理解能力。然而&#xff0c;许多现有方法在视觉主干网络中独立处理各帧&#xff0c;缺乏显式的时序建模&#xff0c;…

蓝桥杯备考:图论初解

1&#xff1a;图的定义 我们学了线性表和树的结构&#xff0c;那什么是图呢&#xff1f; 线性表是一个串一个是一对一的结构 树是一对多的&#xff0c;每个结点可以有多个孩子&#xff0c;但只能有一个父亲 而我们今天学的图&#xff01;就是多对多的结构了 V表示的是图的顶点集…

记录小白使用 Cursor 开发第一个微信小程序(一):注册账号及下载工具(250308)

文章目录 记录小白使用 Cursor 开发第一个微信小程序&#xff08;一&#xff09;&#xff1a;注册账号及下载工具&#xff08;250308&#xff09;一、微信小程序注册摘要1.1 注册流程要点 二、小程序发布流程三、下载工具 记录小白使用 Cursor 开发第一个微信小程序&#xff08…

【Linux学习笔记】Linux基本指令分析和权限的概念

【Linux学习笔记】Linux基本指令分析和权限的概念 &#x1f525;个人主页&#xff1a;大白的编程日记 &#x1f525;专栏&#xff1a;Linux学习笔记 文章目录 【Linux学习笔记】Linux基本指令分析和权限的概念前言一. 指令的分析1.1 alias 指令1.2 grep 指令1.3 zip/unzip 指…

【消息队列】数据库的数据管理

1. 数据库的选择 对于当前实现消息队列这样的一个中间件来说&#xff0c;具体要使用哪个数据库&#xff0c;是需要稍作考虑的&#xff0c;如果直接使用 MySQL 数据库也是能实现正常的功能&#xff0c;但是 MySQL 也是一个客户端服务器程序&#xff0c;也就意味着如果想在其他服…

【HarmonyOS Next】鸿蒙加固方案调研和分析

【HarmonyOS Next】鸿蒙加固方案调研和分析 一、前言 根据鸿蒙应用的上架流程&#xff0c;本地构建app文件后&#xff0c;上架到AGC平台&#xff0c;平台会进行解析。根据鸿蒙系统的特殊设置&#xff0c;仿照IOS的生态闭环方案。只能从AGC应用市场下载app进行安装。这样的流程…

nuxt2 打包优化使用“compression-webpack-plugin”插件

在使用 Nuxt.js 构建项目时&#xff0c;为了提高性能&#xff0c;通常会考虑对静态资源进行压缩。compression-webpack-plugin 是一个常用的 Webpack 插件&#xff0c;用于在生产环境中对文件进行 Gzip 压缩。这对于减少网络传输时间和提高页面加载速度非常有帮助。下面是如何在…

不同开发语言之for循环的用法、区别总结

一、Objective-C &#xff08;1&#xff09;标准的c风格 for (int i 0; i < 5; i) {NSLog("i %d", i); } &#xff08;2&#xff09;for in循环。 NSArray *array ["apple", "banana", "orange"]; for (NSString *fruit in …

ctfshow做题笔记—栈溢出—pwn65~pwn68

目录 前言 一、pwn65(你是一个好人) 二、pwn66(简单的shellcode&#xff1f;不对劲&#xff0c;十分得有十二分的不对劲) 三、pwn67(32bit nop sled)&#xff08;确实不会&#xff09; 四、pwn68(64bit nop sled) 前言 做起来比较吃力哈哈&#xff0c;自己还是太菜了&…

Git基础之工作原理

基础概念 git本地有三个工作区域&#xff0c;工作目录 Working Directory&#xff0c;暂存区Stage/Index和资源区Repository/Git Directory&#xff0c;如果在加上远程的git仓库就是四个工作区域 四个区域与文件交换的命令之间的关系 WorkSpace&#xff1a;工作区&#xff0c;就…

Linux 指定命令行前后添加echo打印内容

目录 一. 前提条件二. 通过sh脚本进行批量修改三. 通过Excel和文本编辑器进行批量转换四. 实际执行效果 一. 前提条件 ⏹项目中有批量检索文件的需求&#xff0c;如下所示需要同时执行500多个find命令 find ./work -type f -name *.java find ./work -type f -name *.html fi…

Immich自托管服务的本地化部署与随时随地安全便捷在线访问数据

文章目录 前言1.关于Immich2.安装Docker3.本地部署Immich4.Immich体验5.安装cpolar内网穿透6.创建远程链接公网地址7.使用固定公网地址远程访问 前言 小伙伴们&#xff0c;你们好呀&#xff01;今天要给大家揭秘一个超炫的技能——如何把自家电脑变成私人云相册&#xff0c;并…