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

目录

    • 一、查询商品信息的常规代码示例
    • 二、缓存击穿
      • 2.1、缓存击穿的理解
      • 2.2、缓存击穿的解决方案
      • 2.3、解决缓存击穿的代码示例
    • 三、缓存雪崩
      • 3.1、缓存雪崩的理解
      • 3.2、缓存雪崩的解决方案
        • 3.2.1、缓存集中过期的情况
        • 3.2.2、缓存服务器宕机的情况
        • 3.2.3、缓存服务器断电的情况
      • 3.3、解决缓存雪崩(缓存集中过期)的代码示例
    • 四、缓存穿透
      • 4.1、缓存穿透的理解
      • 4.2、缓存穿透的解决方案
      • 4.3、解决缓存穿透的代码示例

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

  • 查询商品信息的常规代码示例
/**
*查询商品信息
*/
public ExpressInfo findByDeliveryOrderId(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 {
 			throw new clientException("发货单,的物流信息不存在",id);
 		}
	}
}
		

二、缓存击穿

2.1、缓存击穿的理解

  • 高并发时,当一个kev非常热点(类似于爆款)在不停的扛着大并发当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库并设置到缓存中,导致性能下降。
    Redis——如何解决redis穿透、雪崩、击穿问题_第1张图片

2.2、缓存击穿的解决方案

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

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

  • 代码示例

    /**
    *查询商品信息
    */
    @Suppresswarnings("unchecked”)
    public ExpressInfo findByDeliveryOrderId(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、缓存雪崩的理解

  • 缓存集中过期,或者缓存服务器宕机,导致大量请求访问数据库,造成数据库瞬间压力过大,宕机。
    Redis——如何解决redis穿透、雪崩、击穿问题_第2张图片

3.2、缓存雪崩的解决方案

3.2.1、缓存集中过期的情况

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

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

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

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

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

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

  • 代码示例

    /**
    *查询商品信息
    */
    @Suppresswarnings("unchecked”)
    public ExpressInfo findByDeliveryOrderId(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为特别大(不存在的数据),导致数据库压力过大或宕机。
    Redis——如何解决redis穿透、雪崩、击穿问题_第3张图片

4.2、缓存穿透的解决方案

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

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

  • 代码示例

    /**
    *查询商品信息
    */
    @Suppresswarnings("unchecked”)
    public ExpressInfo findByDeliveryOrderId(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,redis)