什么是缓存穿透,如何解决

场景:
对于系统A,假设一秒 5000 个请求,结果其中 4000 个请求是黑客发出的恶意攻击。

黑客发出的那 4000 个攻击,缓存中查不到,每次你去数据库里查,也查不到。

举个例子
数据库 id 是从 1 开始的,结果黑客发过来的请求 id 全部都是负数。这样的话,缓存中不会有,请求每次都会直接越过缓存,直接查询数据库。这种恶意攻击场景的缓存穿透就会直接把数据库给打死。

大概就是这个样子:
在这里插入图片描述

解决办法:
每次系统 A 从数据库中只要没查到,就写一个空值到缓存里去,比如 set -999 UNKNOWN。这样的话,下次便能走缓存了

### 缓存穿透的概念与常见问题 缓存穿透是指请求的数据既不在缓存中,也不在数据库中,导致每次请求都会直接访问数据库[^5]。这种情况下,如果大量请求针对不存在的数据进行查询,将对后端数据库造成巨大的压力,甚至可能导致系统崩溃。 缓存机制中的常见问题包括以下几种: #### 1. 缓存穿透 缓存穿透指的是客户端请求了不存在的数据,而这些数据既没有存储在缓存中,也没有存储在数据库中。由于缓存未命中,所有请求都会直接落到数据库上,从而增加数据库的负担。例如,恶意用户可能通过构造大量不存在的键值来攻击系统,进一步加剧这一问题[^5]。 解决方法包括: - **空对象缓存**:当发现某个查询返回为空时,可以将这个空结果也缓存起来,并设置一个较短的过期时间。这样可以避免后续对该数据的重复查询直接打到数据库上[^5]。 - **布隆过滤器**:使用布隆过滤器提前判断数据是否存在。布隆过滤器是一种空间效率高的概率型数据结构,能够快速判断某个元素是否存在于集合中。虽然它可能会有误判,但可以显著减少无效查询到达数据库的概率。 #### 2. 缓存雪崩 缓存雪崩是指在短时间内,大量缓存同时失效或缓存服务本身发生故障,导致原本由缓存处理的请求直接涌向数据库,给数据库带来极大的压力[^3]。为了解决这个问题,可以采取以下措施: - 设置随机过期时间,避免缓存在同一时刻集中失效[^3]。 - 使用多级缓存架构,即使某一层缓存失效,其他层仍能分担流量[^3]。 - 实施服务熔断与限流策略,保护数据库免受过高并发请求的影响[^3]。 #### 3. 缓存击穿 缓存击穿是指某个热点数据的缓存失效后,大量并发请求在同一时间访问数据库,造成数据库压力骤增的现象[^1]。解决方法包括: - 使用互斥锁机制,确保只有单个线程负责重建缓存,其他线程等待缓存重建完成后再进行访问[^2]。 --- ### 示例代码:空对象缓存 以下是一个简单的示例代码,展示如何实现空对象缓存以防止缓存穿透: ```python import redis # 初始化Redis客户端 r = redis.Redis(host='localhost', port=6379, db=0) def get_data_from_cache_or_db(key): # 尝试从缓存中获取数据 cached_data = r.get(key) if cached_data: return cached_data.decode('utf-8') # 如果缓存中没有数据,则从数据库中查询 data = query_database(key) # 假设这是一个查询数据库的函数 if data is None: # 如果数据库中也没有数据,则缓存一个空对象 r.setex(key, 60, "null") # 缓存空对象,过期时间为60秒 return None # 如果数据库中有数据,则更新缓存 r.setex(key, 3600, data) # 缓存有效数据,过期时间为3600秒 return data def query_database(key): # 模拟数据库查询逻辑 return None # 假设数据库中没有该数据 ``` --- ### 示例代码:布隆过滤器 以下是一个简单的布隆过滤器实现,用于过滤不存在的键值: ```python from pybloom_live import BloomFilter # 创建布隆过滤器,预计插入100万个元素,允许误差率为0.1% bf = BloomFilter(capacity=1000000, error_rate=0.001) def add_to_bloom_filter(key): bf.add(key) def check_in_bloom_filter(key): return key in bf # 示例用法 add_to_bloom_filter("existing_key") print(check_in_bloom_filter("existing_key")) # 输出 True print(check_in_bloom_filter("non_existing_key")) # 输出 False 或可能为 True(概率性错误) ``` ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值