分布式锁的应用实例

2019-08-20  本文已影响0人  初心myp

解决缓存击穿问题

当我们将数据放在缓存中,每次查询先访问缓存,如果缓存中有数据,就直接返回数据,如果没有,就去数据库里面查询,查询之后将数据添加到缓存中。但是每次缓存中的数据都会设置过期时间,如果刚刚好数据过期的数据,高并发情况发生了,假如这是有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分布式锁解决了。因为当缓存数据失效后,多线程并发过来时,第一个请求会获取锁,然后只有一个请求去查询数据库,查询结束后,将数据添加到缓存,这时候释放锁,其他请求获取锁之后,先查询缓存,这是缓存中已经有数据了,就避免了去查询数据库了。这时无论多少的并发量都没关系啦,因为这时就可以从缓存中查询数据了。。。

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

上一篇 下一篇

猜你喜欢

热点阅读