常见的几种缓存问题

2021-09-15  本文已影响0人  lfboo

一,缓存穿透

描述

访问一个缓存和数据库都不存在的 key,此时会直接打到数据库上,并且查不到数据,没法写缓存,所以下一次同样会打到数据库上; 此时,缓存起不到作用,请求每次都会走到数据库,流量大时数据库可能会被打挂。此时缓存就好像被“穿透”了一样,起不到任何作用

解决方案
  1. 做相应鉴权,排除非法攻击的情况
  2. 缓存空值,从数据库取不到时,可以缓存null值或Optional

二,缓存击穿

描述

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力

解决方案
  1. 加互斥锁
public Object getData(String key) throws InterruptedException {
    Object value = redis.get(key);
    // 缓存值过期
    if (value == null) {
        // lockRedis:专门用于加锁的redis;
        // "empty":加锁的值随便设置都可以
        if (lockRedis.set(key, "empty", "PX", lockExpire, "NX")) {
            try {
                // 查询数据库,并写到缓存,让其他线程可以直接走缓存
                value = getDataFromDb(key);
                redis.set(key, value, "PX", expire);
            } catch (Exception e) {
                // 异常处理
            } finally {
                // 释放锁
                lockRedis.delete(key);
            }
        } else {
            // sleep100ms后,进行重试
            Thread.sleep(100);
            return getData(key);
        }
    }
    return value;
}
  1. 设置热点数据永不过期

三,缓存雪崩

描述

大量的热点 key 设置了相同的过期时间,导在缓存在同一时刻全部失效,造成瞬时数据库请求量大、压力骤增,引起雪崩,甚至导致数据库被打挂; 缓存雪崩其实有点像“升级版的缓存击穿”,缓存击穿是一个热点 key,缓存雪崩是一组热点 key

解决方案
  1. 热点数据永不过期
  2. 过期时间打散
  3. 加互斥锁,同缓存击穿
上一篇 下一篇

猜你喜欢

热点阅读