缓存雪崩
指的短时间内,大量缓存数据过期逐出,还没有从新加载到缓存中时,流量全部打到数据库上,导致数据库负载飙升,导致数据库压力过大甚至被压垮的场景。
我们使用缓存的目的,一是提升接口查询性能,二是降低数据库压力。
很明显,在缓存雪崩场景下这二者不但没有解决,反而成了服务最致命问题。
解决办法
-
请求加锁
造成数据库负载飙升的主要原因,是缓存失效,对同一数据的多次访问全部请求到了数据库上,那么这时候一旦从缓存中拿不到数据,就对此行数据加锁,保证同时只有一个请求访问数据库,而后将数据再加载到缓存。这样相同的请求也不会对数据库造成多次访问。
但是,服务中,任何加锁的方法,都应当只能是最终的方案,任何加锁的解决办法都不是一个好的办法。因为加锁,将请求同步处理,导致服务的性能下降;并且加锁也是一个十分消耗资源的事。
-
过期设置
缓存数据的过期时间,不要都设置在同一时间节点上,否则在这个时间节点,会有海量数据过期逐出。过期时间的设置应当尽量平滑。
-
热点数据
设置热点数据永不过期,这些热点数据可能会占到所有请求流量的绝大部分。
设置热点数据在分布式缓存中分布尽量均匀。
-
降级处理
设置多重缓存,缓存降级。
缓存穿透
指的是查询的数据数据库中不存在,也就不会加载到缓存中,导致每次查询都会请求到数据库。
-
布隆过滤
利用布隆过滤的特性,将不为空的数据放到过滤器中,过滤出一定不存在的记录,这类数据就直接返回空值。
有局限性,比如有些数据可以在为空和不为空之间切换,而布隆过滤器无法剔除数据。
-
对空缓存
可以对空值进行缓存。
-
空值标记
使用其他标记位,标记此行记录是否存在。
缓存击穿
指的是热点数据在更新数据、刷新缓存或者缓存过期的一瞬间犹豫缓存失效,导致海量流量请求到数据库。
-
请求加锁
一旦从缓存中拿不到数据,就对此行数据加锁,保证同时只有一个请求访问数据库,而后将数据再加载到缓存。这样相同的请求也不会对数据库造成多次访问。
-
热点数据异步刷新、永不过期
使用copyOnWrite思想,当新缓存完全准备好再提供查询,在这期间都返回老数据。
网友评论