Redis缓存穿透,缓存雪崩,缓存击穿

缓存穿透

缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存。
在这里插入图片描述

@Override
public List<TbContent> findByCategoryId(Long categoryId) { // -1
	// 加入缓存的代码:
	List<TbContent> list = (List<TbContent>) redisTemplate.boundHashOps("content").get(categoryId);
	
	if(list==null){
		System.out.println("查询数据库===================");
		TbContentExample example = new TbContentExample();
		Criteria criteria = example.createCriteria();
		// 有效广告:
		criteria.andStatusEqualTo("1");
		
		criteria.andCategoryIdEqualTo(categoryId);
		// 排序
		example.setOrderByClause("sort_order");
		
		list = contentMapper.selectByExample(example);
		if(list !=null){
			redisTemplate.boundHashOps("content").put(categoryId, list);
        }
	}else{
		System.out.println("从缓存中获取====================");
	}
	
	return list;
}			

解决方案 :

1). 设置过期时间

@Override
public List<TbContent> findByCategoryId(Long categoryId) {
	// 加入缓存的代码:
	List<TbContent> list = (List<TbContent>) redisTemplate.boundValueOps("content_"+categoryId).get();
	
	if(list == null){
		System.out.println("查询数据库===================");
		TbContentExample example = new TbContentExample();
		Criteria criteria = example.createCriteria();
		// 有效广告:
		criteria.andStatusEqualTo("1");
		
		criteria.andCategoryIdEqualTo(categoryId);
		// 排序
		example.setOrderByClause("sort_order");
		
		list = contentMapper.selectByExample(example);
		if(list != null){
			redisTemplate.boundValueOps("content_"+categoryId).set(list); //-1 
        }else{  //-1
            redisTemplate.boundValueOps("content_"+categoryId).set(null); //null
            redisTemplate.expire("content_"+categoryId,7200, TimeUnit.SECONDS);
        }
	}else{
		System.out.println("从缓存中获取====================");
	}
	
	return list;
}

2). 只查询缓存, 不查询数据库 ;

缓存击穿

缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞 。
解决方案 :

1). 对热点数据 , 不设置过期时间 ;  

2). 互斥锁
public class RedisDemo {

    private static Lock lock = new ReentrantLock();

    public static String getData(String key) throws InterruptedException {
        
        String result = getDataFromRedis(key); //从redis获取数据
		
        if(result == null){ // 如果数据为null , 需要从数据库中获取
            
            if(lock.tryLock()){ //尝试获取锁
                
                result = getDataFromMysql(key); //从数据库中查询
                
                if(result != null){ //如果查询到数据, 就缓存在redis中
                    saveDataToRedis(key,result);
                }
                lock.unlock();//释放锁
            }else{
                TimeUnit.MILLISECONDS.sleep(100);
                result = getData(key);
            }
        }
        return result;
    }

    private static void saveDataToRedis(String key, String result) {
        System.out.println("保存数据到redis中 , key - value ");
    }

    private static String getDataFromMysql(String key) {
        System.out.println("从数据库中获取数据 ");
        return null;
    }

    public static String getDataFromRedis(String key){
        System.out.println("从redis中获取数据 ");
        return null;
    }
}

缓存雪崩

缓存雪崩,是指在某一个时间点,缓存集中过期失效。

产生雪崩的原因之一,比如在写本文的时候,马上就要到双十二零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。
解决方案
1). 如果设置缓存的过期时间 , 需要根据业务划分 , 不同类型的数据, 可以设置不同的过期时间, 不要设置为相同的过期时间, 从而造成缓存在同一个时间点过期 ;

2). 只查询redis , 不查询数据库 ;

Linux 版本的 redis 安装
1). 上传 redis-3.0.0.tar.gz

alt + p ------> put D:/redis-3.0.0.tar.gz 

2). 安装C语言编译环境

yum install gcc-c++   (需要联网)

3). 解压压缩包

tar  -zxvf redis-3.0.0.tar.gz

4). 编译源码

cd  redis-3.0.0

make

5). 安装

make  install  PREFIX=/usr/local/redis

6). 拷贝解压目录下的redis配置文件redis.conf到redis安装目录

cp redis.conf  /usr/local/redis

7). 启动

cd  /usr/local/redis

bin/redis-server redis.conf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值