分布式锁的应用实例

解决缓存击穿问题

当我们将数据放在缓存中,每次查询先访问缓存,如果缓存中有数据,就直接返回数据,如果没有,就去数据库里面查询,查询之后将数据添加到缓存中。但是每次缓存中的数据都会设置过期时间,如果刚刚好数据过期的数据,高并发情况发生了,假如这是有1W的并发量同时访问,那么就会发生这些请求直接访问数据库,给数据库造成一定的压力,甚至数据库服务崩掉,这就是缓存击穿的问题
在高并发下,多线程同时查询同一个资源,如果缓存中没有这个资源,那么这些线程都会去数据库查找,对数据库造成极大压力,缓存失去存在的意义

缓存穿透:在高并发下,多线程同时查询同一个不存在的资源,这个资源数据库里不存在,缓存里肯定也是不存在的,如果这样的话,也是缓存击穿问题

下面我们来写一些伪代码,演示一下:

正常逻辑:
public Object getOrder(Long id){
    //先查询redis
    Order order = redisClient.get(id);
    //redis命中
    if(order != null){
        return order;
    }
    try{
         //查询数据库
        Order order = orderService.getOrderById(id);
        if(order != null){
            //查询到的数据添加到redis
            redisClient.set(id,order);
            return order;
        }
    } catch (Exception e){
            e.printStackTrace();
    }
}

上述代码就有可能出现缓存击穿问题,接下来我们来预防一下,使用我之前写的文章中的redis分布式锁

修改后逻辑:
public Object getOrder(Long id){
    //先查询redis缓存
    Order order = redisClient.get(id);
    //redis命中
    if(order != null){
        return order;
    }
    try{
        //添加redis分布式锁
        redisLock.lock(id);
        //先查询redis缓存
        Order order = redisClient.get(id);
        //redis命中
        if(order != null){
            return order;
        }
         //查询数据库
        Order order = orderService.getOrderById(id);
        if(order != null){
            //查询到的数据添加到redis
            redisClient.set(id,order);
            return order;
        }
    } catch (Exception e){
            e.printStackTrace();
    } finally {
          redisLock.unlock(id);
    }
}

上面的代码就是改造过的,添加了分布式锁。
当缓存中的数据失效之后,如果这是出现大量的并发情况,就可以使用redis分布式锁解决了。因为当缓存数据失效后,多线程并发过来时,第一个请求会获取锁,然后只有一个请求去查询数据库,查询结束后,将数据添加到缓存,这时候释放锁,其他请求获取锁之后,先查询缓存,这是缓存中已经有数据了,就避免了去查询数据库了。这时无论多少的并发量都没关系啦,因为这时就可以从缓存中查询数据了。。。

解决缓存击穿问题可以参考文章
缓存穿透、缓存雪崩、缓存击穿

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 今天看到一位朋友写的mysql笔记总结,觉得写的很详细很用心,这里转载一下,供大家参考下,也希望大家能关注他原文地...
    信仰与初衷阅读 4,769评论 0 30
  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 5,498评论 0 9
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,174评论 1 32
  • 如未做特殊说明,本文均为原创,转载请注明出处。 [TOC] 前言为什么要使用分布式锁呢? 在Nginx实现负载均衡...
    小安的大情调阅读 3,981评论 0 10
  • 最近碰到几个业务场景,会遇到并发的问题。在单实例情况下,我们会通过java.util.concurrent包...
    菜鸟小玄阅读 2,282评论 0 5