- 缓存穿透
在查询一个一定不存在的数据,由于缓存是不命中时被动写入,并且处于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到存储层去查询,缓存层失去意义。
当在大流量流入时,可能因为频繁访问存储层导致DB直接宕机,这样会形成被人利用不存在的key频繁攻击应用的漏洞。
解决方法
最为常简的是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的 bigmap 中,一个一定不存在的数据会被该 bigmap 拦截掉,从而避免对底层存储系统造成查询压力。
另一种更为简单的方法,如果一个查询返回的数据为空(无论数据为空,或是系统故障),将空结果进行缓存,设置一个最长不超过五分钟的过期时间。
- 缓存雪崩(缓存失效)
如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。
缓存层宕掉后,流量会像奔逃的野牛一样,打向后端存储
解决方法:
在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存
不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀
做二级缓存,或者双缓存策略。A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。
- redis缓存击穿(热点Key):
缓存中的一个Key(比如一个促销商品),在某个时间点过期的时候,恰好在这个时间点对这个Key有大量的并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。
解决方案:对缓存查询加锁,如果KEY不存在,就加锁,然后查DB入缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回数据或者进入DB查询