缓存击穿和缓存穿透是在使用缓存时常见的两个问题,它们都会导致数据库压力增大,但原因和解决方案有所不同。
缓存击穿,也叫缓存雪崩,是对同一个key是指一个非常热门的Key在某个时间点过期,由于这个Key的请求量很大,当它过期的瞬间,大量的请求会直接打到数据库上,导致数据库压力剧增。这种情况类似于缓存雪崩
,但只影响单个Key。解决方案包括:
- 使用互斥锁(mutex lock),确保在缓存重建期间只有一个线程能访问数据库,从而避免大量并发请求同时到达数据库。这种方法可以保证数据的高一致性,但可能会降低系统性能,并有潜在的死锁风险。
- 设置热点Key为永不过期,或者使用逻辑过期,即在代码中检查Key是否过期,而不是依赖缓存系统本身的过期机制。
缓存穿透,是对很多的key同时失效,全部打入到数据库是指请求查询数据库和缓存中都不存在的数据,导致每次请求都要到数据库查询,失去了缓存的意义。这种情况通常发生在有恶意攻击或数据请求分布不均匀
,比如缓存再哦那个一个时间失效时。解决方案包括:
- 缓存空对象,即即使查询数据库没有结果,也将这个“空”结果缓存起来,这样再次查询相同的Key时,可以直接返回空结果,而不需要查询数据库。
- 使用布隆过滤器(Bloom Filter),在查询数据库之前先通过布隆过滤器判断Key是否存在,如果布隆过滤器认为Key不存在,则直接返回,避免了对数据库的查询。
在实际应用中,解决这些问题通常需要根据具体的业务场景和系统架构来选择合适的策略。例如,对于缓存击穿,如果业务允许,可以考虑设置热点Key为永不过期;对于缓存穿透,则可以通过缓存空对象或使用布隆过滤器来减少对数据库的无效查询。
布隆过滤器最常见的应用之一就是防止缓存穿透
- 在 Redis 缓存场景中,用户请求的数据可能在缓存和数据库中都不存在,如果不加以防护,这些请求会直接打到数据库。通过布隆过滤器,可以在请求前判断元素是否可能存在于数据库中,从而减少无效的数据库查询。
- 场景: 一个电商系统中,用户可能会频繁查询一些并不存在的商品 ID。布隆过滤器可以用来存储所有合法商品 ID,在查询前进行判断,如果布隆过滤器中不存在,则可以直接返回空结果,而不必查询数据库和缓存。