缓存雪崩和缓存穿透

本文探讨了缓存雪崩和缓存穿透的问题及其解决方案。介绍了如何通过加锁计数、合理分布缓存失效时间及使用布隆过滤器等手段来避免这些问题,确保系统稳定运行。

缓存雪崩

缓存雪崩可能是因为数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。

解决思路:

1,采用加锁计数,或者使用合理的队列数量来避免缓存失效时对数据库造成太大的压力。这种办法虽然能缓解数据库的压力,但是同时又降低了系统的吞吐量。

2,分析用户行为,尽量让失效时间点均匀分布。避免缓存雪崩的出现。

3,如果是因为某台缓存服务器宕机,可以考虑做主备,比如:redis主备,但是双缓存涉及到更新事务的问题,update可能读到脏数据,需要好好解决。


缓存穿透

缓存穿透是指用户查询数据,在数据库没有,自然在缓存中也不会有。这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库中查询。

解决思路:

1,如果查询数据库也为空,直接设置一个默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库,这种办法最简单粗暴。

2,根据缓存数据Key的规则。例如我们公司是做机顶盒的,缓存数据以Mac为Key,Mac是有规则,如果不符合规则就过滤掉,这样可以过滤一部分查询。在做缓存规划的时候,Key有一定规则的话,可以采取这种办法。这种办法只能缓解一部分的压力,过滤和系统无关的查询,但是无法根治。

3,采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的BitSet中,不存在的数据将会被拦截掉,从而避免了对底层存储系统的查询压力。关于布隆过滤器,详情查看:基于BitSet的布隆过滤器(Bloom Filter) 

大并发的缓存穿透会导致缓存雪崩。

### Redis缓存雪崩缓存穿透的概念及解决方案 #### 缓存雪崩 缓存雪崩是指当Redis中的大量缓存数据在同一时间过期,而这些数据的访问频率较高时,由于缓存中没有数据,所有请求会直接到达数据库层进行查询。这种情况下,数据库可能因为瞬间的高并发请求而崩溃或性能急剧下降[^2]。 **解决方案:** 1. **设置随机过期时间** 在存储缓存数据时,为每个key设置一个带有随机偏移量的过期时间,避免大量key在同一时刻过期。例如,可以将原本统一的过期时间调整为 `T + 随机数` 的形式。 2. **预热缓存** 在系统高峰流量来临之前,通过定时任务提前加载热点数据到缓存中,确保缓存始终有效[^2]。 3. **使用互斥锁** 当缓存中没有数据时,使用互斥锁机制(如Redis分布式锁),让一个线程负责从数据库加载数据并更新缓存,其他线程等待缓存更新完成后再获取数据,从而减轻数据库压力[^5]。 --- #### 缓存穿透 缓存穿透是指客户端请求的数据既不在缓存中,也不在数据库中存在,导致每次请求都会直接访问数据库。这种情况会导致数据库承受不必要的压力,尤其是当恶意攻击者故意构造不存在的请求时,可能会对系统造成严重威胁[^3]。 **解决方案:** 1. **缓存空对象** 对于查询结果为空的数据,仍然将其缓存一段时间(如几分钟)。这样,即使后续有相同的请求,也可以直接从缓存中返回,而无需每次都查询数据库。不过需要注意的是,空对象的缓存时间不宜过长,以免占用过多缓存资源。 2. **布隆过滤器** 使用布隆过滤器(Bloom Filter)来判断数据是否存在。布隆过滤器是一种高效的空间节省型数据结构,可以在不增加太多计算开销的情况下快速判断某个数据是否可能存在。如果布隆过滤器返回“不存在”,则可以直接返回,无需查询缓存或数据库[^5]。 --- ```python # 示例代码:使用布隆过滤器防止缓存穿透 from pybloom_live import BloomFilter # 初始化布隆过滤器 bloom_filter = BloomFilter(capacity=100000, error_rate=0.001) def check_cache(key): if key in bloom_filter: # 查询缓存 cached_value = redis.get(key) if cached_value is not None: return cached_value else: # 缓存未命中,查询数据库 db_value = database.query(key) if db_value is not None: redis.set(key, db_value) return db_value else: # 缓存空对象 redis.set(key, "null", ex=60) # 空对象缓存60秒 return None else: # 布隆过滤器判定不存在 return None # 将新key加入布隆过滤器 def add_to_bloom_filter(key): bloom_filter.add(key) ``` --- #### 总结 缓存雪崩缓存穿透虽然都可能导致数据库压力增大,但其触发原因解决方法有所不同。缓存雪崩主要是由于大量缓存同时过期引起,而缓存穿透则是由于查询不存在的数据导致。因此,在设计缓存策略时,需要针对这两种情况分别采取不同的解决方案[^4]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值