Redis——缓存击穿、穿透、雪崩

本文详细探讨了缓存穿透、缓存击穿和缓存雪崩的问题,分别介绍了它们的成因、示例和应对方法,包括空值缓存、黑名单、布隆过滤器、监控与调整等技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、缓存穿透:

(1)问题描述:key对应的数据并不存在,每次请求访问key时,缓存中查找不到,请求都会直接访问到数据库中去,请求量超出数据库时,便会导致数据库崩溃。如一个用户id不存在,数据库与缓存都不存在该id,此时黑客便可以利用此漏洞不断访问该id,造成数据库崩溃。

(2)解决方法:

①对空值缓存:如果一个查询数据为空(不管数据是否存在),都对该空结果进行缓存,其过期时间会设置非常短。

②设置可以访问名单:使用bitmaps类型定义一个可以访问名单,名单id作为bitmaps的偏移量,每次访问时与bitmaps中的id进行比较,如果访问id不在bitmaps中,则进行拦截,不给其访问。

③采用布隆过滤器:布隆过滤器可以判断元素是否存在集合中,他的优点是空间效率和查询时间都比一般算法快,缺点是有一定的误识别率和删除困难。

④进行实时监控:对于redis缓存中命中率急速下降时,迅速排查访问对象和访问数据,将其设置为黑名单。

2.缓存击穿:

(1)问题描述:key中对应数据存在,当key中对应的数据在缓存中过期,而此时又有大量请求访问该数据,缓存中过期了,请求会直接访问数据库并回设到缓存中,高并发访问数据库会导致数据库崩溃。

(2)解决方案:

①预先设置热门数据:在redis高峰访问时期,提前设置热门数据到缓存中,或适当延长缓存中key过期时间。

②实时调整:实时监控哪些数据热门,实时调整key过期时间。

③对于热点key设置永不过期。

3、缓存雪崩·:

(1)问题描述:key中对应数据存在,在某一时刻,缓存中大量key过期,而此时大量高并发请求访问,会直接访问后端数据库,导致数据库崩溃。

注意:缓存击穿是指一个key对应缓存数据过期,缓存雪崩是大部分key对应缓存数据过期

正常访问下如图:

缓存失效瞬间如下图:

(2)解决方法:

①构建多级缓存机制:nginx缓存+redis缓存+其他缓存。

②设置过期标志更新缓存:记录缓存数据是否过期,如果过期会触发另外一个线程去在后台更新实时key的缓存。

③将缓存可以时间分散:如在原有缓存时间基础上增加一个随机值,这个值可以在1-5分钟随机,这样过期时间重复率就会降低,防止大量key同时过期。

④使用锁或队列机制:使用锁或队列保证不会有大量线程一次性对数据库进行读写,从而避免大量并发请求访问数据库,该方法不适用于高并发情况。


---------------------
作者:后端小猿
来源:优快云
原文:https://blog.youkuaiyun.com/weixin_50616848/article/details/123939734
版权声明:本文为作者原创文章,转载请附上博文链接!
内容解析By:优快云,CNBLOG博客文章一键转载插件

### Redis缓存击穿穿透雪崩及限流的概念 #### 缓存击穿 (Cache Breakdown) 当某个热点键(即访问频率极高的键)突然失效时,如果此时大量并发请求同时到达并尝试获取该键对应的值,则会直接打到数据库上,造成数据库压力骤增甚至崩溃的现象称为缓存击穿。 为了防止这种情况发生,通常采用以下几种方法来应对: - **加锁机制**:对于高并发场景下的热点key操作,可以在读取缓存前加上分布式锁。只有获得锁的服务实例才能去查询DB并将结果写回缓存[^3]。 - **设置合理的过期时间**:避免所有缓存项在同一时刻集体到期,可以通过随机化每个缓存条目的TTL(Time To Live),使得它们不会集中在一个时间段内全部过期[^4]。 - **逻辑过期方案**:除了物理删除外还可以给缓存记录附加一个额外的时间戳字段表示其实际有效期;即使超过了这个期限也不会立即清除而是标记为已过期状态等待下一次更新后再真正移除。 ```python import time from redis import StrictRedis def get_with_logical_expiry(redis_client, key): value = redis_client.get(key) if not value: return None data, expiry_time_str = value.split('|') current_time = int(time.time()) expiry_time = int(expiry_time_str) if current_time >= expiry_time: # 已经过期,返回None让调用者重新加载数据 return None return data ``` --- #### 缓存穿透 (Cache Penetration) 指的是恶意攻击者故意构造不存在的数据ID进行查询,由于这些ID对应的数据根本就不存在于数据库中,所以每次都会导致穿透整个缓存层直抵底层存储系统,从而浪费资源并可能引发性能瓶颈。 针对这一现象的有效措施有: - **缓存空对象**:对于确实不存在的数据,在第一次查库确认之后将其置入缓存一段时间,这样后续相同的请求就可以直接命中缓存而无需再次访问数据库了。 - **布隆过滤器(Bloom Filter)**:这是一种空间效率非常高的概率型数据结构,能够快速判断某元素是否属于集合之一员。虽然存在一定误判率但是非常适合用来做前置拦截以减少不必要的缓存查找次数[^1]。 ```python class BloomFilter(object): def __init__(self, size=500000, hash_num=7): self.bit_array = bitarray(size) self.bit_array.setall(0) self.hash_functions = [] for i in range(hash_num): seed = random.randint(0, MAX_SEED) self.hash_functions.append(mmh3.Hash(seed)) def add(self, item): for f in self.hash_functions: pos = f(item) % len(self.bit_array) self.bit_array[pos] = True def test(self, item): for f in self.hash_functions: pos = f(item) % len(self.bit_array) if not self.bit_array[pos]: return False return True ``` --- #### 缓存雪崩 (Cache Avalanche) 指因为某些原因导致大量的缓存在同一时间内几乎同时失效,进而引起瞬间爆发式的流量冲击后端服务的情况。为了避免此类事件的发生,建议采取如下预防手段: - **分片处理**:将不同类型的业务按照一定规则划分成多个独立的小模块各自维护自己的私有缓存区域,以此降低全局性灾难发生的可能性[^2]。 - **引入熔断保护机制**:一旦检测到异常高峰负载则自动启动紧急预案——如暂停部分非核心功能直至恢复正常运作为止。 --- #### 流量控制(Limiting Flow Control) 通过配置网关层面的限流组件(例如Nginx或Spring Cloud Gateway中的Rate Limit插件),可以有效地限制单位时间内允许通过的最大请求数目,从而减轻上游服务器的压力并提高系统的整体稳定性。 ```yaml spring: cloud: gateway: routes: - id: rate_limit_route uri: lb://example-service predicates: - name: RequestRateLimiter args: redis-rate-limiter.replenishRate: 10 redis-rate-limiter.burstCapacity: 20 ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值