📚 高级篇 01. 多级缓存 - 什么是多级缓存与终极架构演进
一、 认知颠覆:为什么有了 Redis 还需要多级缓存?
在之前的架构中,我们的请求链路是这样的:
前端请求 -> Nginx (转发) -> Tomcat (Java业务逻辑) -> Redis (分布式缓存) -> MySQL (数据库)
💥 传统架构的“三大致命瓶颈”:
- 网络带宽瓶颈: 如果一个极其火爆的商品页面(假设 1MB 大小),瞬间涌入 10 万人查看。Tomcat 需要从 Redis 读取数据并返回给前端,瞬间产生 100GB 的网络流量,机房的交换机和网卡会直接瘫痪。
- Tomcat 并发瓶颈: Tomcat 作为 Servlet 容器,虽然性能不错,但在海量并发下,线程上下文切换的开销极大。当请求打到 Tomcat 时,它的吞吐量往往成为整个系统的短板。
- Redis 热点 Key 瓶颈: 哪怕你用了分片集群,但对于极其火爆的“单个热点商品”,请求最终还是会全部打到集群中的某一台 Master 节点的同一个哈希槽上,导致该节点 CPU 直接 100% 熔断。
二、 破局方案:多级缓存的宏大版图
多级缓存的核心思想:让缓存无限逼近用户!
能不走网络的尽量不走网络,能不到 Tomcat 的尽量不到 Tomcat。我们将缓存像套娃一样,一层一层地挡在数据库前面。
一个标准的工业级多级缓存架构,通常包含以下 4 道防线:
🛡️ 第 1 道防线:浏览器/客户端本地缓存
- 位置: 用户的手机 App 或浏览器中。
- 机制: 对于静态资源(CSS、JS、固定图片),通过 HTTP 的
Cache-Control或前端本地存储直接缓存。 - 效果: 零网络延迟,请求根本发不出用户的手机!
🛡️ 第 2 道防线:Nginx 边缘缓存 (网关层) ⚡核心
- 位置: 离用户最近的机房 Nginx 服务器(或者 CDN 节点)。
- 机制: Nginx 极其擅长处理高并发。我们甚至可以直接在 Nginx 里写业务逻辑(利用 OpenResty + Lua 脚本),让 Nginx 直接读取本地缓存或 Redis 缓存并返回结果!
- 效果: 拦截了 80% 以上的读请求,这些请求根本连 Tomcat 的大门都进不去,极大地保护了后端的 Java 服务器。
🛡️ 第 3 道防线:Tomcat 本地进程缓存 (JVM 缓存)
- 位置: Tomcat 所在的 Java 进程内存中。
- 机制: 使用 Caffeine 或 Guava Cache 等本地缓存框架。
- 效果: 当 Nginx 把少量的请求放行到 Tomcat 时,Tomcat 先查自己 JVM 内存里的数据。没有网络 I/O 开销,读取速度达到纳秒级 (ns)! 完美解决 Redis 的热点 Key 问题。
🛡️ 第 4 道防线:Redis 分布式缓存
- 位置: 独立的 Redis 集群。
- 机制: 只有当 Tomcat 本地缓存也未命中时,才会通过网络去请求 Redis。Redis 充当了海量数据的公共资源池。
🏥 最后的兜底:MySQL 数据库
只有当以上 4 道防线全部被击穿时,请求才会悲壮地落到 MySQL 上。
三、 多级缓存架构的技术栈预览 (剧透)
为了搭建这套极其强悍的架构,在接下来的学习中,我们将接触到一系列全新的顶级技术栈:
- Caffeine (咖啡因): 目前 Java 领域性能最强悍的本地缓存框架,碾压 Guava Cache,是 Spring 官方推荐的缓存底座。
- Lua 脚本语言: 一门极其轻量级、极速的脚本语言。
- OpenResty: 基于 Nginx 的高性能 Web 平台,允许我们在 Nginx 中运行 Lua 脚本,直接操作 Redis 和 Tomcat,把 Nginx 变成一个超级网关!
- Canal (阿里开源组件): 这是多级缓存中最难的一环——缓存一致性问题的终极杀器。当 MySQL 数据修改时,如何瞬间通知 JVM 缓存和 Redis 缓存进行更新?Canal 可以伪装成 MySQL 的从节点,监听 Binlog 实现毫秒级的数据同步!
学习总结
“多级缓存”不仅仅是一种技术的堆叠,更是一种**“流量层层漏斗”**的宏大架构思想。
从这一节开始,你的关注点将不再局限于单一的组件(如 Redis),而是要站在全局的上帝视角,统筹整个系统的流量分发与数据流转。这正是初级程序员蜕变为高级架构师的必经之路。