什么是缓存雪崩?为什么会缓存雪崩?
- 缓存雪崩是因为大量缓存数据在同一时间过期或者服务器的宕机/重启/故障登原因导致大量存在于缓存的数据落到数据库上,给DB带来巨大的压力从而崩溃。
- redis服务器宕机,所有key都失效,更严重点。
如何解决缓存雪崩?
- 均匀设置过期时间:就是将key的过期时间后面加上一个随机数(比如随机1-5分钟),让key均匀的失效
Random random = new Random();
int expiration = random.nextInt(max - min + 1) + min;
redisTemplate.expire(key, expiration, TimeUnit.SECONDS);
- 使用后台程序定时更新数据:热点数据可以考虑不失效,后台异步更新缓存(就是后台定时的检测缓存是否失效而淘汰和更新缓存数据,也可以业务线程通知后台的方式让后台更新缓存),适用于不严格要求缓存一致性的场景
使用 @Scheduled 注解实现 定时更新
- 双key策略:主key设置过期时间,备key不设置过期时间,当主key失效时,直接返回备key值(即只有一个请求去更新缓存,在这期间有别的请求到来就使用旧值返回)。更新缓存的时候,同时更新两个key的数据。 相当于给缓存数据做副本.俩KEY-VALUE,key不一致,value一致,备key设置永不过期(TTL = -1).当业务线程访问不到【主key】的缓存数据时,返回【备Key】的数据,有效避免用互斥锁(上述第二点)大量线程被锁住,后续再通知后台线程,重新构建【主key】数据。
- 避免redis宕机的方法:哨兵集群。
什么是缓存击穿?为什么会缓存击穿?
- 缓存雪崩是指只大量热点key同时失效的情况,而如果是单个热点数据过期了(失效),此时有大量的请求访问了该热点数据,在缓存无法读取到数据,而直接访问数据库数据库很容易就被高并发的请求冲垮,这就是缓存击穿。如下图:
从定义上看,我们看出缓存雪崩和缓存击穿很相似,只不过缓存击穿是一个热点key失效,而缓存雪崩是大量热点key失效。因此,可以认为缓存击穿是缓存雪崩的一个子集。
如何解决缓存击穿?
-
互斥锁方案,保证同一时间只有一个业务线程更新缓存,未能获取互斥锁的请求,要么等待锁释放后重新读取缓存,要么就返回空值或者默认值。单机通过synchronized或lock来处理,分布式环境采用分布式锁
-
不给热点数据设置过期时间,由后台异步更新缓存,或者在热点数据准备要过期前,提前通知后台线程更新缓存以及重新设置过期时间。适用于不严格要求缓存一致性的场景
-
”提前“使用互斥锁(Mutex Key):在value内部设置一个比缓存(Redis)过期时间短的过期时间标识,当异步线程发现该值快过期时,马上延长内置的这个时间,并重新从数据库加载数据,设置到缓存中去.
什么是缓存穿透?为什么会缓存穿透?
- 当用户访问的数据,即不在缓存中,也不在数据库中。导致请求在访问缓存时,发现缓存缺失,再去访问数据库时,发现数据库中也没有要访问的数据,则不写入缓存。这就导致每次请求都会到底层数据库进行查询,缓存也失去了意义。当高并发或有人利用不存在的Key频繁攻击时,数据库的压力骤增,甚至崩溃,这就是缓存穿透
如何解决缓存穿透?
-
缓存空值(null)或默认值
- 优点:实现简单维护方便。
- 缺点:消耗内存,可能造成短期的不一致
-
业务逻辑前置校验
-
用户黑名单限制
-
使用布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在
布隆过滤器
- 底层是bitmap二进制0和1的数组,将要查询的数据进行k次哈希算法对应到数组中,存在则为1。时间复杂度是OK。
- 误差度取决于进行了多少次哈希算法,哈希越多次越精准。相应的数组也会变大。
Redis 有哪些数据类型?
5种基础数据类型,分别是:String、List、Set、Zset、Hash。3种特殊的数据类型 分别是 HyperLogLogs(基数统计), Bitmaps (位图) 和 geospatial (地理位置)
Redis 数据类型有哪些底层数据结构?
Redis key 的过期时间和永久有效分别怎么设置?
EXPIRE
和 PERSIST
命令