在 Java 缓存生态里,Redis 几乎成了分布式缓存的代名词,但提到本地缓存,有一个 “老伙计” 你一定绕不开 ——Ehcache。作为纯 Java 实现的进程内缓存框架,Ehcache 凭借轻量、易集成、高性能的特点,至今仍是中小型项目、单机应用的首选。本文带你吃透 Ehcache 的核心用法、适用场景,以及和 Redis 的选型逻辑。

一、Ehcache 是什么?先搞懂核心定位

Ehcache 是一款开源的纯 Java 本地缓存框架,核心作用是将高频访问、变更不频繁的数据缓存到 JVM 内存中,避免频繁查询数据库 / 调用接口,从而提升系统响应速度、降低后端存储压力。

关键特征(为什么它能火这么多年?)

  • 本地性:数据存在当前应用的 JVM 内存里,读写无网络开销,速度比 Redis 更快(毫秒级→微秒级);

  • 轻量级:无外部依赖,引入 jar 包就能用,Spring Boot 一键集成;

  • 多级缓存:支持 “内存 + 磁盘” 两级缓存,内存满了自动刷盘,避免 OOM;

  • 灵活配置:自定义过期时间、淘汰策略(LRU/FIFO)、缓存大小,适配不同业务场景;

  • 生态友好:完美兼容 Spring Cache、MyBatis、Hibernate 等主流框架,开箱即用。

二、Ehcache 实战:Spring Boot 集成三步搞定

以 “电商商品缓存” 为例,手把手教你落地 Ehcache,全程复制就能用。

1. 引入依赖

<!-- Spring Boot 缓存核心依赖 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Ehcache 核心包 -->
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>2.10.6</version> <!-- 稳定版本,适配大部分项目 -->
</dependency>

2. 配置 Ehcache 规则

resources 目录下创建 ehcache.xml,定义缓存策略(核心是 “控制缓存大小 + 过期时间”):

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="ehcache.xsd">
    <!-- 磁盘缓存文件存储路径(默认临时目录) -->
    <diskStore path="java.io.tmpdir/ehcache"/>

    <!-- 默认缓存配置(兜底规则) -->
    <defaultCache
        maxEntriesLocalHeap="10000"   <!-- 内存最大缓存条目数 -->
        eternal="false"               <!-- 是否永久有效(建议false,避免内存溢出) -->
        timeToIdleSeconds="300"       <!-- 闲置5分钟过期(无访问则失效) -->
        timeToLiveSeconds="600"       <!-- 存活10分钟过期(创建后无论是否访问都失效) -->
        diskExpiryThreadIntervalSeconds="120" <!-- 磁盘过期扫描线程间隔 -->
        memoryStoreEvictionPolicy="LRU"/> <!-- 内存淘汰策略:最近最少使用 -->

    <!-- 自定义缓存:商品缓存(针对性配置) -->
    <cache name="goodsCache"
           maxEntriesLocalHeap="5000"  <!-- 商品缓存量小,按需调整 -->
           eternal="false"
           timeToIdleSeconds="600"     <!-- 商品信息变更少,闲置10分钟过期 -->
           timeToLiveSeconds="1800"    <!-- 存活30分钟 -->
           maxEntriesLocalDisk="10000" <!-- 磁盘最大缓存数 -->
           diskPersistent="false"/>    <!-- 重启是否持久化到磁盘(默认false) -->
</cache>

3. 业务代码中使用

结合 Spring Cache 注解,一行代码实现缓存逻辑,无需手动操作缓存:

@Service
@CacheConfig(cacheNames = "goodsCache") // 全局指定缓存名称,简化后续注解
public class GoodsService {

    @Autowired
    private GoodsMapper goodsMapper;

    /**
     * 查询商品:缓存命中则直接返回,未命中则查库并缓存
     * key = 商品ID,保证缓存唯一性
     */
    @Cacheable(key = "#goodsId", unless = "#result == null") // 空结果不缓存
    public GoodsVO getGoodsById(Long goodsId) {
        // 仅第一次调用/缓存过期时执行,后续走内存缓存
        return goodsMapper.selectById(goodsId);
    }

    /**
     * 更新商品:删除对应缓存,避免缓存脏数据
     */
    @CacheEvict(key = "#goodsDTO.id")
    public void updateGoods(GoodsDTO goodsDTO) {
        goodsMapper.updateById(goodsDTO);
    }

    /**
     * 批量删除商品:清空整个商品缓存
     */
    @CacheEvict(allEntries = true)
    public void batchDeleteGoods(List<Long> goodsIdList) {
        goodsMapper.deleteBatchIds(goodsIdList);
    }
}

三、Ehcache 用在哪?看场景选对才高效

Ehcache 不是 “万能缓存”,核心适配本地、低并发、小数据量场景,具体分三类:

首选场景(用 Ehcache 性价比最高)

  1. 后台管理系统:OA/CRM/ERP 等单机 / 小集群部署的系统,数据量小、访问量低,无需分布式缓存;

  2. MyBatis/Hibernate 二级缓存:框架原生支持,无需额外开发,提升数据库查询效率;

  3. Shiro 权限缓存:缓存用户角色、权限信息,避免每次接口校验都查库;

  4. 单机高频读场景:比如定时任务配置、字典表数据,变更少、访问频繁。

不推荐场景(优先选 Redis)

  1. 分布式集群:多服务实例需要共享缓存(比如用户登录态、订单状态);

  2. 高并发 / 大数据量:每秒万级以上访问、缓存数据量超 GB 级,JVM 内存扛不住;

  3. 跨语言场景:系统包含 Java/PHP/Go 等多语言服务,需要统一缓存中间件。

📌 最优组合:Ehcache + Redis 两级缓存

大型项目常用 “本地缓存 + 分布式缓存” 架构,兼顾速度和一致性:

  1. 一级缓存(Ehcache):缓存热点数据,优先读取,减少网络开销;

  2. 二级缓存(Redis):缓存分布式共享数据,兜底一级缓存未命中的场景;

  3. 缓存更新:更新数据时,先删 Redis 缓存,再删 Ehcache 缓存,保证数据一致性。

四、避坑指南:使用 Ehcache 必注意的 3 个问题

1. 内存溢出(OOM)

  • 问题:缓存数据过多,占用 JVM 堆内存导致 OOM;

  • 解决:合理配置 maxEntriesLocalHeap(内存最大条目数)、timeToLiveSeconds(过期时间),开启磁盘缓存兜底。

2. 缓存数据不一致(多实例场景)

  • 问题:单机缓存不共享,A 实例更新数据,B 实例缓存还是旧数据;

  • 解决:① 小集群可通过广播通知刷新缓存;② 核心数据优先用 Redis;③ 给缓存设置合理过期时间,兜底不一致问题。

3. 缓存穿透 / 击穿

  • 缓存穿透:查询不存在的数据,每次都查库;解决:缓存空值(unless = "#result == null" 可调整为缓存空值);

  • 缓存击穿:热点 key 过期瞬间,大量请求打穿到数据库;解决:设置热点 key 永不过期(eternal = true),或加分布式锁。

五、总结:Ehcache 该不该用?

Ehcache 虽然不如 Redis “热门”,但在本地缓存领域仍是标杆

  • 中小型项目 / 单机应用:优先用 Ehcache,轻量、易集成、成本低;

  • 分布式 / 高并发项目:以 Redis 为主,Ehcache 为辅做一级缓存;

  • 学习成本:掌握 Spring Cache 注解 + 核心配置即可,无需深钻底层,够用就好。