Redis查询缓存

article/2025/8/23 3:26:14

文章目录

  • 缓存更新策略
    • 主动更新策略
    • 问题考虑
  • 难题
    • 1.缓存穿透
      • 解决方案:
    • 2.缓存击穿
      • 互斥锁
      • 逻辑过期
    • 3.缓存雪崩
  • 商品查询缓存实例
    • 解决缓存穿透
    • 解决缓存击穿
      • 互斥锁(这里还要考虑了缓存穿透问题)
      • 逻辑时间

缓存更新策略

内存淘汰超时剔除主动更新
redis自动进行,当redis内存达到咱们设定的max-memery的时候,会自动触发淘汰机制,淘汰掉一些不重要的数据(可以自己设置策略方式)当我们给redis设置了过期时间ttl之后,redis会将超时的数据进行删除,方便咱们继续使用缓存我们可以手动调用方法把缓存删掉,通常用于解决缓存和数据库不一致问题

由于我们的缓存的数据源来自于数据库,而数据库的数据是会发生变化的,因此,如果当数据库中数据发生变化,而缓存却没有同步,此时就会有一致性问题存在,其后果是:

业务场景

  • 低一致性需求:使用内存淘汰
  • 高一致性需求:主动更新,并以超时剔除作为兜底方案

主动更新策略

用户使用缓存中的过时数据,就会产生类似多线程数据安全问题,有如下几种解决方案

  • Cache Aside Pattern 人工编码方式:缓存调用者在更新完数据库后再去更新缓存,也称之为双写方案

  • Read/Write Through Pattern : 由系统本身完成,数据库与缓存的问题交由系统本身去处理

  • Write Behind Caching Pattern :调用者只操作缓存,其他线程去异步处理数据库,实现最终一致

问题考虑

  • 删除缓存还是更新缓存?

更新缓存:每次更新数据库都更新缓存,假如更新数据库100次,缓存也更新100次,但期间没人查询,会导致无效写操作较多
删除缓存:更新数据库时让缓存失效,查询时再更新缓存

  • 如何保证缓存与数据库的操作的同时成功或失败?

单体系统,将缓存与数据库操作放在一个事务
分布式系统,利用TCC等分布式事务方案

  • 先操作缓存还是先操作数据库?

先删除缓存,再操作数据库
先操作数据库,再删除缓存

在这里插入图片描述

数据库20和缓存10数据不一致了,这种出行问题可能性较大

在这里插入图片描述

缓存10和数据库20出现了不一致,这种出现问题可能较小,因为写缓存时间非常短,这期间出现一个并发的线程插入可能较小。


难题

1.缓存穿透

缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。

解决方案:

  • 缓存空对象(会占空间)
    在这里插入图片描述

  • 布隆过滤(实现复杂)
    在这里插入图片描述


2.缓存击穿

在这里插入图片描述

缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击。(秒杀抢卷业务)

常见的解决方案有两种:

  • 互斥锁
  • 逻辑过期

互斥锁

在这里插入图片描述

保证一致性,但可能死锁,性能受影响

逻辑过期

在这里插入图片描述

无需等待,但需额外内存消耗,不能保证一致性


3.缓存雪崩

缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。

解决方案:

  • 给不同的Key的TTL添加随机值
  • 利用Redis集群提高服务的可用性
  • 给缓存业务添加降级限流策略
  • 给业务添加多级缓存

商品查询缓存实例

解决缓存穿透

public <R,ID> R queryWithPassThrough(String keyPrefix, ID id, Class<R> type, Function<ID, R> dbFallback, Long time, TimeUnit unit){String key = keyPrefix + id;// 1.从redis查询商铺缓存String json = stringRedisTemplate.opsForValue().get(key);// 2.判断是否存在if (StrUtil.isNotBlank(json)) {// 3.存在且字符串不为空,直接返回return JSONUtil.toBean(json, type);}// 判断命中的是否是空值,如果为空值证明缓存和数据库都没有该店铺信息,这就是缓存穿透的第一种解决办法if (json != null) {// 返回一个错误信息return null;}// 4.缓存不存在,根据id查询数据库R r = dbFallback.apply(id);// 5.不存在,返回错误if (r == null) {// 将空值写入redisstringRedisTemplate.opsForValue().set(key, "", CACHE_NULL_TTL, TimeUnit.MINUTES);// 返回错误信息return null;}// 6.存在,写入redisthis.set(key, r, time, unit);return r;
}

解决缓存击穿

互斥锁(这里还要考虑了缓存穿透问题)

public <R, ID> R queryWithMutex(String keyPrefix, ID id, Class<R> type, Function<ID, R> dbFallback, Long time, TimeUnit unit) {String key = keyPrefix + id;// 1.从redis查询商铺缓存String shopJson = stringRedisTemplate.opsForValue().get(key);// 2.判断是否存在if (StrUtil.isNotBlank(shopJson)) {// 3.缓存存在(命中)且不为空值,直接返回return JSONUtil.toBean(shopJson, type);}// 判断命中的是否是空值,空值代表就是缓存和数据库都没有该店铺信息了if (shopJson != null) {// 返回一个错误信息return null;}// 4.实现缓存重建,防止缓存击穿问题// 4.1.获取互斥锁String lockKey = LOCK_SHOP_KEY + id;R r = null;try {boolean isLock = tryLock(lockKey);// 4.2.判断是否获取成功if (!isLock) {// 4.3.获取锁失败,休眠并重试Thread.sleep(50);// 自旋return queryWithMutex(keyPrefix, id, type, dbFallback, time, unit);}// 4.4.获取锁成功,根据id查询数据库r = dbFallback.apply(id);// 5.不存在,返回错误if (r == null) {// 将空值写入redis,防止缓存穿透stringRedisTemplate.opsForValue().set(key, "", CACHE_NULL_TTL, TimeUnit.MINUTES);// 返回错误信息return null;}// 6.存在,写入redisthis.set(key, r, time, unit);} catch (InterruptedException e) {throw new RuntimeException(e);}finally {// 7.释放锁unlock(lockKey);}// 8.返回return r;
}

逻辑时间

因为缓存不存在过期,只有逻辑过期(查不到热点,证明数据库也没有了),所以直接返回空,解决了缓存穿透问题,就不用考虑了

public <R, ID> R queryWithLogicalExpire(String keyPrefix, ID id, Class<R> type, Function<ID, R> dbFallback, Long time, TimeUnit unit) {String key = keyPrefix + id;// 1.从redis查询商铺缓存String json = stringRedisTemplate.opsForValue().get(key);// 2.判断是否存在if (StrUtil.isBlank(json)) {// 3.存在,直接返回return null;}// 4.命中,需要先把json反序列化为对象RedisData redisData = JSONUtil.toBean(json, RedisData.class);R r = JSONUtil.toBean((JSONObject) redisData.getData(), type);LocalDateTime expireTime = redisData.getExpireTime();// 5.判断是否过期if(expireTime.isAfter(LocalDateTime.now())) {// 5.1.未过期,直接返回店铺信息return r;}// 5.2.已过期,需要缓存重建// 6.缓存重建// 6.1.获取互斥锁String lockKey = LOCK_SHOP_KEY + id;boolean isLock = tryLock(lockKey);// 6.2.判断是否获取锁成功if (isLock){// 6.3.成功,开启独立线程,实现缓存重建CACHE_REBUILD_EXECUTOR.submit(() -> {try {// 查询数据库R newR = dbFallback.apply(id);// 重建缓存this.setWithLogicalExpire(key, newR, time, unit);} catch (Exception e) {throw new RuntimeException(e);}finally {// 释放锁unlock(lockKey);}});}// 6.4.返回过期的商铺信息return r;
}

http://chatgpt.dhexx.cn/article/7TOoHkLg.shtml

相关文章

redis的成功写入缓存但查不了

最近在学习redis的简单应用并写出实例结果出现了一个非常奇怪的问题&#xff0c;每次查询都是从mysql中读入并且写入缓存成功但当我再次查询时仍然是从MySQL中读取数据并且再次写入缓存 这让我十分疑惑&#xff0c;实际上就是因为我#spring.redis.database1这行代码没有写但我…

TP框架无法写入缓存文件

问题 解决方案&#xff1a;TP框架无法写入缓存文件

网站提示 缓存文件写入失败 PHP

2019独角兽企业重金招聘Python工程师标准>>> 先确认诸如.cache这样的文件夹已创建成功执行&#xff1a; chmod 777 -R /www&#xff0c;其中/www更换为项目根目录如果是生产环境谨慎设置目录权限&#xff0c;可以只设置需要写权限的 转载于:https://my.oschina.net/…

延缓写入失败计算机硬件,WinXP提示windows写入延缓失败怎么办?写入延缓失败解决方法...

虽然WinXP系统已经退市&#xff0c;但是一些老电脑用户依然坚守XP系统&#xff0c;那么在使用XP系统的过程中经常会出一些小问题&#xff0c;比较常见的就是系统提示“windows写入延缓失败”&#xff0c;那么遇到WinXP提示windows写入延缓失败怎么办&#xff1f;下面装机之家就…

linux缓存无法写入,缓存文件写入失败_Linux下搭建网站提示缓存文件写入失败怎么办...

摘要 腾兴网为您分享:Linux下搭建网站提示缓存文件写入失败怎么办&#xff0c;中意在线&#xff0c;智联招聘&#xff0c;优化大师&#xff0c;易信等软件知识&#xff0c;以及快易多&#xff0c;酷狗6&#xff0c;cc语音&#xff0c;反编译app&#xff0c;快捷酒店管家&#x…

linux缓存无法写入,Linux下搭建网站提示缓存文件写入失败解决方法?

Linux下搭建网站提示缓存文件写入失败时该怎么处理&#xff1f;基于ThinkPHP框架及Linux环境搭建的网站&#xff0c;经常会遭遇缓存文件写入失败的错误提示&#xff0c;即便是现在流行的P2P网站软件便是如此&#xff0c;具体处理办法请看下文。 Linux下搭建网站提示缓存文件写入…

计算机硬盘写入错误怎么办,电脑提示缓存文件写入失败

非正常电脑关引起的&#xff1a; 如果是非正常关电脑引起的写入缓存失败&#xff0c;那就在【运行】中输入【CHKDSK 盘符】。 系统错误&#xff1a; 1&#xff0c;打开我的电脑&#xff0c;打开本地磁盘属性&#xff0c;在弹出的对话框中选择【工具】--【开始检查】&#xff0c…

php linux 缓存文件,Linux下搭建网站提示缓存文件写入失败的处理办法

Linux下建立网站提示缓存文件写入失利时该怎样处理&#xff1f;依据ThinkPHP结构及Linux环境建立的网站&#xff0c;经常会遭受缓存文件写入失利的过错提示&#xff0c;即就是现在盛行的P2P网站程序就是如此&#xff0c;详细处理办法请看下文。 缓存文件写入失利常见原因&#…

linux 下缓存失败,Linux下搭建网站提示缓存文件写入失败怎么办?

Linux下搭建网站提示缓存文件写入失败时该怎么处理&#xff1f;基于ThinkPHP框架及Linux环境搭建的网站&#xff0c;经常会遭遇缓存文件写入失败的错误提示&#xff0c;即便是现在流行的P2P网站程序便是如此&#xff0c;具体解决方法请看下文。 Linux下搭建网站提示缓存文件写入…

php本地缓存错误,thinkphp网站提示缓存文件写入失败

thinkphp网站提示缓存文件写入失败 问题描述&#xff1a; 有用户在虚拟主机中运行thinkphp网站程序时会有些不顺利&#xff0c;如果遇到访问网站提示缓存文件写入失败!:./App/Runtime/Cache/En/4f5e9b635ecef48c04ac2cd42e8b5956.php 问题分析&#xff1a; 如果您遇到上述问题&…

灾备知识总结:容灾与备份区别、灾备技术、容灾体系规划

1.容灾备份的区别 容灾 &#xff08;Disaster Tolerance&#xff09;&#xff1a;就是在上述的灾难发生时&#xff0c;在保证生产系统的数据尽量少丢失的情况下&#xff0c;保持生存系统的业务不间断地运行。 容错 &#xff08;Fault Tolerance&#xff09;&#xff1a;指在计…

容灾与备份的区别与联系

容灾备份的区别 容灾 &#xff08;Disaster Tolerance&#xff09;&#xff1a;就是在上述的灾难发生时&#xff0c;在保证生产系统的数据尽量少丢失的情况下&#xff0c;保持生存系统的业务不间断地运行。 容错 &#xff08;Fault Tolerance&#xff09;&#xff1a;指在计算机…

容灾与备份区别、灾备技术、容灾体系规划

1.容灾备份的区别 容灾 &#xff08;Disaster Tolerance&#xff09;&#xff1a;就是在上述的灾难发生时&#xff0c;在保证生产系统的数据尽量少丢失的情况下&#xff0c;保持生存系统的业务不间断地运行。 容错 &#xff08;Fault Tolerance&#xff09;&#xff1a;指在计…

通俗易懂浅谈一下服务器异地容灾备份

最近关于服务器异地容灾备份等话题热度逐渐上升&#xff0c;服务端的网络、机房硬件等一旦出现故障&#xff0c;将有可能导致大规模的服务瘫痪&#xff0c;商城订单下降等&#xff0c;进而对公司造成经济损失。 服务端灾备不仅是运维人员的工作&#xff0c;前后端开发人员也有…

容灾数据复制技术的比较

容灾数据复制技术的比较 一、概述 近几年来&#xff0c;容灾已经成为信息数据中心建设的热门课题。很多容灾技术也快速发展起来&#xff0c;对用户来说也有很广阔的选择余地。但由于容灾方案的技术复杂性和多样性&#xff0c;一般用户很难搞清其中的优劣以确定如何选择最适合自…

云计算技术 — 容灾备份技术

目录 文章目录 目录本地多活同城双活多 Region多云异地双活两地三中心异地多活本地多活 同城双活 多 Region AWS Region 是由多个可用区(availability zone,AZ)组成的,每个 AZ 是一个或多个的数据中心,它们具有独立的电源、网络和连接。在一个 Region 的多个 AZ 中运行能…

容灾与备份究竟有什么区别?

更多专业文档请访问 www.itilzj.com 1.容灾备份的区别 容灾 &#xff08;Disaster Tolerance&#xff09;&#xff1a;就是在上述的灾难发生时&#xff0c;在保证生产系统的数据尽量少丢失的情况下&#xff0c;保持生存系统的业务不间断地运行。 容错 &#xff08;Fault Tolera…

云数据中心容灾备份方案

云计算中心涵盖系统多、类型复杂、关键性程度不一,因此对于恢复目标也有不同的要求,针对不同恢复目标的业务采取不同的灾备技术,同时考虑到数据中心重要性,需要建立同城灾备数据中心,并规划异地灾备中心,实现两地三中心。 一、数据中心业务分析 业务恢复目标 XX云中心…

数据备份与数据容灾全解析(图)

【IT168 专稿】 许多读者对经常听到的数据容灾这种说法不理解&#xff0c;把数据容灾与数据备份等同起来&#xff0c;其实这是错误的。为此&#xff0c;笔者在本文中要向大家解释数据容灾与数据备份的区别&#xff0c;同时还将介绍几种典型的数据容灾等级和关键技术。首先来看…

数据保护与容灾备份

在云与大数据时代&#xff0c;海量增长的数据容量&#xff0c;给数据的存储和保护带来新的挑战&#xff0c;从传统熟悉的IT架构到以云架构、虚拟化、超融合为代表的技术升级迭代&#xff0c;使得数据保护的技术手段也要加速。 数据保护的重要性 数据是企业重要的生产资料&…