💫《博主主页》:
🔎 CSDN主页__奈斯DB
🔎 IF Club社区主页__奈斯、
🔥《擅长领域》:擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控;并对SQLserver、NoSQL(Redis)有了解
💖如果觉得文章对你有所帮助,欢迎点赞收藏加关注💖
作为DBA或运维在日常与Redis打交道时,往往更关注部署安装🔧、Key清理🧹、内存回收💾、备份恢复🔄等这些运维层面的问题,也就是非业务相关的问题。但大家否深入思考过:
❓为什么现代数据库架构中需要引入Redis做缓存?
❓不同的NoSQL在缓存场景下各有怎样的特性?
❓当高并发来临时,缓存穿透、击穿、雪崩这些问题究竟会对系统造成什么影响?
博主在此之前也没有考虑过这些问题(应该大部分DBA或者运维都没有考虑过这些问题,因为引用缓存技术,以及缓存策略(穿透/击穿/雪崩的防治)通常被视为研发的职责范畴)
,因为DBA或者运维更多的是关心NoSQL本身的稳定性保障,直到亲身经历了一次高并发场景下的缓存雪崩事故,才意识到意识到这些业务逻辑对运维人的重要性。
那么今天这篇文章就从业务角度出发,一起来了解和学习一下互联网数据库架构演进中Redis缓存的技术必然性,以及其他NoSQL在缓存场景下的特点比较,并在高并发场景下缓存穿透、缓存击穿、缓存雪崩的体系化解决方案。
写这篇文章的初衷是想让不懂为什么加缓存技术的小伙伴们明白,此篇文章的内容来源于B站UP主“遇见狂神说”中的前部分视频讲解内容,博主在文章中对内容稍加润色,并对流程图重新构图加以个人理解。那么正好也借此机会推荐给大家这个Redis好课,在B站上搜索“遇见狂神说”UP主,就可以搜索到他讲的Redis课程,UP主是个大佬,Redis讲的非常通透,最最最主要的是UP主是无偿且免费的把Redis这套课程分享出来的(免费!香!)
,并且视频中的相关讲解UP主也愿意让学习过的小伙伴进行整理和分享,免费是情谊,收费是本分,感谢大佬为爱发电💞,为我们带来了如此宝贵的学习资源。
20世纪90年代:数据库的单机时代:
在互联网发展初期,网站访问量普遍较小,许多网站仍以静态HTML页面为主。由于用户请求量有限,应用服务器和数据库服务器的负载压力并不大。因此,单台关系型数据库(如MySQL)足以满足数据存储和查询的需求。这一阶段的架构简单直接,甚至数据库服务和应用部署在同一台机器上,无需复杂的分布式设计或性能优化。
那么这一时期的Web应用主要呈现以下特点:
- 静态内容占绝对主导,动态请求占比很低
- 单台MySQL数据库完全能够满足存储和查询需求
- 应用服务器和数据库服务器都承受着极小的压力
此时的典型架构如下:
架构图说明 Web服务器:
- 请求分发中心
- 接收所有HTTP请求(GET/POST)
- 区分静态请求(.html/.jpg)和动态请求(.php/.asp)
- 静态请求直接返回文件,动态请求转发给后端处理
- 基础服务支撑
- 单进程/单线程模型(早期Apache的prefork模式)
- 不支持keep-alive(每个请求新建TCP连接)
- 典型配置:Pentium 100MHz CPU + 32MB内存
MySQL 数据库层:
- 数据库用于持久化存储应用的核心数据,例如用户、订单、商品等结构化数据。
- 数据库层需要处理事务、并发访问、数据一致性等问题。
- 数据库也提供了 ACID 特性,保证数据的可靠性和完整性。
21世纪00年代,大数据时代:
随着互联网的发展和数据量的不断增长,传统单台数据库在处理海量数据时逐渐暴露出性能瓶颈。以下是一些常见的问题:
- 存储瓶颈: 随着数据的激增,单台服务器的磁盘空间逐渐不足。单一磁盘和服务器无法满足日益增长的数据存储需求。
- 单表数据量过大: 例如,当一张表的数据量达到几百万条时,查询操作将会消耗大量内存,导致性能下降,且在没有合理优化的情况下,查询速度会急剧下降。
- 高并发访问: 随着访问量增加,单台数据库服务器可能无法承受来自多个用户的并发请求。每秒钟的查询次数(QPS)会造成数据库的负载过重,导致响应时间延迟。
- 查询效率低: 当大量用户频繁查询相同的数据时,数据库不断重复执行相同的查询操作,使得查询效率下降,严重时可能会导致数据库崩溃。
- …
在大数据和高并发的背景下,提升查询效率成为了一个至关重要的课题。传统的数据库虽然是存储数据的核心技术,但随着数据量的增加,单台数据库在高并发场景下的响应时间会急剧上升,甚至导致系统性能瓶颈。为了应对这些挑战,技术进步经历了几个阶段,从最初的数据库结构和索引优化,到文件缓存和磁盘I/O优化,再到如今的缓存技术,特别是Redis等内存缓存技术的应用。
首先,数据库通过优化表结构和索引
来提升查询效率。这些优化可以减少扫描全表的操作,快速定位所需数据,进而提升查询速度。然而,随着数据量的剧增,这种优化方式逐渐显得力不从心,尤其是在面对高并发请求时,数据库的负载急剧增加,查询性能出现瓶颈。
随着技术的发展,文件缓存和磁盘I/O优化
成为了重要的提升手段。特别是SSD(固态硬盘)的普及,使得磁盘I/O性能得到了显著提升。文件缓存通过将部分数据存储在磁盘上,以减少数据库的频繁读写,从而减轻数据库的压力。然而,磁盘I/O的速度毕竟不如内存,因此,文件缓存虽然有效,但也有限。
既然磁盘I/O的速度毕竟不如内存,那么能不能将数据库中的数据缓存到内存中用来提高查询效率呢❓答案是当然可以,举一个例子💫,在一般情况下网站80%的情况都是在读,高并发的去查询单台数据库的话就会增加查询响应时间,比如张三查询了1号商品,李四也同样去查询了一样的1号商品,都是同样的查询操作,每次都要去查询数据库的话让压力本来就很大的数据库更加雪上加霜,因此能不能让多次不变的1号商品做成缓存,让李四或者其他同样想查询1号商品的用户直接可以在缓存中调用1号商品,而避免再次在数据库中查询呢?为了解决这一问题,缓存技术孕育而生,缓存技术是解决上述问题的关键技术之一。
那么,缓存技术的核心目标是:减少对数据库的访问,避免频繁执行重复的查询操作
。缓存通过将热点数据保存在内存中,首先检查缓存中是否有该数据,若有,则直接从缓存中读取,避免了对数据库的多次查询。这不仅提升了响应速度,还显著降低了数据库的压力,尤其在高并发的场景下,缓存能够有效减轻数据库的负担,提升系统的整体性能。
其中,Redis作为一种高效的内存键值数据库
,成为了最常用的缓存解决方案。它以其超低的延迟和高效的读写性能,尤其适用于需要处理大量并发请求的应用场景。例如,电商平台、社交媒体等高访问量的应用,通过将热点数据存储在Redis缓存中,避免频繁访问数据库,从而提升系统性能。缓存不仅减少了数据库的压力,还改善了用户的体验,尤其是在响应速度上。
那么总结一下缓存的作用:
- 提高查询效率: 缓存将高频访问的数据存储在内存中,避免每次都去查询数据库,极大地提高了响应速度。
- 减少数据库负载: 通过缓存,数据库的查询压力得以减少,尤其是在高并发的情况下,缓存能够有效地减轻数据库的负担。
- 提升用户体验: 减少查询延迟,提升用户对系统的响应速度和体验。
在总结一下缓存的工作原理:
缓存将数据存储在快速访问的存储介质(如内存)中,每当用户发起查询时,系统首先检查缓存中是否有该数据。如果数据存在,就直接从缓存中读取,避免了对数据库的多次访问。这种机制不仅加快了查询速度,也大幅降低了数据库的压力。
不过,缓存技术并不是万能的,它主要用于加速对高频访问数据的读取,而对于大多数长期存储的数据,传统的关系型数据库依然不可替代。
因此,缓存技术往往与数据库的读写分离技术结合使用,以进一步优化系统性能。通过ProxySQL等工具,可以实现数据库的读写分离,将写操作集中在主数据库上,而将读操作分散到多个从数据库上,这样可以有效提高系统的并发处理能力。
从最初的数据库结构优化,再到文件缓存和磁盘I/O优化,再到缓存技术与传统关系型数据库的结合(发展过程:优化数据结构和索引---->文件缓存(磁盘IO性能的提升,比如SSD全闪盘)---->然后才到缓存技术,也就是NoSQL)
,整个技术演变使得高并发场景下的性能瓶颈得到了有效解决。Redis与传统关系型数据库的结合(NoSQL+RDBMS技术)
,形成了一个高效的协作机制:Redis负责缓存高频访问的数据,而数据库则存储长期数据。两者协同工作,使得系统能够在面对大量请求时保持高效运行。
架构图说明 Redis 缓存层:缓存层不仅仅可以是Redis,也可以是Memcached(缓存,内存数据库)。不仅仅NoSQL数据库可以做缓存,其实只要带有缓存技术的都可以在缓存层。
- 缓存存储:Redis 用于存储高频查询的数据,例如用户信息、热门商品、常见查询结果等。
- 缓存策略:采用合适的缓存过期策略(TTL,Time-To-Live)来确保缓存数据不会过期。可以使用 LRU(Least Recently Used) 策略来避免缓存溢出。
- 异步更新:通常,缓存的数据会有一定的过期时间,过期后缓存失效。数据库中的数据变化时,可以触发缓存的更新(例如,更新操作后删除对应的缓存)。
MySQL 数据库层:
- 数据库用于持久化存储应用的核心数据,例如用户、订单、商品等结构化数据。
- 数据库层需要处理事务、并发访问、数据一致性等问题。
- 数据库也提供了 ACID 特性,保证数据的可靠性和完整性。
21世纪10年代:多元数据时代
在2010至2020年间,世界经历了巨大的变化,尤其是在信息技术和互联网的飞速发展下,出现了许多以前未曾存在的数据类型。例如,互联网中的地图定位信息、音乐视频信息、新闻热榜信息等,这些信息不再仅仅是文本数据
,而是变得更加多元化,涵盖了图片、音频、视频、地理位置等多种数据形式。
随着这些多元数据的涌现,传统的关系型数据库,尤其是MySQL,在存储大文件、图片等信息时面临着巨大的挑战。特别是在查询时,MySQL的效率显著降低,数据库的压力急剧上升。原因在于,单一的MySQL数据库已无法满足存储这些复杂、多元化数据的需求。因此,必须研发新的数据库类型来应对这些变化。例如,专门用于存储定位信息的数据库、用于存储大文件的数据库,或是图数据库,专门用于存储图片等数据。
此外,随着互联网的普及,用户的个人信息、社交网络、地理位置、音乐视频、以及用户自己产生的数据(如日志等)都在爆发式增长。与传统的行列数据存储方式不同,这些数据往往呈现出无序、动态变化的特点。例如,社交网络和地理位置数据是一个动态发展的图谱,新闻热榜则需要实时更新。这些数据不适合传统的关系型数据库,以表格中的行或列来存储。
为了解决这些问题,技术发展引入了NoSQL技术,提供了更加灵活和高效的方式来处理这类动态、无序的数据。NoSQL数据库能够更好地适应这些数据的存储需求,其横向扩展性使得存储和处理这些数据变得更加可行。
架构图说明 API网关:
统一接入层,负责协议转换、限流鉴权等,典型技术:Kong/Nginx
统一数据服务层UDSL:
Unified Data Service Layer, UDSL,是一种用于整合和管理企业内部各种数据源的中间层
数据存储层(核心组件):
- MySQL集群:
- 分库分表:用户订单按user_id哈希分片
- GTID复制:全局事务标识保证主从一致性
- 典型场景:银行交易、库存管理等ACID场景
- MongoDB分片集群:
- 自动分片:基于shard key自动平衡数据
- 文档版本控制:MVCC并发控制
- 典型场景:CMS系统、产品目录
- Neo4j集群:
- 原生图存储:免索引邻接设计
- Cypher查询:声明式图查询语言
- 典型场景:社交关系、推荐系统
- InfluxDB集群:
- 时间分片:按时间范围自动分区
- 连续查询:实时聚合时序数据
- 典型场景:IoT设备监控、应用指标
- Redis生态圈:
- RedisJSON:支持JSON文档操作
- RedisGraph:图数据库功能
- 典型场景:会话缓存、实时排行榜
数据湖:
- 数据集成:通过各数据库的变更捕获机制(如MySQL binlog)集中原始数据
- 典型技术:Apache Kafka + Delta Lake
- 用途:离线分析、机器学习训练
Redis介绍
Redis(Remote Dictionary Server,即远程字典服务),简称Redis。是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API, 并且免费和开源!
redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
Redis 是一个高性能的key-value数据库。 redis的出现,很大程度补偿了memcached这类key/value存储的不足,在部 分场合可以对关系数据库起到很好的补充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等客户端,使用很方便。
Redis支持主从同步。数据可以从主服务器向任意数量的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。这使得Redis可执行单层树复制。存盘可以有意无意的对数据进行写操作。由于完全实现了发布/订阅机制,使得从数据库在任何地方同步树时,可订阅一个频道并接收主服务器完整的消息发布记录。同步对读取操作的可扩展性和数据冗余很有帮助。
redis的官网地址,非常好记,是redis.io。(域名后缀io属于国家域名,是british Indian Ocean territory,即英属印度洋领地),Vmware在资助着redis项目的开发和维护。
从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。
并且Redis推荐在Linux上搭建,不推荐在windows上搭建。
Redis性能方面的表现:
下面是官方的bench-mark数据:
测试完成了50个并发执行100000个请求。
设置和获取的值是一个256字节字符串。
Linux box是运行Linux 2.6,这是X3320 Xeon 2.5 ghz。
文本执行使用loopback接口(127.0.0.1)。
结果: 读的速度是110000次/s,写的速度是81000次/s。
Redis的特性:
特性 描述 内存存储 Redis 是内存数据库,所有数据存储在内存中,提供非常高的读写性能。 数据结构丰富 支持多种数据结构:String、List、Set、Sorted Set、Hash、Bitmap、HyperLogLog、Geospatial。 高性能 提供低延迟(微秒级别)和高吞吐量,适合高并发、高吞吐量应用场景。 持久化机制 提供 RDB 快照和 AOF 日志持久化方式,确保数据持久性。可配置混合持久化模式。 高可用性 通过 Redis Sentinel 提供自动故障转移和高可用性。 分布式支持 支持 Redis Cluster,提供自动分片和水平扩展。 事务支持 支持事务,通过 MULTI、EXEC、WATCH实现命令的原子执行。 Lua 脚本支持 支持在服务器端执行 Lua 脚本,实现原子操作,减少客户端与服务器的交互。 发布/订阅模式 支持 Pub/Sub 模式,允许客户端订阅频道并实时接收消息。 轻量级和易部署 Redis 非常轻量,易于启动和部署,支持单机及分布式部署。 内存管理策略 提供 LRU、LFU 等内存淘汰策略,确保有效利用内存资源。 强一致性保证 Redis 提供强一致性,支持复制和故障转移机制。 客户端支持 支持多种编程语言的客户端,包括 Java、Python、Go、Node.js、C、C++、PHP、Ruby 等。 应用场景广泛 用于缓存、消息队列、排行榜、实时数据分析、会话存储等多种场景。
NoSQL分类
什么是NoSQL:
NoSQL = Not only SQL(不仅仅是SQL),泛指非关系型数据库。也就是存储新时代中的多元化数据。比如专门储存定位信息的数据库,专门存储大文件的数据库,专门存储图片的图关系数据库,等等等。
NoSQL的特点:
- 方便扩展,数据之间没有关系,不需要过多的操作就可以横向扩展。
- 大数据量高性能。官方测试Redis一秒写8万次,读取11万次。NoSQL的缓存记录级是一种细粒度的缓存,性能会比较高
- 数据类型是多样型的。对于关系型数据库需要事先设计数据的表结构(现实中很少有人可以通过三大范式把数据库设计的很好),对于NoSQL而言不需要事先设计数据库,随取随用。
RDBMS关系型数据库和NoSQL非关系型数据库的区别:
关系型数据库 非关系型数据库 结构化数据 不仅仅是数据。非结构化数据,多元化数据结构 有特定的SQL语句 没有固定的查询语句 数据和关系都存在单独的表中(row行、column列) 键值对存储,列存储,文档存储,图形数据库(社交关系) 数据定义语言(DML、DDL、DQL、DCL、TCL) 严格的一致性(遵循ACID特性) 最终一致性 基础的事务 CAP定理和BASE(异地多活、) 高性能、高可用、高扩展性 高性能、高可用、高扩展性 … …
NoSQL的四大分类:
- 内存键值存储(Key-value stores):redis、memcached、Tair、Voldemort、Oracle BDB
- 文档存储(Document stores):mongoDB、conthDB
- 列存储数据库:Redshift、BigQuery、Snowflake、HBase、分布式文件系统。注意:关系型数据库大多以行存储
- 图关系数据库(Graph DBMS):Neo4j、infoGrdid、Infinite Graph。注意:图关系数据库存的不是图形,而是存放图关系的。比如:朋友圈社交网络、广告推荐等
分类 举例 典型应用场景 数据模型 优点 缺点 内存键值存储(Key-value stores) redis、memcached、Tair、Voldemort、Oracle BDB 内容缓存,主要用于处理大量数据的高访问负载,也用于一些日志系统等等。 Key 指向Value 的键值对,通常用hash table来实现。 查找速度快 数据无结构化,通常只被当作字符串或者二进制数据 文档存储(Document stores) mongoDB、conthDB Web应用(与Key-Value类似,Value是结构化的,不同的是数据库能够了解Value的内容) Key-Value对应的键值对,Value为结构化数据 数据结构要求不严格,表结构可变,不需要像关系型数据库一样需要预先定义表结构 查询性能不高,而且缺乏统一的查询语法。 列存储数据库 Redshift、BigQuery、Snowflake、HBase、分布式文件系统 分布式的文件系统 以列簇式存储,将同一列数据存在一起 查找速度快,可扩展性强,更容易进行分布式扩展 功能相对局限 图关系数据库(Graph DBMS) Neo4J、InfoGrid、Infinite Graph 社交网络、推荐系统等。专注于构建关系图谱 图结构 利用图结构相关算法。比如最短路径寻址,N度关系查找等 很多时候需要对整个图做计算才能得出需要的信息,而且这种结构不太好做分布式的集群方案
互联网架构演变 + Redis初探 + NoSQL分类介绍的讲解到这里就算完成了!相信看完的小伙伴们对缓存技术的理解已经焕然一新了✨。不过一个人的精力毕竟是有限的🕶️,文章中可能有些细节没覆盖全面,欢迎各位大佬评论区拍砖补充 💬,提出改进意见。
各位看官可以休息一下,摸鱼10分钟🕒…
下一站高能预警 🚨: 直击高并发三大缓存问题——
🔥 缓存穿透(请求像穿了隐身衣👻)
💥 缓存击穿(热点数据突然暴毙💣)
❄️ 缓存雪崩(集体去世的惨案🏔️)
一、缓存穿透(Cache Penetration)
理解缓存穿透:
缓存穿透是指查询一个在数据库中肯定不存在的数据。为了避免每次请求都直接访问数据库,我们通常会使用缓存来提高查询效率。
正常的缓存使用流程大致如下:
- 查询缓存:首先,会检查缓存中是否存在需要的数据。如果缓存中有数据,就直接返回,不需要访问数据库。
- 缓存失效或不存在数据:如果缓存中没有数据,或者缓存的数据已经过期,那么系统会访问数据库去查找数据。
- 查询结果为空:如果数据库中查询到的数据为空(即数据确实不存在),那么我们不会把这个空结果存入缓存。
举个例子,比如我传一个用户 id 为 -1,这个用户 id 在缓存里面是肯定不存在的,所以会去数据库里面查询,如果有搞事情的人,大批量请求并传用户 id 为 -1,那就和没用 redis 一样,导致数据库压力过大而崩溃。
总结来说,缓存穿透问题就是指我们查询的那个数据本来就不存在,而这种查询没有被有效地拦截,导致每次都要访问数据库,造成缓存的无效使用。
解决方法:
- 接口层增加校验:不合法的参数直接返回(如ID格式、范围限制)。不相信任务调用方,根据自己提供的 API 接口规范来,作为被调用方,要考虑可能任何的参数传值。
- 缓存空值:在缓存查不到,DB 中也没有的情况,可以将对应的 key 的 value 写为 null,或者其他特殊值写入缓存,同时将过期失效时间设置短一点(如30秒),以免影响正常情况。这样是可以防止反复用同一个 ID 来暴力攻击。
if (data == null) { cache.set(key, null, 30); // 缓存空值 }
- 网关设置阈值:正常用户是不会这样暴力功击,只有是恶意者才会这样做,可以在网关 NG 作一个配置项,为每一个 IP 设置访问阈值。
- 布隆过滤器:高级用户布隆过滤器(Bloom Filter), 这个也能很好地防止缓存穿透。原理就是利用高效的数据结构和算法快速判断出你这个 Key 是否在 DB 中存在,不存在你 return 就好了,存在你就去查了 DB 刷新 KV 再 return。
二、缓存击穿(Cache Breakdown)
理解缓存击穿:
缓存击穿是指某个缓存中的热点数据(即频繁访问的数据)在短时间内失效,导致大量并发请求绕过缓存,直接访问数据库。这种情况就像是屏障上的一个洞,导致数据查询瞬间变得非常慢。
具体来说,当一个非常热门的缓存数据失效时,如果没有其他机制来保护,所有的并发请求都会直接去访问数据库,给数据库带来巨大的压力。这样,原本应该由缓存处理的请求就会集中到数据库,造成性能瓶颈,甚至可能导致数据库崩溃。
举个例子,好比秒杀某一个商品或者某个top实时热搜,这个key一直在缓存中,但缓存是有过期时间的,假如这个key是1800秒(30分钟)过期,1800秒后这个key还是非常热点,但key过期了,那么会直接在数据库中进行查询,查询到后放入缓存中,在放入缓存这段过程,虽然时间很短很短,比如只有0.1秒,但就是这0.1秒会直接让数据库并发激增,甚至导致宕机。
解决方法:
- 互斥锁:在缓存失效时,为获取数据的请求加锁(如Redis的SETNX),确保只有一个请求去查询数据库并更新缓存,其他请求等待获取缓存更新后的结果。
String value = cache.get(key); if (value == null) { if (lock.tryLock()) { // 获取分布式锁 try { value = db.get(key); // 查数据库 cache.set(key, value); } finally { lock.unlock(); } } }
- 提前更新缓存:在数据更新时,提前刷新相关缓存,以避免缓存失效。
- 热点数据永不过期(慎用):对极热点数据不设过期时间,通过后台任务定期更新,充分把 Redis 高吞吐量性能利用起来。
- 逻辑过期:不设置物理过期时间,而是在value中存储过期时间。业务逻辑判断是否过期,异步更新缓存。
三、缓存雪崩(Cache Avalanche)
理解缓存雪崩:
缓存雪崩是指在同一时间,大量缓存数据同时失效,导致大量请求直接访问数据库。这样会给数据库带来极大压力,甚至可能导致数据库崩溃。
举个例子,双十一期间,凌晨12点会迎来抢购高峰期,热点商品都会放在缓存中,假设缓存1小时,那么到凌晨1点这批热点数据就会批量过期,那么就会导致大量的商品直接在数据库中进行查询,直接让数据库并发激增,导致宕机。
还有就是缓存数据库异常宕机,大量缓存同时失效,导致所有请求涌向数据库。
解决方案:
- 分散过期时间:为缓存key设置分散的过期时间(如基础时间+随机偏移量),避免同一时间大量缓存同时失效。
cache.set(key, value, baseTime + random.nextInt(300)); // 基础时间+随机秒数
- 提前预热缓存:在系统负载较低时,提前加载重要的数据到缓存中。
- 使用多级缓存:采用多层级缓存(如本地缓存+Redis),避免单点故障。
- 高可用架构:Redis集群部署(主从+哨兵/Cluster模式),避免全盘崩溃。
- 接口限流:当访问的不是核心数据的时候,在查询的方法上加上接口限流保护。
总结一下:
- 缓存穿透: 查询一个 不存在的数据,缓存和数据库都没有,导致每次请求都直接访问数据库(如恶意请求不存在的ID)。
- 缓存击穿: 某个 热点key过期 时,大量并发请求同时穿透缓存,直接访问数据库。
- 缓存雪崩: 大量缓存key同时失效或缓存服务宕机,导致所有请求涌向数据库。
问题 触发条件 核心解决方案 缓存穿透 查询不存在的数据(如恶意请求不存在的ID)。 1、接口层增加校验
2、缓存空值
3、网关设置阈值
4、布隆过滤器缓存击穿 热点key突然失效 1、互斥锁
2、提前更新缓存
3、热点数据永不过期(慎用)
4、逻辑过期缓存雪崩 大量key同时失效/服务宕机 1、分散过期时间
2、提前预热缓存
3、使用多级缓存
4、高可用架构
5、接口限流
呼,关于这篇的内容到这里就结束啦!🎉 尤其是文章中的6个示意图,花了接近4小时精心绘制⏳,就是希望能更直观地展现原理,让枯燥的文字变得生动易懂💡。看在博主爆肝作图、疯狂掉发的份上😝,各位大佬赏个三连吧👍⭐💬!也让博主有更多的动力去认真撰写后续的博客~🚀