一、使用场景

  我们在日常的开发中,经常会遇到查询数据列表的问题,有些数据是不经常变化的,如果想做一下优化,在提高查询的速度的同时减轻数据库的压力,那么redis缓存绝对是一个好的解决方案。

二、需求

  假设有10000个请求,想达到第一次请求从数据库中获取,其他9999个请求从redis中获取这种效果。

三、代码实现

3.1、常规写法

public List<UsersDO> getAllUserWithNoPage2(){try{//序列化器,将key的值设置为字符串RedisSerializer redisSerializer=new StringRedisSerializer();redisTemplate.setKeySerializer(redisSerializer);//查缓存List<UsersDO> list=(List<UsersDO>)redisTemplate.opsForValue().get("allUsers");if(null==list){UsersQuery query=new UsersQuery();list=usersDOMapper.selectByExample(query);redisTemplate.opsForValue().set("allUsers", list);System.out.println("从数据库中取数据");}else{System.out.println("从缓存中取数据");}return list;}catch (Exception e) {logger.error("UserService.getAllUserWithNoPage error",e);}return null;}

  常规的这种写法单线程没有问题,但是考虑到并发的存在,就会出现缓存渗透的问题,也就是不能保证其他9999个请求都是从redis中取。

3.2、常规写法压测

@GetMapping(value = "/test2")public String  test2(){ExecutorService executorService= Executors.newFixedThreadPool(20);for(int i=1 ; i<=10000;i++){executorService.submit(new Runnable() {@Overridepublic void run() {userService.getAllUserWithNoPage2();}});}return "test over";}

3.3、常规写法压测结果

3.4、常规写法的改进,使用双重检测锁

public List<UsersDO> getAllUserWithNoPage(){try{//序列化器,将key的值设置为字符串RedisSerializer redisSerializer=new StringRedisSerializer();redisTemplate.setKeySerializer(redisSerializer);//查缓存List<UsersDO> list=(List<UsersDO>)redisTemplate.opsForValue().get("allUsers");if(null==list){//双重检测 锁synchronized (this) {List<UsersDO> list1 = (List<UsersDO>) redisTemplate.opsForValue().get("allUsers");if (null == list1) {UsersQuery query=new UsersQuery();list=usersDOMapper.selectByExample(query);redisTemplate.opsForValue().set("allUsers", list);System.out.println("从数据库中取数据");}else{System.out.println("从缓存中取数据");}}}else{System.out.println("从缓存中取数据");}return list;}catch (Exception e) {logger.error("UserService.getAllUserWithNoPage error",e);}return null;}

3.5、双重检测锁压测

@GetMapping(value = "/test")public String  test(){ExecutorService executorService= Executors.newFixedThreadPool(20);for(int i=1 ; i<=10000;i++){executorService.submit(new Runnable() {@Overridepublic void run() {userService.getAllUserWithNoPage();}});}return "test over";}

3.6、双重检测锁压测结果

压测结果符合要求。

完整代码已上传Github :传送门

转载于:https://www.cnblogs.com/geekdc/p/9256515.html

高并发下redis缓存穿透问题解决方案相关推荐

  1. 【redis】redis缓存穿透及解决方案|缓存穿透,缓存击穿,雪崩的理解

    |目录 缓存穿透 解决方案 布隆过滤 缓存空对象 缓存雪崩 解决方案 1.保证缓存层服务高可用性 2.依赖隔离组件为后端限流并降级 3.数据预热 4.做二级缓存,或者双缓存策略. 5.缓存永远不过期 ...

  2. Redis缓存穿透与解决方案

    什么是缓存穿透? 要查询的key在redis中不存在,对应的id(对应的值)在数据库中也不存在,此时被非法用户攻击,大量的请求直接打到db上,造成db宕机,从而影响整个系统.这就种现象就称之为缓存穿透 ...

  3. Redis缓存穿透、击穿、雪崩及主从复制

    文章目录 Redis缓存穿透 概念 解决方案1-布隆过滤器 解决方案2-缓存空对象 缓存击穿 概念 解决方案1-热点数据永不过期 解决方案2-加互斥锁 缓存雪崩 概念 解决方案1-Redis高可用 解 ...

  4. Redis 缓存穿透、缓存击穿和缓存雪崩

    目录 Redis 缓存穿透.缓存击穿和缓存雪崩 Redis 缓存穿透(查不到) Redis缓存穿透的解决方案 方案一:接口校验 方案二:缓存空对象 方案三:布隆过滤器 Redis 缓存击穿 Redis ...

  5. Redis缓存穿透,缓存击穿,缓存雪崩原因以及解决方案

    一.前言 在我们日常的开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者是 ...

  6. Redis缓存穿透 缓存击穿 缓存雪崩原因及其解决方案

    解决缓存穿透 方法一:布隆过滤器:将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力. 方法二:如果一个查询返回 ...

  7. redis缓存穿透问题及解决方案代码实现

    1.定义及解决方案 缓存穿透 :缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库. 常见的解决方案有两种: 缓存空对象 优点:实现简单,维护方便 缺 ...

  8. Redis缓存穿透问题及解决方案

    Redis缓存穿透问题及解决方案 参考文章: (1)Redis缓存穿透问题及解决方案 (2)https://www.cnblogs.com/lingyejun/p/10087135.html 备忘一下 ...

  9. redis缓存穿透,缓存击穿,缓存雪崩原因和解决方案

    redis缓存穿透,缓存击穿,缓存雪崩原因和解决方案 参考文章: (1)redis缓存穿透,缓存击穿,缓存雪崩原因和解决方案 (2)https://www.cnblogs.com/shisuiliun ...

最新文章

  1. Android NDK开发之旅31 FFmpeg音频解码
  2. C#获取当前日期时间(转)
  3. Node.js 目录操作
  4. python包括哪些部分_python基础知识部分练习大全
  5. 【STM32】 keil新建工程模板
  6. IDEA新建maven项目漏掉webapp目录解决方法
  7. VMware虚拟机下安装Ubuntu16.04镜像完整教程
  8. tab vue 竖排_vue 实现tab切换保持数据状态
  9. c 连接mysql数据库_C++连接mysql数据库的两种方法
  10. android酷狗音乐播放器,酷狗音乐app官方下载
  11. php hprose扩展1.5.5,Laravel框架RPC解决方案--Hprose
  12. (分层图)洛谷P4568[JLOI2011]飞行路线
  13. 华为USG防火墙恢复密码步骤
  14. java epics_Visual Paradigm敏捷开发教程(7):如何管理Epics
  15. ERP“创建会计科目”的请求数据量过大报黄
  16. ArcGIS API for JavaScript 图层顺序
  17. matlab 蒙特卡罗计算pi值
  18. 如何部署超级签名分发平台系统?
  19. win10 C语言开发环境搭建
  20. Jmeter+InfluxDB+Grafana+Prometheus搭建遇过的问题

热门文章

  1. 科研找到属于自己的思想
  2. 远控软件VNC***案例研究
  3. smartbits的国产版本minismb-如何测试路由器
  4. SpringBoot系列三:SpringBoot基本概念(统一父 pom 管理、SpringBoot 代码测试、启动注解分析、配置访问路径、使用内置对象、项目打包发布)...
  5. KVM虚拟机添加虚拟磁盘
  6. Navicat Essentials 功能简介
  7. Innosetup(pascal)标签控件label换行
  8. Gson.toJson()时内存溢出StackOverflowError
  9. 2、程序包 Packages
  10. C#实现动态桌面背景图片切换