在日常的项目中,我们经常需要用到缓存技术。因为有些数据不需要每次查询时都从数据库获取。特别是在高QPS(每秒查询率)的系统中,频繁查询数据库可能会导致数据库性能问题甚至崩溃。
我们通常的业务系统调用流程如下图所示: [图片]
但在特定情况下,可能会出现缓存穿透和缓存雪崩的问题,这些问题可能导致所有请求都打到数据库上,最终导致数据库崩溃,进而影响整个业务系统的运行。接下来我们将讨论如何避免这些问题。
缓存穿透指的是大量用户查询的key在Redis中找不到,从而导致所有请求都打到MySQL数据库上。
针对上述情况,我们提出以下解决方案:
黑客攻击
方案一:
当缓存和数据库中都没有找到该key时,可以将该key缓存为空值(如"unknown"),后续再次查询该key时直接返回空值,避免再次查询数据库。
方案二:
使用布隆过滤器。在缓存之前增加一层布隆过滤器,查询时先判断key是否存在,若不存在则直接返回,存在再查询缓存和数据库。
方案比较:
对于恶意攻击带来的大量不存在的key,第一种方案会缓存大量无效数据,因此更适合使用第二种方案来过滤这些无效key。而对于少量但重复率较高的空数据key,则可以考虑使用第一种方案。
热点key过期
方案一:
设置不同的过期时间。为了避免热点数据集中失效,可以在设置缓存过期时间时加入随机值,使不同数据的过期时间错开。
方案二:
使用分布式锁控制访问数据库的线程数。例如,利用互斥锁控制一个线程访问数据库,并将数据更新至缓存中,其他线程则直接从缓存中读取数据。
缓存雪崩是指由于某种原因(如突发事件引发热点key)导致多个Redis节点负载过高而宕机,这些热点key会转移到其他节点,导致更多节点宕机,最终导致整个缓存集群崩溃。
事前准备:
使用集群缓存,确保缓存服务高可用。例如,使用Redis的主从+哨兵架构或Redis Cluster来避免单一故障点。
事中应对:
使用本地缓存(如Ehcache)和Hystrix进行限流和降级操作。本地缓存可以在Redis集群不可用时临时支撑一段时间。Hystrix可以限制并发请求数量,超过限制的请求则进入降级逻辑,例如返回默认值。
处理缓存雪崩的关键点:
参考有赞TMC的思路,通过热点探测和本地缓存功能,结合实际业务需求灵活配置,可以有效缓解缓存雪崩问题。