2.多级缓存方案

予早 2025-02-21 01:08:23
Categories: Tags:

多级缓存方案

目标

承载亿级流量

核心思路

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

缓存分类

缓存在日常开发中启动至关重要的作用,由于是存储在内存中,数据的读取速度是非常快的,能大量减少对数据库的访问,减少数据库的压力。我们把缓存分为两类:
分布式缓存,例如Redis:
优点:存储容量更大、可靠性更好、可以在集群间共享
缺点:访问缓存有网络开销
场景:缓存数据量较大、可靠性要求较高、需要在集群间共享

Caffeine

Caffeine是一个基于Java8开发的,提供了近乎最佳命中率的高性能的本地缓存库。目前Spring内部的缓存使用的就是Caffeine。GitHub地址:https://github.com/ben-manes/caffeine

进程本地缓存,例如HashMap、GuavaCache:
优点:读取本地内存,没有网络开销,速度更快
缺点:存储容量有限、可靠性较低、无法共享
场景:性能要求较高,缓存数据量较小

缓存链路

无缓存链路

  1. 客户端请求 Nginx
  2. Nginx 转发请求到 Tomcat
  3. Tomcat 查询数据库响应请求给Nginx
  4. Nginx 响应请求给客户端

分析:

进程缓存链路

  1. 客户端请求 Nginx
  2. Nginx 转发请求到 Tomcat
  3. Tomcat 线程访问进程中的缓存数据,命中则获取到数据
  4. 未命中则查询数据库
  5. Tomcat 响应请求给Nginx
  6. Nginx 响应请求给客户端

分析:

在【无缓存链路】的基础上,使用进程缓存减少数据库压力,理想情况下,缓存100%命中,此时性能瓶颈落在Tomcat上,另外分布式环境下,进程缓存会导致数据不一致,这使得进程缓存的应用受到限制

经典分布式缓存链路

  1. 客户端请求 Nginx
  2. Nginx 转发请求到 Tomcat
  3. Tomcat 首先查询 Redis 看是否命中缓存,命中则获取到数据
  4. 未命中则查询数据库获取到数据
  5. Tomcat 响应请求给 Nginx
  6. Nginx 响应请求给客户端

分析:

在【无缓存链路】方案的基础上,在数据库这里做了优化,优先从 Redis 中读取缓存数据,期望解决数据库性能瓶颈。假定缓存必然被命中,则此时性能瓶颈会转移到 Tomcat。即Tomcat处理该请求的耗时比直接请求缓存数据耗时还长得多。此时解决了分布式环境下若干台Tomcat缓存不一致问题,但Tomcat成为新的性能瓶颈这个问题并未解决。

缓存代理链路

在【经典分布式缓存链路】基础上,将缓存前移,使用专门的代理用于代理请求缓存,而非缓存请求则转发给Tomcat,由于 OpenResty 比 Tomcat 性能高,此时在链路上提高了性能

完全多级缓存链路

OpenResty 支持本地缓存,客户端也可以有一份缓存,Tomcat 进程缓存可以选择性使用

  1. 客户端缓存
  2. 缓存代理本地缓存
  3. 分布式缓存
  4. Web服务进程缓存

流程

  1. 客户端首先查看本地缓存,命中缓存则直接返回数据
  2. 未命中缓存,客户端请求 Nginx
  3. Nginx 转发请求到 OpenResty
  4. OpenResty 首先看是否命中本地缓存,若命中本地缓存则直接返回数据
  5. 未命中缓存,OpenResty 查询 Redis 看是否命中缓存,命中则获取到数据直接返回
  6. 未命中缓存则向 Tomcat 发起请求
  7. Tomcat 查询数据库获取到数据
  8. Tomcat 响应请求给 OpenResty
  9. OpenResty响应请求给Nginx
  10. Nginx 响应请求给客户端

冷启动与缓存预热

冷启动:服务刚刚启动时,Redis 中并没有缓存,如果所有商品数据都在第一次查询时添加缓存,可能会给数据库带来较大压力。

缓存预热:在实际开发中,我们可以利用大数据统计用户访问的热点数据,在项目启动时将这些热点数据提前查询并保存到Redis中。

缓存重建

缓存同步

缓存同步方案

缓存数据同步的常见方式有三种:

  1. 设置有效期:给缓存设置有效期,到期后自动删除。再次查询时更新

    • 优势:简单、方便

    • 缺点:时效性差,缓存过期之前可能不一致

    • 场景:更新频率较低,时效性要求低的业务

  2. 同步双写:在修改数据库的同时,直接修改缓存

    • 优势:时效性强,缓存与数据库强一致

    • 缺点:有代码侵入,耦合度高;

    • 场景:对一致性、时效性要求较高的缓存数据

  3. 异步通知:修改数据库时发送事件通知,相关服务监听到通知后修改缓存数据

    • 优势:低耦合,可以同时通知多个缓存服务

    • 缺点:时效性一般,可能存在中间不一致状态

    • 场景:时效性要求一般,有多个服务需要同步

异步通知方案:

基于 MQ 的异步通知方案

基于 Canal 的异步通知方案

最终缓存方案