首页 > 其他分享 >逻辑过期解决缓存击穿问题

逻辑过期解决缓存击穿问题

时间:2022-11-27 21:22:15浏览次数:35  
标签:shop 缓存 过期 redis 击穿 线程 id

需求:修改根据id查询商铺的业务,基于逻辑过期方式来解决缓存击穿问题

思路分析:当用户开始查询redis时,判断是否命中,如果没有命中则直接返回空数据,不查询数据库,而一旦命中后,将value取出,判断value中的过期时间是否满足,如果没有过期,则直接返回redis中的数据,如果过期,则在开启独立线程后直接返回之前的数据,独立线程去重构数据,重构完成后释放互斥锁。

 

 这么做需要保证shop全部都在缓存中且不再变动,因为缓存查不到直接就返回了

如何封装数据:因为现在redis中存储的数据的value需要带上过期时间,此时要么你去修改原来的实体类,要么你继承之前的数据

@Data
public class RedisData {
    private LocalDateTime expireTime;
    private Object data;
}

正式代码: 创建一个单独的线程去更新缓存。不要直接建立,而是使用线程池,避免重复建立和销毁线程造成资源浪费

private static final ExecutorService CACHE_REBUILD_EXECUTOR = Executors.newFixedThreadPool(10);
public Shop queryWithLogicalExpire( Long id ) {
    String key = CACHE_SHOP_KEY + 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);
    Shop shop = JSONUtil.toBean((JSONObject) redisData.getData(), Shop.class);
    LocalDateTime expireTime = redisData.getExpireTime();
    // 5.判断是否过期
    if(expireTime.isAfter(LocalDateTime.now())) {
        // 5.1.未过期,直接返回店铺信息
        return shop;
    }
    // 5.2.已过期,需要缓存重建
    // 6.缓存重建
    // 6.1.获取互斥锁
    String lockKey = LOCK_SHOP_KEY + id;
    boolean isLock = tryLock(lockKey);
    // 6.2.判断是否获取锁成功
    if (isLock){
        CACHE_REBUILD_EXECUTOR.submit( ()->{

            try{
                //重建缓存
                this.saveShop2Redis(id,20L);
            }catch (Exception e){
                throw new RuntimeException(e);
            }finally {
                unlock(lockKey);
            }
        });
    }
    // 6.4.返回过期的商铺信息
    return shop;
}

 

标签:shop,缓存,过期,redis,击穿,线程,id
From: https://www.cnblogs.com/kisshappyboy/p/16930712.html

相关文章

  • .NET6之MiniAPI(十七):缓存
    缓存是空间换时间的一种做法,可以有效的提升响应时间,asp.netcore引入了本地内存缓存和分布式缓存。先看一下本地内存缓存:usingMicrosoft.Extensions.Caching.M......
  • .NET6之MiniAPI(十七):缓存
    缓存是空间换时间的一种做法,可以有效的提升响应时间,asp.netcore引入了本地内存缓存和分布式缓存。先看一下本地内存缓存:usingMicrosoft.Extensions.Caching.M......
  • 利用互斥锁解决缓存击穿问题
    核心思路:相较于原来从缓存中查询不到数据后直接查询数据库而言,现在的方案是进行查询之后,如果从缓存没有查询到数据,则进行互斥锁的获取,获取互斥锁后,判断是否获得到了锁,如果......
  • 缓存雪崩和击穿问题及解决思路
    缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。解决方案:给不同的Key的TTL添加随机值        ......
  • 设置cookies过期时间的几种方法
     默认cookies失效时间是直到关闭浏览器,cookies失效,也可以指定cookies时间。Response.Cookies("user_name").Expires=Date+1'指定cookie保存时间保留COOKIES一个小时R......
  • 缓存穿透问题的解决思路
    缓存穿透:缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。常见的解决方案有两种:缓存空对象优点:实现简单,维......
  • 缓存更新策略
    缓存更新是redis为了节约内存而设计出来的一个东西,主要是因为内存数据宝贵,当我们向redis插入太多数据,此时就可能会导致缓存中的数据过多,所以redis会对部分数据进行更新,或者......
  • 为商户添加redis缓存
    缓存模型和思路标准的操作方式就是查询数据库之前先查询缓存,如果缓存数据存在,则直接从缓存中返回,如果缓存数据不存在,再查询数据库,然后将数据存入redis。  代码如下:......
  • 什么是缓存
    1.浏览器层缓存缓存一些静态页面等2.应用缓存将部分数据存入map,来访问时直接将map里的数据返给你。3.  缓存(Cache),就是数据交换的缓冲区,俗称的缓存就是缓冲区......
  • spring三级缓存
    IOC容器中的bean是单例的bean生命周期 什么是循环依赖    什么是成品对象和半成品对象   解决循环依赖方式  spring中使用三个map来表示三级缓......