首页 > 其他分享 >利用互斥锁解决缓存击穿问题

利用互斥锁解决缓存击穿问题

时间:2022-11-27 12:11:53浏览次数:36  
标签:缓存 击穿 查询 互斥 线程 key stringRedisTemplate

核心思路:相较于原来从缓存中查询不到数据后直接查询数据库而言,现在的方案是 进行查询之后,如果从缓存没有查询到数据,则进行互斥锁的获取,获取互斥锁后,判断是否获得到了锁,如果没有获得到,则休眠,过一会再进行尝试,直到获取到锁为止,才能进行查询

如果获取到了锁的线程,再去进行查询,查询后将数据写入redis,再释放锁,返回数据,利用互斥锁就能保证只有一个线程去执行操作数据库的逻辑,防止缓存击穿

 

 

 

 

 

 

 

 

 

 

 

 

 

操作锁的代码:

核心思路就是利用redis的setnx方法来表示获取锁,该方法含义是redis中如果没有这个key,则插入成功,返回1,在stringRedisTemplate中返回true, 如果有这个key则插入失败,则返回0,在stringRedisTemplate返回false,我们可以通过true,或者是false,来表示是否有线程成功插入key,成功插入的key的线程我们认为他就是获得到锁的线程。

简易版: 设置过期时间防止死锁

 private boolean tryLock(String key) {
        Boolean flag = stringRedisTemplate.opsForValue().setIfAbsent(key, "1", 10, TimeUnit.SECONDS);
        return BooleanUtil.isTrue(flag);
    }

    private void unlock(String key) {
        stringRedisTemplate.delete(key);
    }

思考: 释放锁的时候,没有判断释放的是不是自己的锁,最终会导致锁失效。

如何标识是自己的锁呢? 我们在执行相关命令时,都使用了主线程,那么主线程ID是一直跟随,将主线程ID融合进去。

   public boolean tryLock(long timeoutSec) {
       //获取主线程标识
        String threadId = ID_PREFIX + Thread.currentThread().getId();
        // 获取锁
        Boolean success = stringRedisTemplate.opsForValue()
                .setIfAbsent(KEY_PREFIX + name, threadId, timeoutSec, TimeUnit.SECONDS);
        return Boolean.TRUE.equals(success);
    }

锁释放的时候,要保证缓存已经重建完成了, 如何保证呢

 

标签:缓存,击穿,查询,互斥,线程,key,stringRedisTemplate
From: https://www.cnblogs.com/kisshappyboy/p/16929409.html

相关文章

  • 缓存雪崩和击穿问题及解决思路
    缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。解决方案:给不同的Key的TTL添加随机值        ......
  • 缓存穿透问题的解决思路
    缓存穿透:缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库。常见的解决方案有两种:缓存空对象优点:实现简单,维......
  • 缓存更新策略
    缓存更新是redis为了节约内存而设计出来的一个东西,主要是因为内存数据宝贵,当我们向redis插入太多数据,此时就可能会导致缓存中的数据过多,所以redis会对部分数据进行更新,或者......
  • 为商户添加redis缓存
    缓存模型和思路标准的操作方式就是查询数据库之前先查询缓存,如果缓存数据存在,则直接从缓存中返回,如果缓存数据不存在,再查询数据库,然后将数据存入redis。  代码如下:......
  • 什么是缓存
    1.浏览器层缓存缓存一些静态页面等2.应用缓存将部分数据存入map,来访问时直接将map里的数据返给你。3.  缓存(Cache),就是数据交换的缓冲区,俗称的缓存就是缓冲区......
  • spring三级缓存
    IOC容器中的bean是单例的bean生命周期 什么是循环依赖    什么是成品对象和半成品对象   解决循环依赖方式  spring中使用三个map来表示三级缓......
  • HTTP缓存
    浏览器、缓存服务器、源服务器   浏览器:资源请求直接发起方。   源服务器:资源实际提供方。   缓存服务器:在浏览器、源服务器之间架设的中间服务器,由它代替浏览......
  • redis缓存击穿、缓存穿透、缓存雪崩
    redis缓存穿透、缓存击穿、缓存雪崩​ 在我们日常的开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问......
  • 【Azure Redis 缓存】在Azure Redis中,如何限制只允许Azure App Service访问?
    问题描述在AzureRedis服务中,如何实现只允许AzureAppService访问呢? 问题解答AzureRedis开启防火墙的功能,并在防火墙中添加上AppService的出口IP地址即可。两步即可实......
  • Redis — 缓存方案
    1Redis—缓存方案(热数据和冷数据)1.1 新建和更新数据时,设置一个过期时间product_cache_timeout(比如24小时),查询时同时也将过期时间setinredis缓存1.2查到数据时重......