一、缓存穿透
1.1定义:根据查询条件,在数据库查询结果为空,没有查到数据时,程序没有设置缓存,这时如果恰好有上百万的高并发请求(可能是碰巧,也可能是黑客发现该漏洞后的恶意攻击),就直接到了DB层,导致数据库服务器压力过大而发生崩溃。
1.2具体场景:苹果手机发布了新品IPhone 13,但是商城还没有添加该新商品,数据库查询结果为空。
1.3解决办法:将空结果也缓存起来,设置一个较短的过期时间。
二、缓存雪崩
2.1定义:所有的(或者大部分的)缓存在同一时间,集体失效。导致cache层失效,高并发的请求直接到了DB层,导致数据库服务器压力过大而发生崩溃。
2.2具体场景:所有的(或者大部分的)缓存,在同一时间被放入缓存,并且设置的缓存时常相等。
2.3解决办法:设置缓存过期时间时,用固定值加随机数。
三、缓存击穿
3.1定义:某个热点数据,到了过期时间,缓存失效,但是仍然有高并发的访问。
3.2具体场景:商城新上架的新品IPhone 13,虽然该商品的设置了缓存,但是缓存时间为12小时,过了12小时之后,该商品缓存失效,高并发的请求直接到了DB层,导致数据库服务器压力过大而发生崩溃。
3.3解决办法:加锁(分布式系统,则需要加分布式锁,如redission),在web层等待,等读取到数据后设置新缓存,再释放锁。
四、个人建议:
1)其实前两种缓存失效的情况,也都应该加锁,或者系统刚上线的时候提前初始化一些缓存,否则系统刚上线,所有的查询都还没来得及设置缓存,如果这是有高并发,还是会因为高并发的请求直接到了DB层,导致数据库服务器压力过大而发生崩溃。
2)对于后两种,已经设置过缓存,但是都是由于缓存到期导致的问题,可以参考redission的watch dog机制,可以在第一次设置缓存的时候,设置一个定时任务,在缓存失效时间的1/3时间内,定时检查缓存最新的过期时间,并自动延长。比如30秒过期,每隔10秒检查一次缓存,并自动延长至30秒。