目录

一、缓存预热

二、缓存雪崩

三、缓存穿透

3.1、解决方案

3.1.1、空对象缓存或者缺省值

3.1.2、Goolge布隆过滤器Guava解决缓存穿透

四、缓存击穿

4.1、危害

4.2、解决方案

4.3、模拟百亿补贴活动案例

一、缓存预热

场景:MySQL有N条新记录,redis没有

1、MySQL做数据新增 ,redis利用回写机制,让它逐步实现100条新增记录的同步,部署发布版本的时候,自己人提前做一次redis同步。

2、通过中间件或者程序自行完成。

3、使用白名单

二、缓存雪崩

场景:

1、redis主机挂掉,redis全盘崩溃,偏硬件运维。

2、redis中有大量key同时过期大面积失效,偏软件开发。

预防和解决:

1、redis中key设置为永不过期或者过期时间错开

2、redis缓存集群实现高可用:①、主从+哨兵。②、redis集群。③、开启redis持久化机制aof/rdb,尽快恢复缓存集群。

3、多缓存结合预防雪崩:ehcache本地缓存+redis缓存。

4、服务降级:Hystrix或者阿里sentinel限流和降级

5、用钱购买阿里云---》云数据库redis。

三、缓存穿透

查询一条或N条数据,redis中没有,mysql中也没有,但请求每次都会去查询数据库,导致后台数据库压力暴增,就是缓存穿透。

3.1、解决方案

3.1.1、空对象缓存或者缺省值

 黑客或恶意攻击:

黑客会对系统进行攻击,拿一个不存在的id去查询数据,会产生大量的请求到数据库查询。可能会导致数据库压力大而宕掉。

key相同攻击系统:

第一次访问到MySQL,空对象缓存后第二次就返回defaultNull缺省值,避免MySQL被攻击,不用到数据库中去走一圈了。

key不同攻击系统:

由于存在空对象缓存和缓存回写,redis中的垃圾key会越写越多(设置key过期时间)。

3.1.2、Goolge布隆过滤器Guava解决缓存穿透

 白名单过滤器:

1、误判问题,概率小可以接受,不能从布隆过滤器中删除

2、全部合法的key都需要放入Guava版布隆过滤器+redis里面,不然数据就是返回null

 代码实现:

改pom

 <!--google开源guava--><dependency><groupId>com.google.guava</groupId><artifactId>guava</artifactId><version>23.0</version></dependency>

测试案例:

  /*** 创建Guava布隆过滤器测试*/@Testpublic void testGuavaAndBloomFilter(){//创建Guava布隆过滤器BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), 100);//判断指定的元素是否存在System.out.println(bloomFilter.mightContain(1));System.out.println(bloomFilter.mightContain(2));System.out.println("加入后");//将元素添加进布隆过滤器bloomFilter.put(1);bloomFilter.put(2);System.out.println(bloomFilter.mightContain(1));System.out.println(bloomFilter.mightContain(2));}

使用百万数据测试:

@Service
@Slf4j
public class GuavaBloomFilterServiceImpl implements GuavaBloomFilterService {public static final Integer  _1W = 10000;//定义guava布隆过滤器,初始容量public static final Integer  SIZE = 100 * _1W;//误判率,误判率越小误判个数越少public static double fpp = 0.03;//创建guava布隆过滤器private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), SIZE,fpp);@Overridepublic void guavaBloomFilter() {//在guava布隆过滤器加入一百万白名单数据for (int i = 0; i < SIZE; i++) {bloomFilter.put(i);}//取十万个不在合法范围的数据测试ArrayList<Integer> list = new ArrayList<>(10 * _1W);//测试for (int i = SIZE + 1; i < SIZE+(10 * _1W) ; i++) {//判断在guava布隆过滤器是否存在if (bloomFilter.mightContain(i)){log.info("被误判:{}",i);list.add(i);}}log.info("误判总数为:{}",list.size());}
}
@RestController
@Api(tags = "Google的guavaBloomFilter")
@Slf4j
public class GuavaBloomFilterController {@Autowiredprivate GuavaBloomFilterService guavaBloomFilterService;@RequestMapping(value = "/guavaBloomFilter",method = RequestMethod.GET)@ApiOperation("guava布隆过滤器插入100万样本数据和10万测试数据")public void guavaBloomFilter(){guavaBloomFilterService.guavaBloomFilter();}
}

结论 :100000 / 3033 = 0.03033

源码分析:

四、缓存击穿

大量的请求同时查询一个key时,而这个热点key正好失效,就会导致大量的请求都打到数据库上面去。

4.1、危害

会造成某一刻数据库请求量过大,压力剧增。

4.2、解决方案

 热点key失效的原因:

1、时间到了自然被清除但还是被访问到

2、删除的key,刚好被访问。

方案1:

差异失效时间,对于访问频繁的热点key,不设置过期时间。

方案2:

互斥更新,采用双检加锁策略。

4.3、模拟百亿补贴活动案例

@Data
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(value = "百亿补贴活动模拟")
public class Product {//商品idprivate Long id;//商品名private String name;//商品价格private Integer price;//商品描述private String detail;
}
@Service
@Slf4j
public class BYBTTaskServiceImpl implements BYBTTaskService {public static final String BYBT_KEY = "bybt";public static final String BYBT_KEY_A = "bybt:a";public static final String BYBT_KEY_B = "bybt:b";@Autowiredprivate RedisTemplate redisTemplate;/*** 模拟MySQL添加商品* @return*/public List<Product> getProductFromById(){List<Product> list = new ArrayList<>();for (int i = 1; i <= 20; i++) {Random random = new Random();int id = random.nextInt(1000);Product product = new Product((long) id, "product" + i, i, "鸽子蛋" + i);list.add(product);}return list;}
//    @PostConstructpublic void initBYBT(){log.info("启动定时器模拟百亿补贴活动开始。。。");//使用线程模拟定时任务,后台任务定时将MySQL里的活动商品刷新到redis中new Thread(()->{while (true){//从MySQL中查询数据,写入redisList<Product> list = this.getProductFromById();//删除过期keyredisTemplate.delete(BYBT_KEY);//使用redis的list数据结果存储最新数据redisTemplate.opsForList().leftPushAll(BYBT_KEY,list);//暂停2分钟模拟,模拟百亿补贴参加活动商品try {TimeUnit.MINUTES.sleep(2);} catch (InterruptedException e) {throw new RuntimeException(e);}}},"a1").start();}@PostConstructpublic void initBYBTAB(){log.info("启动AB定时器模拟百亿补贴活动开始。。。" + DateUtil.now());//使用线程模拟定时任务,后台任务定时将MySQL里的活动商品刷新到redis中new Thread(()->{while (true){//从MySQL中查询数据,写入redisList<Product> list = this.getProductFromById();//先更新缓存B,让缓存B过期时间超过缓存A,缓存A突然失效,还有缓存B,以防止缓存击穿redisTemplate.delete(BYBT_KEY_B);redisTemplate.opsForList().leftPushAll(BYBT_KEY_B,list);//设置过期时间redisTemplate.expire(BYBT_KEY_B,86410L,TimeUnit.SECONDS);//更新缓存AredisTemplate.delete(BYBT_KEY_A);redisTemplate.opsForList().leftPushAll(BYBT_KEY_A,list);//设置过期时间redisTemplate.expire(BYBT_KEY_A,86400L,TimeUnit.SECONDS);//暂停2分钟模拟,模拟百亿补贴参加活动商品try {TimeUnit.MINUTES.sleep(2);} catch (InterruptedException e) {throw new RuntimeException(e);}}},"a1").start();}
}
@RestController
@Slf4j
@Api(tags = "百亿补贴活动模拟")
public class BYBTTaskController {public static final String BYBT_KEY = "bybt";public static final String BYBT_KEY_A = "bybt:a";public static final String BYBT_KEY_B = "bybt:b";@Autowiredprivate RedisTemplate redisTemplate;/*** 分页查询,查询redis* @return*/@RequestMapping(value = "/findPage",method = RequestMethod.GET)@ApiOperation("查询商品,每次1页每页5条显示")public List<Product> findPage(int page,int size){List<Product> list =null;long start = (page - 1) * size;long end = start + size - 1;try {//使用redis的list里的lrange查询分页list = redisTemplate.opsForList().range(BYBT_KEY,start,end);if (CollectionUtils.isEmpty(list)){//查询为空就去mysql中查询return null;}log.info("参加活动商品:{}",list);} catch (Exception e) {//出现异常,一般redis出现事故log.error("bybt异常:{}",e);}return list;}@RequestMapping(value = "/findPageAB",method = RequestMethod.GET)@ApiOperation("双缓存查询商品,每次1页每页5条显示")public List<Product> findPageAB(int page,int size){List<Product> list =null;long start = (page - 1) * size;long end = start + size - 1;try {//先去缓存A中查找list = redisTemplate.opsForList().range(BYBT_KEY_A,start,end);if (CollectionUtils.isEmpty(list)){log.info("缓存A已失效,暂时采用缓存B");//若缓存A没有就去缓存B中查找list = redisTemplate.opsForList().range(BYBT_KEY_B,start,end);if (CollectionUtils.isEmpty(list)){//TODO 去MySQL查找return null;}}log.info("参加活动商品:{}",list);} catch (Exception e) {//出现异常,一般redis出现事故log.error("bybt异常:{}",e);e.printStackTrace();}return list;}
}

Java --- redis7之缓存预热+雪崩+穿透+击穿相关推荐

  1. 【redis】缓存预热雪崩穿透击穿

    [redis]缓存预热雪崩穿透击穿(上) 文章目录 [redis]缓存预热雪崩穿透击穿(上) 前言 一.面试题 二.缓存预热 三.缓存雪崩 发生原因 预防+解决 高可用: 多缓存结合: 人民币玩家 四 ...

  2. 缓存的雪崩,击穿,穿透

    缓存的雪崩,击穿,穿透 前言 在将今天的内容之前,我们先来了解一下什么是缓存,缓存是用来干什么的,常用的缓存有哪些? 什么是缓存 我们要知道缓存其实就是一个临时的存储器,那么缓存里的数据就不是持久化的 ...

  3. redis缓存的雪崩、击穿、穿透,淘汰策略,持久化

    1.redis缓存的雪崩.击穿.穿透,在实际中如何处理? 雪崩:缓存不存在,数据库存在,高并发,大量的key 原因:大量数据同时过期,Redis宕机 解决方案:给缓存数据的过期时间上加上小的随机数,避 ...

  4. 今天带你们走进缓存的雪崩、击穿、穿透基本概念

    在互联网时代,大流量.海量数据.高并发是每个企业都渴望又害怕的名词,渴望是因为它们代表着提供的服务用户愿意买单.有价值;害怕是因为一旦用户全上来了,系统不能正常为用户提供服务,让用户失望,最终选择离开 ...

  5. Redis 5.0.8+常见面试题(单线程还是多线程、先更新缓存还是数据库、雪崩穿透击穿解决办法...)

    Redis 6.0 保姆级教程(含微服务案例与完整面试题):https://www.yuque.com/yuxuandmbjz/redis Redis是单线程还是多线程 ?为什么这么设计 ? Redi ...

  6. 关于缓存雪崩\穿透\击穿等一些问题

    前言 设计一个缓存系统,不得不要考虑的问题就是:缓存穿透.缓存击穿与失效时的雪崩效应. 缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到 ...

  7. 缓存 雪崩 穿透 击穿

    缓存雪崩 原因:缓存雪崩是并发量过大带来的一系列的雪崩效应.大量的请求涌入缓存导致缓存无法处理挂掉,接着大量的请求会涌入数据库导致数据库挂掉. 分析:处理此问题的关键就是避免并发量大的时候缓存不要挂掉 ...

  8. 5redis-----------redis高级--GEO-查询附近的人、基数统计算法HLL 、布隆过滤器、缓存雪崩穿透击穿-------全栈式开发44

    redis高级 一.GEO查询附近的人 二.基数统计算法-HyperLogLog 三.布隆过滤器 四.缓存雪崩&缓存穿透 (一)缓存雪崩 (二)缓存穿透 (三)缓存击穿 一.GEO查询附近的人 ...

  9. 如何解决Redis缓存雪崩、击穿与穿透

    Redis最常用使用的场景就是作为业务系统的缓存,既然是作为缓存,那么就不免会碰到缓存常见的问题,即雪崩.击穿与穿透,什么是缓存雪崩.击穿与穿透以及如何解决这几个问题呢?今天我们一起来探讨一下! 一. ...

最新文章

  1. jpg在线合并jpg_JPG如何运作
  2. gcc a.c 究竟经历了什么
  3. 【扫盲】什么是FTP、FTPS 和 SFTP?
  4. PMCAFF | 从200块到300万,史上最全自媒体报价单
  5. 转载一个pythonA*实现
  6. 基于Python+Django+Mysql的图书管理系统
  7. 英魂之刃显示已将战斗服务器,英魂之刃战略版来袭,是挂名游戏还是搞事情?玩家:过于真实!...
  8. 【tf.keras.Model】构建模型小结(部分问题未解决)
  9. 服务器lsass状态代码c0000005,lsass.exe是什么进程?Win7系统提示Lsass.exe系统错误的原因及解决方法...
  10. 经典简约风格教师求职简历免费word模板
  11. 锻炼!!!!最佳时间!!!!希望大家都要记得锻炼身体!!!!
  12. 《数据结构》实验报告四:串的模式匹配(BF算法、KMP算法)
  13. 赵小楼《天道》《遥远的救世主》解读(1)怎么评价《遥远的救世主》《天幕红尘》这两本书和《天道》这部电视剧?
  14. 前端基础之CSS标签样式
  15. windows找不到文件请确定文件名是否正确怎么办?
  16. 专门画像素图的软件_有哪几种简便的做像素画的软件?
  17. linkcloud:KVM虚拟化渐趋成熟 可与XEN和Vmware比肩
  18. 机器学习导论:什么是机器学习?
  19. 漏洞复现 用友畅捷通T+任意文件上传漏洞(CNVD-2022-60632)
  20. 10个基于python的的BBS论坛的源码

热门文章

  1. PHP等级水平评定标准
  2. 力科示波器截屏功能 python代码实现
  3. php di 使用,PHP - DI 的使用
  4. esxi管理端口_ESXI 6.7修改网页端口号
  5. Flink 源码解析 —— 源码编译运行
  6. IPVS的OPS调度
  7. sql注入原理及危害
  8. couldn’t be completed. (LaunchServicesError error 0.)
  9. 游龙传说服务器维护,发家致富全靠维护 炉石传说超长维护事件回顾
  10. 预测赢家_新敏捷—赢家