一、缓存击穿
场景:
缓存击穿指的是缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
解决方案: 1、设置热点数据永远不过期:这是一种“物理”上的解决方案,即不设置过期时间,这样就不会出现热点数据过期的情况,但这需要人工保证热点数据被正确维护。 2、加互斥锁:在并发多个请求同时去查询数据库的这条数据的时候,加锁保证同一时间只有一个请求去查询数据库,其他请求要么等待、要么有降级方案,比如提供默认值。
二、缓存穿透
场景:
缓存穿透是指查询一个数据库一定不存在的数据,由于缓存也不存在,每次请求都会到数据库去查询,造成缓存层和数据库层都击穿的现象。
解决方案:
1、布隆过滤器:布隆过滤器是一个可以告诉你“某样东西一定不存在或者可能存在”的数据结构,它非常适合用来解决缓存穿透问题。在查询缓存之前,先使用布隆过滤器进行过滤,如果布隆过滤器判断数据不存在,则直接返回,避免了对数据库的查询。
2、缓存空对象:当数据库查询结果为空时,也将其缓存起来,并设置一个较短的过期时间。这样,在下次请求相同的数据时,就可以直接从缓存中获取空对象,而不需要再去查询数据库。
三、缓存雪崩
场景:
缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求直接到达数据库,带来巨大压力。
解决方案:
1、缓存预热:在系统上线前,预先加载一部分热点数据到缓存中,这样,在大量用户请求到来时,这些热点数据就已经在缓存中了。 2、设置缓存过期时间随机:避免大量的key在同一时刻同时失效,造成缓存雪崩。 3、使用互斥锁或队列:在更新缓存时,使用互斥锁或队列来确保同一时间只有一个请求去更新缓存,其他请求要么等待、要么有降级方案。