缓存穿透#
缓存穿透是指查询一个在缓存和数据库中都不存在的数据。
可能有恶意用户故意请求一个不存在的数据
解决方案#
基本思路就是提前校验拦住
- 查缓存之前做初步校验
- 缓存空值:将查询不到的数据缓存一个空值(如 null),设置短暂的过期时间,避免频繁查询数据库
- 布隆过滤器 (Bloom Filter):使用布隆过滤器来快速判断某个数据是否存在,从而避免无效的数据库查询。
缓存击穿#
缓存击穿是指缓存中没有数据库中有的查询,一般指某个缓存项过期后,大量请求同时访问该缓存项,导致大量请求打到数据库上,造成数据库压力骤增。
解决方案#
- 热点数据支持续期,即到期后自动续期
- 缓存失效时,加互斥锁重建缓存。确保只有一个线程能访问数据库并重建缓存,其他线程等待锁释放后直接从缓存读取 采用 check lock check(double check)模式。协程查不到缓存时抢锁,抢到锁后继续查缓存,若无缓存则查库并重建缓存,有缓存则直接返回。这样只有一个抢到锁并重建缓存,其他的等待锁释放后就能直接读取已重建的缓存了 Go 中具体解决方式:使用 sync.once()
缓存雪崩#
缓存雪崩是指在某一个时间点,缓存中的大量数据同时过期,导致大量请求直接打到数据库上,造成数据库压力骤增,甚至崩溃。
解决方案#
- 缓存的数据过期时间设置随机,防止同一时间大量的数据过期
- 和缓存击穿一样,加互斥锁重建缓存
- 缓存预热,在缓存大量过期前,提前加载数据到缓存中