什么是多级缓存

传统的缓存策略一般是请求到达Tomcat后,先查询Redis,如果未命中则查询数据库,如图:

image-2

存在下面的问题:

  • 请求要经过Tomcat处理,Tomcat的性能成为整个系统的瓶颈
  • Redis缓存失效时,会对数据库产生冲击

多级缓存就是充分利用请求处理的每个环节,分别添加缓存,减轻Tomcat压力,提升服务性能:

  • 浏览器访问静态资源时,优先读取浏览器本地缓存
  • 访问非静态资源(ajax查询数据)时,访问服务端
  • 请求到达Nginx后,优先读取Nginx本地缓存
  • 如果Nginx本地缓存未命中,则去直接查询Redis(不经过Tomcat)
  • 如果Redis查询未命中,则查询Tomcat
  • 请求进入Tomcat后,优先查询JVM进程缓存
  • 如果JVM进程缓存未命中,则查询数据库

image-3

在多级缓存架构中,Nginx内部需要编写本地缓存查询、Redis查询、Tomcat查询的业务逻辑,因此这样的nginx服务不再是一个反向代理服务器,而是一个编写业务的Web服务器了

因此这样的业务Nginx服务也需要搭建集群来提高并发,再有专门的nginx服务来做反向代理。另外,我们的Tomcat服务将来也会部署为集群模式。

可见,多级缓存的关键有两个:

  • 一个是在nginx中编写业务,实现nginx本地缓存、Redis、Tomcat的查询
  • 另一个就是在Tomcat中实现JVM进程缓存

其中Nginx编程则会用到OpenResty框架结合Lua这样的语言。

目录

多级缓存总结

image-38

1. 页面请求静态资源

  • 静态资源服务器:item.html页面部署在Nginx服务器上,同时承担静态资源服务器和反向代理服务器双重角色
  • 请求流程:用户浏览器请求页面时,Nginx直接返回静态HTML;页面渲染时通过ajax请求数据,请求地址格式为item/{id}
  • 反向代理特性:Nginx不处理业务逻辑,仅将数据请求代理给后端OpenResty集群

2. openResty本地缓存

  • 缓存机制:使用shared dict实现本地缓存,请求到达后优先查询内存中的缓存数据
  • 集群限制:本地缓存仅在当前Nginx进程有效,集群环境下不同节点内存不共享
  • 解决方案:
    • 负载均衡配置基于商品ID哈希路由(非轮询)
    • 相同ID始终路由到同一OpenResty节点,确保缓存命中率
    • 修改负载均衡算法为基于URL地址的哈希策略

3. openResty查询Redis缓存

  • 二级查询:本地缓存未命中时查询Redis集群
  • API操作:通过OpenResty提供的Redis操作接口访问缓存
  • 命中处理:若Redis命中则直接返回数据,否则继续向下游Tomcat查询

4. 查询Tomcat

  • 集群配置:Tomcat同样采用集群部署(示例中2个节点)
  • 缓存层级:
    • 进程缓存:Tomcat本地JVM缓存,集群间不共享
    • 查询顺序:先查进程缓存 → 未命中再查数据库
  • 路由策略:
    • 基于商品ID哈希路由确保请求一致性
    • 相同ID始终访问同一Tomcat节点
  • 多级缓存效果:
    • 第一级:OpenResty本地缓存
    • 第二级:Redis缓存
    • 第三级:Tomcat进程缓存
    • 最终才访问数据库

5. 数据同步问题

  • 同步挑战:数据库修改后需同步Redis/本地缓存/进程缓存
  • OpenResty方案:
    • 超时失效机制:设置缓存过期时间自动删除
    • 适用场景:低频更新数据(如商品基础信息)
  • Redis+Tomcat方案:
    • Canal监听MySQL binlog变更
    • 实时通知Java客户端更新Redis和本地缓存
    • 适用场景:高频更新且强一致性要求的数据
  • 混合策略:根据数据特性组合使用超时失效和实时同步机制