Redis + Caffeine 多级缓存架构

目录

前言:

[Redis + Caffeine多级缓存架构查数据的过程:](#Redis + Caffeine多级缓存架构查数据的过程:)

Redis与Caffeine的核心区别:

[为什么要用Redis + Caffeine 多级缓存架构?](#为什么要用Redis + Caffeine 多级缓存架构?)

[一、核心原因:单缓存方案的 "致命短板"](#一、核心原因:单缓存方案的 “致命短板”)

[只用 Caffeine(本地缓存)的痛点](#只用 Caffeine(本地缓存)的痛点)

[只用 Redis(分布式缓存)的痛点](#只用 Redis(分布式缓存)的痛点)

[二、多级缓存架构的 "核心价值"](#二、多级缓存架构的 “核心价值”)

极致的性能:降低时延,提升吞吐量

高可用性:容错能力更强

[数据一致性:兼顾 "快" 和 "准"](#数据一致性:兼顾 “快” 和 “准”)

[4. 成本优化:资源利用更高效](#4. 成本优化:资源利用更高效)

[Caffeine 本地缓存配置类:](#Caffeine 本地缓存配置类:)

结尾


前言:

在高并发场景下,缓存是提升系统性能的核心手段,但单一缓存往往难以兼顾"速度"与"一致性"。Redis 作为分布式缓存的标杆,Caffeine 作为 JVM 本地缓存的性能王者,两者组合的多级缓存架构,已成为电商、直播等高频访问场景的最优解。本文将拆解这一架构的核心逻辑、落地方式,帮你快速掌握高并发系统的缓存优化技巧。

Redis + Caffeine多级缓存架构查数据的过程:

Redis与Caffeine的核心区别:

为什么要用Redis + Caffeine 多级缓存架构?

一、核心原因:单缓存方案的 "致命短板"

先看只用其中一种缓存的问题,就能理解多级缓存的必要性:

只用 Caffeine(本地缓存)的痛点

数据不一致:每个 JVM 实例都有独立的本地缓存,多服务节点间数据无法同步(比如 A 节点更新了数据,B 节点缓存还是旧的);

内存上限:受 JVM 堆内存限制,缓存数据量不能太大,否则会引发频繁 GC 甚至 OOM;

无持久化:JVM 进程重启后,本地缓存数据全部丢失,会导致 "缓存雪崩"(所有请求瞬间打到数据库)。

只用 Redis(分布式缓存)的痛点

性能瓶颈 :每次访问都要走网络 IO(TCP 连接、协议解析),即使是本地 Redis,单次操作也在毫秒级,高频访问场景下(比如每秒百万次请求),网络开销会被放大,成为性能瓶颈;

网络风险:Redis 节点故障、网络抖动会导致缓存不可用,直接影响业务;

资源浪费:把所有高频热点数据都放到 Redis,会增加 Redis 的压力(内存、CPU、网络),提升运维成本。

二、多级缓存架构的 "核心价值"

Redis + Caffeine 组合后,形成 "本地缓存(Caffeine)做第一层,分布式缓存(Redis)做第二层" 的架构,完美解决单缓存的问题,核心收益有 4 点:

极致的性能:降低时延,提升吞吐量

热点数据本地化 :把访问频率最高的 "热点数据"(比如占请求量 80% 的 20% 数据)放到 Caffeine 中,进程内直接访问,时延从 Redis 的毫秒级 降到微秒 / 纳秒级

减轻 Redis 压力:Caffeine 拦截了大部分高频请求,Redis 只处理 "冷数据" 或 "首次请求",Redis 的 QPS 压力能降低 50% 以上,避免 Redis 成为瓶颈。

高可用性:容错能力更强

Redis 故障兜底:如果 Redis 集群宕机,Caffeine 中的热点数据还能正常提供服务,不会导致所有请求直接打到数据库,降低 "缓存击穿 / 雪崩" 的风险

Caffeine 失效不影响:单个 JVM 实例的 Caffeine 缓存失效(比如重启),只是该实例的请求会走到 Redis,整体业务不受影响。

数据一致性:兼顾 "快" 和 "准"

Redis 作为 "缓存唯一数据源":所有缓存的写入 / 更新 / 删除,都以 Redis 为准;

Caffeine 作为 "临时副本":Caffeine 只缓存 Redis 的数据副本,且设置较短的过期时间(比如 5 分钟),既保证了大部分请求的速度,又能通过 Redis 保证多节点的数据一致性。

4. 成本优化:资源利用更高效

本地缓存(Caffeine)使用 JVM 闲置内存,几乎无额外成本;

Redis 只需存储全量缓存数据,无需为 "热点数据" 过度扩容,降低 Redis 集群的硬件成本。

Caffeine 本地缓存配置类:

核心参数:

  • 默认缓存最大数量
  • 默认过期时间,单位秒

**Spring Cache 的具体实现 :**将 Caffeine 高性能本地缓存集成到 Spring 的缓存抽象中

CaffeineCache的特点:

|--------|---------------------------------|
| 本地内存缓存 | 数据存储在应用进程的内存中 |
| 有界缓存 | 可以设置最大容量和过期时 |
| 线程安全 | 底层使用 ConcurrentHashMap 和 CAS 操作 |

java 复制代码
package com.rmcloud.common.caffeine;

import java.util.ArrayList;
import java.util.concurrent.TimeUnit;

import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.caffeine.CaffeineCache;
import org.springframework.cache.support.SimpleCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.github.benmanes.caffeine.cache.Caffeine;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * Caffeine缓存配置类
 */
@Configuration
@Slf4j
@EnableCaching
public class CaffeineCacheConfig {

    // 默认缓存最大数量
    private static final int DEFAULT_MAXSIZE = 100;
    // 默认过期时间,单位秒
    private static final int DEFAULT_TTL = 1800;

    @Bean
    public CacheManager createCacheManager() {
        log.info("cache manager init...");
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        ArrayList<CaffeineCache> caches = new ArrayList<>();
        for (HadesInsightCache c : HadesInsightCache.values()) {
            caches.add(new CaffeineCache(c.name(),
                Caffeine.newBuilder().expireAfterWrite(c.getTtl(), TimeUnit.SECONDS).maximumSize(c.getMaxSize()).build()));
        }
        cacheManager.setCaches(caches);
        return cacheManager;
    }

    @Getter
    @AllArgsConstructor
    @NoArgsConstructor
    public enum HadesInsightCache {

        // 将缓存的key值注册进来
        // 第三方应用订阅事件缓存 key:eventId
        COMPANY_APP_SUB_EVENT_CACHE_EVENT_ID(600, 10800),
        // 第三方应用事件配置 key:appId
        COMPANY_EVENT_CONFIG_APP_ID(600, 10800),
        // 第三方应用订阅事件缓存 key:eventId+companyId
        COMPANY_APP_SUB_EVENT_CACHE_EVENT_COMPANY_ID(600, 10800),
        // 菜单权限表 key:companyId
        SYS_MENU_COMPANY_ID(1000, 5),
        // 事件 key:eventCode
        EVENT_FOR_COMPANY_EVENT_CODE(100, 43200),
        // 加工工艺缓存 key:id
        PROCESS_TECHNOLOGY_CACHE_ID(600, 43200),
        // 省份信息缓存 key:provinceCode
        PROVINCE_DATA_CACHE_CODE(200, 259200),
        // 市区信息缓存 key:cityCode
        CITY_DATA_CACHE_CODE(500, 259200),
        // 地区信息缓存 key:areaCode
        AREA_DATA_CACHE_CODE(4000, 259200),
        // 省市区信息缓存 key:unionCode
        PCA_DATA_CACHE_CODE(4000, 259200),
        // 国内省份信息缓存 key:DOMESTIC_PROVINCE_DATA
        DOMESTIC_PROVINCE_DATA_CACHE(50, 259200),;

        /**
         * 最大数量
         */
        private int maxSize = DEFAULT_MAXSIZE;

        /**
         * 过期时间,单位秒
         */
        private int ttl = DEFAULT_TTL;
    }
}

结尾

综上,Redis + Caffeine 多级缓存架构的核心,是用 Caffeine 突破性能瓶颈、用 Redis 保障数据一致,既规避了单缓存的短板,又实现了性能、可用性与成本的平衡。对于高并发系统而言,这不仅是一种缓存方案,更是一套经过实践验证的性能优化思路,落地后能显著降低请求时延、减轻数据库与 Redis 压力,值得每一位后端开发者掌握与应用。

相关推荐
星辰_mya2 小时前
Redis 锁的“续命”艺术:看门狗机制与原子性陷阱
数据库·redis·分布式·缓存·面试
炸裂狸花猫2 小时前
Kubernetes架构演进:Node Pool分层与Pod IP不足的解决方案
云原生·架构·kubernetes·aws·oci·oke
实在智能RPA2 小时前
2026年企业级实测:企业部署智能体要什么电脑配置?从硬件门槛到架构选型的深度拆解
人工智能·ai·架构
毛骗导演2 小时前
对话历史越来越长,OpenClaw 是怎么「压缩」掉的?——深读 Compaction 机制源码
前端·架构
guslegend3 小时前
JavaCore核心技术综合实战
架构
Mintopia3 小时前
从架构起步:如何在软件开发初期决定交付速度与质量
前端·架构
balmtv3 小时前
Claude国内镜像站实测:可扩展监督与宪法AI,推理架构的范式革命
人工智能·机器学习·架构
LSL666_3 小时前
Redis值数据类型——list
数据库·redis·缓存·数据类型
尽兴-3 小时前
拨开迷雾:深入理解 Redis 7 的线程模型
数据库·redis·缓存·redis7·线程模型