0


Redis——如何解决redis穿透、雪崩、击穿问题

目录

一、查询商品信息的常规代码示例

  • 查询商品信息的常规代码示例
/**
*查询商品信息
*/publicExpressInfofindByDeliveryOrderId(Long id){String key="xz-express:expmess-info:"//从 Redis查询物流信息Object obj =     redisTemplate.opsForValue().get( key + id);if(obi !=null)[return(ExpressInfo) obj;}else{ExpressInfo expressInfo= expressMapper,selectByDeliveryOrderId(id);//数据库查询    if(expressInfo l= nul1){ 
            redisTemplate,opsForValue(),set(key + d,expressInfo,Duration,ofHours(2));return expressInfo;}else{thrownewclientException("发货单,的物流信息不存在",id);}}}

二、缓存击穿

2.1、缓存击穿的理解

  • 高并发时,当一个kev非常热点(类似于爆款)在不停的扛着大并发当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库并设置到缓存中,导致性能下降。在这里插入图片描述

2.2、缓存击穿的解决方案

  • 设置缓存永不过期
  • 加锁排队

2.3、解决缓存击穿的代码示例

  • 代码示例/***查询商品信息*/@Suppresswarnings("unchecked”)publicExpressInfofindByDeliveryOrderId(Long id){String key="xz-express:expmess-info:"//从 Redis查询物流信息Object obj = redisTemplate.opsForValue().get( key + id);if(obi ==null){synchronized(this){//进入 synchronized 一定要先再查询一次 Redis,防止上一个抢到锁的线程已经更新过了 obj = redisTemplate.opsForValue().get( key + id);if(obj !=null){return(List<ProductCategory>) obj;}//数据库查询 List<ProductCategory> categorylList = productCategoryMapper.selectProductCategory(id); redisTemplate,opsForValue().set(key,categoryList,Duration.ofHours(2L));}return categorylList ;}else{return(List<ProductCategory>) obj;}}

三、缓存雪崩

3.1、缓存雪崩的理解

  • 缓存集中过期,或者缓存服务器宕机,导致大量请求访问数据库,造成数据库瞬间压力过大,宕机。在这里插入图片描述

3.2、缓存雪崩的解决方案

3.2.1、缓存集中过期的情况

  • 加锁排队
  • 设置随机失效时间

3.2.2、缓存服务器宕机的情况

  • 提前部署好redis高可用集群(比如哨兵模式)

3.2.3、缓存服务器断电的情况

  • 提前做好灾备(多机房部署)

3.3、解决缓存雪崩(缓存集中过期)的代码示例

  • 代码示例/***查询商品信息*/@Suppresswarnings("unchecked”)publicExpressInfofindByDeliveryOrderId(Long id){String key="xz-express:expmess-info:"//从 Redis查询物流信息Object obj = redisTemplate.opsForValue().get( key + id);if(obi ==null){synchronized(this){//进入 synchronized 一定要先再查询一次 Redis,防止上一个抢到锁的线程已经更新过了 obj = redisTemplate.opsForValue().get( key + id);if(obj !=null){return(List<ProductCategory>) obj;}//数据库查询 List<ProductCategory> categorylList = productCategoryMapper.selectProductCategory(id);//设置随机失效时间Duration expire =DurationofHours(2L).plus(Duration.ofSeconds((Math.random()100))); redisTemplate,opsForValue().set(key,categoryList,expire);}return categorylList ;}else{return(List<ProductCategory>) obj;}}

四、缓存穿透

4.1、缓存穿透的理解

  • 数据库不存在缓存中也不存在,导致每次请求都会去查询数据库,这时的用户很可能是攻击者如发起为id为“-1”的数据或id为特别大(不存在的数据),导致数据库压力过大或宕机。在这里插入图片描述

4.2、缓存穿透的解决方案

  • 参数校验
  • 缓存空对象
  • 布隆过滤器

4.3、解决缓存穿透的代码示例

  • 代码示例/***查询商品信息*/@Suppresswarnings("unchecked”)publicExpressInfofindByDeliveryOrderId(Long id){String key="xz-express:expmess-info:"//从 Redis查询物流信息Object obj = redisTemplate.opsForValue().get( key + id);if(obi ==null){synchronized(this){//进入 synchronized 一定要先再查询一次 Redis,防止上一个抢到锁的线程已经更新过了 obj = redisTemplate.opsForValue().get( key + id);if(obj !=null){return(List<ProductCategory>) obj;}//数据库查询 List<ProductCategory> categorylList = productCategoryMapper.selectProductCategory(id);//设置随机失效时间Duration expire =DurationofHours(2L).plus(Duration.ofSeconds((Math.random()100)));//从数据库中查询出的categoryList不管是否是空,都存到redis中 redisTemplate,opsForValue().set(key,categoryList,expire);}return categorylList ;}else{return(List<ProductCategory>) obj;}}
标签: redis

本文转载自: https://blog.csdn.net/li1325169021/article/details/132562686
版权归原作者 小志的博客 所有, 如有侵权,请联系我们删除。

“Redis——如何解决redis穿透、雪崩、击穿问题”的评论:

还没有评论