缓存的穿透,击穿,雪崩

缓存的穿透,击穿,雪崩

theme: csdn
highlight: redis

一. 缓存穿透

产生原因:用户在使用不存在的值去恶意访问,而缓存中不存在就会产生该请求不断db,造成数据库访问压力过大。
解决方案:
1. 如果是用户访问就去做鉴权校验,并对规定参数做限制大于或者小于亦或者符合自己所定义的规格。
2. 使用布隆过滤器排除不可能做缓存的请求:
实现原理:把所有可能存在问题的数据hash到一个足够大的bitmap中,如果一个一定不存在的数据会被这个bigmap直接拦截掉,从而避免了底层存储系统的查询压力。
优点:
1. 省空间:位是很省空间的,很长的东西也可以变为几位。
2. 省时间:判断,操作都是很快的,hash算法转化为向量也很快。
缺点:使用布隆会出现精准度损失的问题,而Bloom给出的默认损失精度的概率为3%,但是这个精准度的损失是可控的。
       <!--guava-->
		<dependency>
			<groupId>com.google.guava</groupId>
			<artifactId>guava</artifactId>
			<version>22.0</version>
		</dependency>
/** 
* @ClassName : BloomFilterTest 
* @Description : 布隆过滤器使用方法 
* @Author : LinZhiQ 
* @Date : 2020/12/3  15:00
*/
public class BloomFilterTest {
    
    
    public static void main(String[] args) {
    
    
        //1%,有个概率问题,布隆越大,占用的空间越多,但是错误概率减小了
        BloomFilter bloomFilter= BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()),1000000,0.001);
        bloomFilter.put("name");
        //为true表示在布隆过滤器里
        System.out.println(bloomFilter.mightContain("name"));
    }
}

二. 缓存击破

产生原因:缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
解决方案:
1. 设置热点缓存永不过期。
2. 加互斥锁,从而解决缓存穿透。
/**
 * @ClassName : RedisLockTest
 * @Description : 互斥锁
 * @Author : LinZhiQ
 * @Date : 2020/12/3  15:30
 */
@Service
public class RedisLockTest implements RedisLockTestInt{
    
    

    private Lock lock = new ReentrantLock();

    @Autowired
    private RedisTemplateUtils redisTemplateUtils;

    public String redisLockTest(String key) {
    
    
        // 从缓存中读取数据
        Object o = redisTemplateUtils.get(key);
        String result = "";
        // 缓存中不存在数据
        if (o == null) {
    
    
            //String str = String.valueOf(o);
            // 去获取锁,当锁获取成功后,去数据库查询数据
            if (lock.tryLock()) {
    
    
                try {
    
    
                    System.out.println("访问数据库... 查到了" + "result");
                    result = "result";
                    redisTemplateUtils.set(key, result);
                } catch (Exception e) {
    
    
                    e.printStackTrace();
                } finally {
    
    
                    lock.unlock(); // 释放锁
                }
            } else {
    
    
                try {
    
    
                    //暂停 200ms
                    Thread.sleep(200);
                } catch (Exception e) {
    
    
                    e.printStackTrace();
                } finally {
    
    
                    lock.unlock(); // 释放锁
                }
                redisLockTest(key); // 重新去获取数据
            }
        }
        return result; // 返回最终结果
    }
}

三. 缓存雪崩

产生原因:缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。
解决方案:
1. 分布式锁:若只有一个线程能够获得锁,先判断缓存是否存在,不存在便从db中获取数据并更新缓存,存在缓存便阻塞其它进程,更新完所有缓存完成后再获取缓存并释放。
2. 数据预热:提前将所有热点数据缓存好,不用等用户请求再缓存数据,如果有大量数据便交由后台运维,如果数据并不是很大,便自动加载。
3. 缓存降级:当缓存A失效时,便请求备份B,A的失效时间短,B的失效时间设置长。
4. 错峰更新缓存:更新缓存时与用户请求高峰错开,规定其更新缓存过期时间策略。
5. 设置不同的过期时间:让缓存时间均匀,这样会使很多用户的缓存数据保存下来。
6. 设置热点数据永不过期。
7. 如果缓存是分布式布置,将热点数据分布均匀的分布在不同的缓存数据库中。

猜你喜欢

转载自blog.csdn.net/weixin_43869435/article/details/110549650