Redis中几个简单的概念:缓存穿透/击穿/雪崩,别再被吓唬了
Redis中几个“看似”高大上的概念,经常有人提到,某些好事者喜欢扣概念,嘴巴里冒出来的全是高大上的名词(互联网八股文???),呵呵!
其实这几个概念:缓存穿透/缓存击穿/缓存雪崩,有一个共通的相似之处,就是高并发下,某些原因导致缓存层失去了保护,导致后端的持久化层(数据库)承担较大压力的情形。
需要注意的是,这些问题发生的前提,需要有足够大的并发性,如果本身并发性不高,那些即便出现了这些个问题,也不会造成非常大的影响。
甚至极端地讲,只要代码的健壮性足够,即便是缓存层全部宕机,也不会导致整个应用程序的崩溃,只不过是所有的请求都指向后端的持久化数据库层罢了。
试问,排出一些低级的问题包括方案,君见过多少请求压垮数据库的场景,或者数据缓存流行之前应用程序就应付不了高并发?
使用缓存,更多的进一步改善性能或者并发,而不是因为数据库被压垮了才使用缓存。
缓存穿透
缓存穿透本质上是查询一个缓存和数据库中都不存在的key值,Redis的缓存层无法命中,导致请求再次指向执行数据库层的情况。
由于是查询到值不存在(当然也不存在与Redis缓存中),导致请求总是“穿透”Redis发往数据库层,因此缓存层失去了“保护”关系数据库层的意义。
解决方案:
布隆过滤器是一个比较好的选择,参考:https://www.cnblogs.com/wy123/p/11571215.html
缓存击穿
强调对于某些热点key,缓存穿透本质上是高并发地请求一个缓存中不存在,但是数据库中存在的key值,导致并发请求指向数据库,导致数据库端承担大量的请求压力的情况,本质上跟缓存穿透一样。
主要侧重的是并发&&“热点”Key不存在与缓存中,导致请求指向数据库层。
解决方案:
这种场景可以从代码逻辑层面优化,从缓存中查询不到数据,再次将请求转向数据库中的时候,锁定该key,获取到该key之后,将该key写入缓存,伪代码如下
value = get_value_from_redis(key1) if not value: if exclusiveness_lock(key1):#成功排他性锁定目标,请求指向数据库 value = get_value_from_mysql(key1) if value: write_key_to_redis(key1,value) else:#无法获取排他性锁,间隔0.1s之后再次查询缓存 time.sleep(0.1) # 再次从缓存中查询 get_value_from_redis(key1)
缓存雪崩
某些原因,比如:
1,Redis实例(主从,集群,哨兵等等)故障。
2,Redis中的key由于过期时间已到,自动过期。
3,由于Redis内存策略导致(maxmemory,maxmemory-policy配置)某些key失效(过期,被清理出缓存等)。
如果此时出现高并发的请求出现,这些请求会全部指向数据库层,缓存层失去了对数据库层的保护,导致数据库承担绝大压力的情况。
解决方案:
1,Redis层的高可用,保证缓存层可以有效地保护数据库层
2,从Redis配置(内存管理策略maxmemory,maxmemory-policy)以及结合业务,避免某些潜在的热点key值过期
3,应用程序端限流,或者通过队列的方式等削峰的方式来保护后端数据库
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?