redis分布式缓存(二十八)一一缓存击穿解决方案什么是

什么是缓存击穿

在高并发的系统中,大量的请求同时查询一个key时,如果这个key正好失效或删除,就会导致大量的请求都请求到数据库,导致数据库扛不住这种高并发流量,卡顿甚至死机。这种现象我们称为缓存击穿

QPS

key失效或更新

客户端请求

缓存

DB

如何解决缓存击穿的问题?

针对这种定时更新缓存的特定场景,解决缓存击穿一般是采用主从轮询的原理。

  • 定时器更新原理

开辟2块缓存,A 和 B,定时器在更新缓存的时候,先更新B(主)缓存,然后再更新A缓存(从),记得要按这个顺序。

1先更新

2后更新

定时更新

主缓存B

从缓存A

  • 查询原理

用户先查询缓存A(从),如果缓存A查询不到(例如,更新缓存的时候删除了),再查询缓存B(主)

不存在

存在

存在

不存在

客户端

从缓存A

主缓存B

返回结果

DB

以上2个步骤,由原来的一块缓存,开辟出2块缓存,最终解决了缓存击穿的问题

实战:主从轮询

@PostConstruct
public void initJHSAB(){
    log.info("启动AB定时器..........");
    new Thread(()->runJhsAB()).start();
}
复制代码
public void runJhsAB() {
    while (true){
        //模拟从数据库读取100件 特价商品,用于加载到聚划算页面
        List<Product> list=this.products();
        //先更新B:先删除再更新
        this.redisTemplate.delete(Constants.JHS_KEY_B);
        this.redisTemplate.opsForList().leftPushAll(Constants.JHS_KEY_B,list);

        //再更新A:先删除再更新
        this.redisTemplate.delete(Constants.JHS_KEY_A);
        this.redisTemplate.opsForList().leftPushAll(Constants.JHS_KEY_A,list);
        try {
            Thread.sleep(1000*60);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.info("重新刷新..............");
    }
}
复制代码
@GetMapping(value = "/findAB")
public List<Product> findAB(int page, int size) {
    List<Product> list=null;
    long start = (page - 1) * size;
    long end = start + size - 1;
    try {
        //采用redis,list数据结构的lrange命令实现分页查询。
        list = this.redisTemplate.opsForList().range(Constants.JHS_KEY_A, start, end);
        //用户先查询缓存A,如果缓存A查询不到(例如,更新缓存的时候删除了),再查下缓存B
        if (CollectionUtils.isEmpty(list)) {
            this.redisTemplate.opsForList().range(Constants.JHS_KEY_B, start, end);
        }
        log.info("{}", list);
    } catch (Exception ex) {
        //这里的异常,一般是redis瘫痪 ,或 redis网络timeout
        log.error("exception:", ex);
        //TODO 走DB查询
    }
    return list;
}
复制代码

注意:主从轮询延时双删是不一样场景,延时双删是解决双写一致性方案。

redis分布式缓存系列文章

上一章节: redis分布式缓存(二十七)一一 淘宝聚划算商品列表解决方案

  • 👍🏻:有收获的,点赞鼓励!
  • ❤️:收藏文章,方便回看!
  • 💬:评论交流,互相进步!