1. 缓存穿透问题
- 概念:缓存穿透是指大量请求访问系统中不存在的数据,这些请求绕过缓存直接打到数据库上,导致数据库压力过大甚至崩溃。在面对十亿非法 Key 攻击时,这种情况会更为严重。
- 危害:由于缓存中没有这些非法 Key 对应的数据,每次请求都要查询数据库,若攻击请求量大,会使数据库负载过高,影响系统的可用性和性能。
- 总结:缓存穿透是一种因非法数据请求导致数据库压力过大的问题,理解其概念和危害是后续探讨解决方案的基础。
2. 布隆过滤器
- 原理:布隆过滤器是一种概率型数据结构,它可以快速判断一个元素是否在集合中。它通过多个哈希函数将元素映射到一个位数组中,将对应位置置为 1 。查询时,通过哈希函数映射判断对应位置是否都为 1 ,如果有一个不为 1 则元素一定不在集合中,如果都为 1 则大概率在集合中(存在误判)。
- 作用:在防止缓存穿透中,将所有合法的 Key 存入布隆过滤器中,当有请求时,先通过布隆过滤器判断 Key 是否合法,若不合法则直接返回,不再查询数据库,从而防止非法 Key 打到数据库上。
- 总结:布隆过滤器利用其独特的结构和哈希映射原理,能快速过滤非法 Key ,减少数据库的压力,是防止缓存穿透的有效手段之一,但存在一定的误判率。
3. 缓存空值
- 方法:当查询数据库发现数据不存在时,也将这个空结果存入缓存中,并设置一个较短的过期时间。这样当下次再有相同的请求时,直接从缓存中获取空值,而不会再次查询数据库。
- 注意事项:要合理设置空值的过期时间,时间过短可能导致仍然有大量请求打到数据库,时间过长则可能影响新数据的及时更新。
- 总结:缓存空值通过缓存不存在的数据的空结果,避免了对不存在数据的重复数据库查询,是一种简单有效的防止缓存穿透的方法,但需要注意过期时间的设置。
4. 请求校验和清洗
- 操作:对前端发送过来的请求进行校验,比如检查请求参数的格式、类型、长度等是否符合要求,对于不符合要求的请求直接拒绝。同时,对请求中的数据进行清洗,去除非法字符、恶意代码等,防止恶意攻击。
- 目的:从源头上拦截非法请求,避免非法 Key 进入到缓存和数据库的查询流程中,保障系统的安全性和稳定性。
- 总结:请求校验和清洗是在请求入口处对请求进行处理,通过验证和清洗操作,防止非法请求进入系统内部,是防止缓存穿透的前置防线。
5. 异步加载与预热
- 异步加载:在系统启动或者数据更新时,通过异步线程提前加载数据到缓存中,避免在请求到来时才去查询数据库并加载数据到缓存,减少缓存未命中的情况。
- 预热:在系统上线前,提前将一些热点数据或者常用数据加载到缓存中,使缓存中已有部分数据,当请求到来时可以直接从缓存中获取,提高缓存命中率,减轻数据库压力。
- 总结:异步加载和预热通过提前将数据加载到缓存中,提高了缓存命中率,减少了请求直接查询数据库的情况,对于防止缓存穿透和提升系统性能有积极作用。
6. 熔断降级
- 熔断:当数据库的负载达到一定阈值或者出现异常时,自动切断对数据库的请求,直接返回一个默认值或者错误信息给前端,防止过多的请求压垮数据库。
- 降级:在系统资源紧张或者出现故障时,降低系统的某些功能的服务质量,比如返回简化的数据或者降低数据的实时性等,以保证核心功能的正常运行,减轻数据库的压力。
- 总结:熔断降级是在系统出现异常或者压力过大时的一种保护机制,通过切断请求或者降低服务质量,保护数据库和系统的稳定运行,是防止缓存穿透和应对系统故障的重要手段。
7. 数据库层面分散压力
- 方法:可以采用数据库的读写分离、分库分表等技术,将数据库的压力分散到多个数据库实例或者表中。比如对于读请求较多的情况,将读操作分散到多个从库上,减少主库的压力;对于数据量较大的情况,通过分库分表将数据分散存储,提高查询效率。
- 作用:即使存在缓存穿透问题,通过分散压力,也能保证数据库不会因为大量请求而崩溃,提高数据库的可用性和稳定性。
- 总结:在数据库层面采用分散压力的技术,能够增强数据库的抗压能力,配合其他防止缓存穿透的措施,更好地保障系统的稳定运行。
8. 分层缓存:本地和 Redis
- 本地缓存:
- 原理:在应用服务器本地存储数据,如使用 Guava Cache 等工具。本地缓存的访问速度极快,因为数据就在应用服务器的内存中,不需要进行网络通信。
- 优点:能快速响应请求,减少对 Redis 等远程缓存的访问压力,对于一些频繁访问且数据变化不频繁的数据(如字典数据等)非常适用。
- 缺点:存储容量有限,受应用服务器内存大小限制;数据共享性差,不同的应用服务器实例之间的本地缓存数据不共享;数据一致性维护相对复杂,当数据更新时需要及时通知各个实例更新本地缓存。
- Redis 缓存:
- 原理:Redis 是一种基于内存的高性能键值对数据库,支持多种数据结构。它通过网络与应用服务器进行通信,应用服务器可以将数据存储到 Redis 中,并在需要时从 Redis 中读取数据。
- 优点:存储容量相对较大,可以通过集群等方式扩展存储容量;数据共享性好,多个应用服务器实例可以共享 Redis 中的数据;提供了丰富的数据结构和操作命令,方便进行各种数据处理。
- 缺点:存在网络延迟,虽然 Redis 本身性能很高,但网络通信会带来一定的延迟;如果 Redis 出现故障,可能会影响到依赖它的应用服务。
- 分层缓存的作用:通过本地缓存和 Redis 缓存的结合,先从本地缓存中查询数据,如果未命中再查询 Redis 缓存,最后才查询数据库。这样可以大大提高缓存命中率,减少对数据库的访问,在一定程度上防止缓存穿透问题,同时也能提高系统的整体性能。
- 总结:分层缓存利用本地缓存和 Redis 缓存各自的优势,形成了多级缓存结构,提高了缓存的命中率和系统性能,对防止缓存穿透和提升系统的整体效率有重要作用,但也需要注意解决数据一致性和缓存管理等问题。
9. 组合策略
- 方式:将上述多种防止缓存穿透的方案组合使用,比如同时使用布隆过滤器进行非法 Key 过滤、缓存空值防止重复查询、请求校验和清洗保证请求合法、分层缓存提高缓存命中率等。
- 优势:单一的方案可能存在一定的局限性,组合策略可以发挥不同方案的优势,更有效地拦截非法请求,提高系统的安全性和稳定性,确保数据库的正常运行。
- 总结:组合使用多种防止缓存穿透的策略是一种更全面、更有效的方式,能够弥补单一方案的不足,更好地应对复杂的攻击场景,保障系统的稳定运行。