有图有真相的QQ资源、网赚教程分享,高质量的网络教程和软件下载
保存到桌面加入收藏设为首页
冷牛教程网
当前位置:首页 > 技术文章 > Redis

如何避免缓存击穿 Java主从轮询解决方案

2021-07-20 00:51:17   管理员      2691  

  当网站一瞬间有大量的用户去请求redis key的时候,恰好这个key已经被删除或者过期,这个时候就都会请求到数据库,导致数据库压力增大瘫痪。(注意:缓存击穿是redis中没有这个数据,但是数据库中有,和缓存穿透要区别)

  解决方案:

  设置AB定时器,主从轮询原理去解决

  定时器更新原理
  开辟2块缓存,A 和 B,定时器在更新缓存的时候,先更新B缓存,然后再更新A缓存,记得要按这个顺序。
  查询原理
  用户先查询缓存A,如果缓存A查询不到(例如,更新缓存的时候删除了),再查下缓存B
  以上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;
}



上一篇:布隆过滤器(Bloom Filter)的原理和实现
下一篇:没有了
相关评论
冷牛网络 2015-2021 版权所有  豫ICP备2021000561号-1