当前位置: 首页 > news >正文

Redis:缓存击穿

缓存击穿(热点key): 部分key(被高并发访问且缓存重建业务复杂的)失效,无数请求会直接到数据库,造成巨大压力

1.互斥锁:可以保证强一致性

      线程一:未命中之后,获取互斥锁,再查询数据库重建缓存,写入缓存,释放锁

      线程二:查询未命中,未获得锁(已由线程一获得),等待一会,缓存命中

互斥锁实现方式:redis中setnx key value:改变对应key的value,仅当value不存在时执行,以此来实现互斥锁,防止出现锁得不到释放,设置有效期

public Shop queryWithMutex(Long id) throws InterruptedException {Shop shop;//实现互斥锁,解决缓存击穿String key=CACHE_SHOP_KEY+id;//1.从redis查询商铺缓存String shopJson=stringRedisTemplate.opsForValue().get(key);//2.判断是否存在,isNotBlank("")也为falseif(StrUtil.isNotBlank(shopJson)){//3.存在,返回商铺对象return JSONUtil.toBean(shopJson,Shop.class);}//判断命中的是否为空值if(shopJson != null && shopJson.isEmpty()){return null;}//4.实现缓存重建String lockKey=LOCK_SHOP_KEY+id;//4.1.获取互斥锁boolean isLock=tryLock("lockKey");//4.2.判断互斥锁是否成功if(!isLock){//4.3.未成功,等待Thread.sleep(50);//递归shop=queryWithMutex(id);}else{//4.4.成功,从mysql数据库中查询shop=getById(id);//5.判断是否存在if(shop==null){//缓存空值,处理缓存穿透stringRedisTemplate.opsForValue().set(key,"",CACHE_NULL_TTL,TimeUnit.MINUTES);return null;}//6.存在,向redis中缓存店铺数据stringRedisTemplate.opsForValue().set(key,JSONUtil.toJsonStr(shop),LOGIN_USER_TTL, TimeUnit.MINUTES);//7.释放互斥锁unlock(lockKey);}//8.返回return shop;}

2.逻辑过期:

      不存TTL,添加上逻辑过期时间,判断逻辑上有没有过期,以此来更新数据

      线程一:查询缓存,逻辑已过期,获取互斥锁,开启新线程,返回过期数据

               新线程:查询数据库并重建缓存,重置逻辑过期时间,释放锁

      线程二:查询未命中,未获得锁(已由线程一获得),返回过期数据

 private boolean tryLock(String key){//尝试获得互斥锁Boolean flag=stringRedisTemplate.opsForValue().setIfAbsent("key","1",LOCK_SHOP_TTL,TimeUnit.SECONDS);return BooleanUtil.isTrue(flag);//通过工具类将其转化为基本类型}private void unlock(String key){//删除锁stringRedisTemplate.delete("key");}

实现互斥锁相关的方法

//线程池,有10个线程private static final ExecutorService CACHE_REBUILD_EXECUTOR= Executors.newFixedThreadPool(10);

创建线程池

public Shop queryWithLogicalExpire(Long id) {//实现逻辑过期,解决缓存击穿(不存在缓存穿透问题)String key=CACHE_SHOP_KEY+id;String lockKey=LOCK_SHOP_KEY+id;//1.从redis查询商铺缓存String shopJson=stringRedisTemplate.opsForValue().get(key);//2.判断是否存在if(StrUtil.isBlank(shopJson)){//3.不存在,返回nullreturn null;}//4.存在,判断是否过期//将Json反序列化成RedisDate对象RedisData redisData=JSONUtil.toBean(shopJson,RedisData.class);Shop shop=JSONUtil.toBean((JSONObject)redisData.getData(),Shop.class);//5.过期if(LocalDateTime.now().isAfter(redisData.getExpireTime())){//6.缓存重建//6.1.获取互斥锁boolean isLock=tryLock(lockKey);//6.2.获取成功if(isLock){//开启新线程CACHE_REBUILD_EXECUTOR.submit(()->{try {saveShopToRedis(id, 20L);}catch(Exception e){throw new RuntimeException(e);}finally {//释放锁unlock(lockKey);}});}//6.3.获取失败return shop;}return shop;}

逻辑删除相关方法

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 低空经济新概念
  • 1 Linux SSH安全加固_linux system-auth
  • HTML 基础,尚优选网站设计开发(二)
  • 数据结构应用实例(四)——最小生成树
  • 新能源汽车出海中的数据合规热点问题
  • UE5 半透明阴影 快速解决方案
  • tensorrt 下载地址
  • 解锁Web3.0——Scaffold-eth打造以太坊DApp的终极指南
  • 散户怎么在大A炒股挣钱?
  • JAVA基础:抽象类,接口,instanceof,类关系,克隆
  • APSME 2025 亚洲国际功率半导体、材料及装备技术展览会
  • Netty中用到了哪些设计模式
  • 【数据结构】详解二叉搜索树及其实现
  • TOP 100 AI应用,字节跳动独占6个!
  • 分类预测|基于雪消融优化BP神经网络的数据分类预测Matlab程序SAO-BP 多特征输入多类别输出 含基础程序
  • 【译】JS基础算法脚本:字符串结尾
  • ES6指北【2】—— 箭头函数
  • CentOS学习笔记 - 12. Nginx搭建Centos7.5远程repo
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • GraphQL学习过程应该是这样的
  • Java 网络编程(2):UDP 的使用
  • spring boot 整合mybatis 无法输出sql的问题
  • ViewService——一种保证客户端与服务端同步的方法
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • 从零搭建Koa2 Server
  • 理解在java “”i=i++;”所发生的事情
  • 浅谈Kotlin实战篇之自定义View图片圆角简单应用(一)
  • 如何解决微信端直接跳WAP端
  • 跳前端坑前,先看看这个!!
  • 线性表及其算法(java实现)
  • 硬币翻转问题,区间操作
  • 再谈express与koa的对比
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • # centos7下FFmpeg环境部署记录
  • # 利刃出鞘_Tomcat 核心原理解析(七)
  • # 执行时间 统计mysql_一文说尽 MySQL 优化原理
  • (2)从源码角度聊聊Jetpack Navigator的工作流程
  • (C++)八皇后问题
  • (NSDate) 时间 (time )比较
  • (分布式缓存)Redis持久化
  • (附源码)spring boot车辆管理系统 毕业设计 031034
  • (附源码)springboot优课在线教学系统 毕业设计 081251
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (三)c52学习之旅-点亮LED灯
  • (三)SvelteKit教程:layout 文件
  • (十八)三元表达式和列表解析
  • (十七)Flink 容错机制
  • (转)Android学习系列(31)--App自动化之使用Ant编译项目多渠道打包
  • .Net Core和.Net Standard直观理解
  • .net wcf memory gates checking failed
  • .NET 动态调用WebService + WSE + UsernameToken
  • .NET 简介:跨平台、开源、高性能的开发平台
  • .NET框架类在ASP.NET中的使用(2) ——QA
  • .Net转Java自学之路—SpringMVC框架篇六(异常处理)