Ehcache 是一个广泛使用的 Java 缓存框架,其底层实现基于内存和磁盘存储,提供了高效的缓存管理功能。

Ehcache 的核心组件

CacheManager

  • 作用:管理多个缓存实例(Cache);

  • 功能:负责创建、配置和销毁缓存实例;

  • 实现:通常通过单例模式实现,确保全局唯一。

Cache

  • 作用:存储缓存数据;

  • 功能:提供缓存的读写、删除和清理操作;

  • 实现:基于内存和磁盘存储,支持多种缓存策略。

Store

  • 作用:实际存储缓存数据;

  • 类型

    • MemoryStore:基于内存的存储,使用 Java 堆或堆外内存;

    • DiskStore:基于磁盘的存储,用于持久化缓存数据;

    • TieredStore:多级存储,结合内存和磁盘存储。

Eviction Algorithm

  • 作用:决定缓存数据的淘汰策略;

  • 常见策略

    • LRU(Least Recently Used):淘汰最近最少使用的数据;

    • LFU(Least Frequently Used):淘汰使用频率最低的数据;

    • FIFO(First In First Out):淘汰最早进入缓存的数据。

CacheLoaderWriter

  • 作用:在缓存未命中时,从外部数据源加载数据;

  • 功能:支持缓存穿透时的数据加载。

Ehcache 的存储结构

内存存储(MemoryStore)

  • 堆内存(On-Heap)

    • 使用 Java 堆内存存储缓存数据;

    • 优点:访问速度快;

    • 缺点:受 JVM 堆大小限制,可能引发 GC 压力。

  • 堆外内存(Off-Heap)

    • 使用 JVM 堆外内存(Direct Memory)存储缓存数据;

    • 优点:不受 JVM 堆大小限制,减少 GC 压力;

    • 缺点:访问速度略慢于堆内存。

磁盘存储(DiskStore)

  • 持久化缓存

    • 将缓存数据持久化到磁盘,防止内存溢出或应用重启时数据丢失;

    • 支持本地文件系统或分布式存储。

  • 磁盘溢出(Overflow to Disk)

    • 当内存存储达到上限时,将部分数据写入磁盘。

Ehcache 的缓存淘汰机制

基于容量的淘汰

  • 当缓存中的数据量达到配置的最大容量时,触发淘汰机制;

  • 淘汰策略包括 LRU、LFU 和 FIFO。

基于时间的淘汰

  • TTL(Time To Live):缓存数据的存活时间;

  • TTI(Time To Idle):缓存数据的空闲时间。

手动淘汰

  • 通过调用 remove()clear() 方法手动删除缓存数据。

Ehcache 的并发控制

分段锁(Striped Locking)

  • 将缓存数据划分为多个段(Segment),每个段使用独立的锁;

  • 减少锁竞争,提高并发性能。

读写锁(ReadWrite Lock)

  • 读操作共享锁,写操作独占锁;

  • 提高读操作的并发性。

CAS(Compare and Swap)

  • 使用 CAS 操作实现无锁并发控制;

  • 适用于高并发场景。

Ehcache 的持久化机制

本地磁盘持久化

  • 将缓存数据写入本地文件系统;

  • 支持序列化和反序列化。

分布式持久化

  • 将缓存数据写入分布式存储系统(如 Terracotta);

  • 支持高可用性和数据一致性。

Ehcache 的缓存加载机制

CacheLoader

  • 在缓存未命中时,自动调用 CacheLoader 加载数据;

  • 适用于单机缓存。

CacheLoaderWriter

  • 在缓存未命中时,自动调用 CacheLoaderWriter 加载数据;

  • 适用于分布式缓存。

Ehcache 的配置示例

  • XML 配置

    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd">
        <cache alias="myCache">
            <heap unit="entries">1000</heap>
            <offheap unit="MB">100</offheap>
            <diskstore path="/tmp/ehcache"/>
            <expiry>
                <tti unit="seconds">60</tti>
            </expiry>
        </cache>
    </ehcache>
  • Java 配置

    CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build();
    cacheManager.init();
    
    CacheConfigurationBuilder<String, String> config = CacheConfigurationBuilder.newCacheConfigurationBuilder(
        String.class, String.class, ResourcePoolsBuilder.newResourcePoolsBuilder()
            .heap(1000, EntryUnit.ENTRIES)
            .offheap(100, MemoryUnit.MB)
            .disk(10, MemoryUnit.GB, "/tmp/ehcache")
    );
    
    Cache<String, String> myCache = cacheManager.createCache("myCache", config);