Ehcache

Ehcache 使用指南与配置详解

Ehcache 是一个高性能的 Java 分布式缓存框架,可显著减少数据库访问压力。以下是基于 Ehcache 3 的完整配置指南:

一、环境准备
  1. 添加依赖(Maven 项目)
    pom.xml 中添加:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-cache</artifactId>
    </dependency>
    <dependency>
        <groupId>org.ehcache</groupId>
        <artifactId>ehcache</artifactId>
        <version>3.10.0</version> <!-- 使用最新版本 -->
    </dependency>
    
  2. 启用缓存
    在 Spring Boot 主类添加注解:

    @SpringBootApplication
    @EnableCaching // 启用缓存功能
    public class Application { ... }
    
二、核心配置(ehcache.xml)

resources 目录创建配置文件:

<config xmlns="http://www.ehcache.org/v3"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.ehcache.org/v3 
        http://www.ehcache.org/schema/ehcache-core.xsd">
    
    <!-- 定义缓存模板 -->
    <cache-template name="defaultTemplate">
        <heap unit="entries">1000</heap> <!-- 堆内最多存储1000个条目 -->
        <expiry>
            <ttl unit="seconds">86400</ttl> <!-- 数据存活时间:24小时 -->
        </expiry>
    </cache-template>
    
    <!-- 应用模板创建缓存 -->
    <cache alias="userCache" uses-template="defaultTemplate"/> 
    <cache alias="productCache" uses-template="defaultTemplate">
        <heap unit="MB">50</heap> <!-- 可覆盖模板配置:分配50MB内存 -->
    </cache>
</config>
三、Spring Boot 集成
  1. 配置缓存管理器
    application.yml 中指定配置文件:

    spring:
      cache:
        jcache:
          config: classpath:ehcache.xml
        type: jcache # 明确使用JCache标准
    
  2. 使用缓存注解
    在 Service 层实现缓存逻辑:

    @Service
    public class UserService {
        // 缓存查询结果到userCache
        @Cacheable(cacheNames = "userCache", key = "#userId")
        public User getUserById(String userId) {
            return userRepository.findById(userId); 
        }
        
        // 更新时清除缓存
        @CacheEvict(cacheNames = "userCache", key = "#user.id")
        public void updateUser(User user) { ... }
    }
    
四、高级特性
  1. 分层存储(堆外+磁盘)

    <cache alias="largeDataCache">
      <heap unit="MB">100</heap>
      <offheap unit="MB">500</offheap> <!-- 堆外内存 -->
      <disk unit="GB" persistent="true">1</disk> <!-- 持久化到磁盘 -->
    </cache>
    
  2. 分布式集群
    通过 Terracotta 实现节点间数据同步:

    <service>
      <terracotta>
        <cluster uri="terracotta://server1:9410,server2:9410"/>
      </terracotta>
    </service>
    
五、监控与调优
  • 监控方式:JMX 或 Ehcache 自带的 CacheManagerStatistics
  • 关键指标:命中率(Cache Hit Ratio)、驱逐数量(Eviction Count)
  • 调优建议
    • 根据数据访问频率调整 heap/offheap 比例
    • 对热点数据启用 eternal=true(永不过期)

官方文档:Ehcache 3 Documentation
Spring集成指南:Caching with Spring

思维导图

在这里插入图片描述


Ehcache 深度解析

一、技术原理

Ehcache 采用分层存储架构实现高性能缓存,通过多级存储介质平衡速度与容量:

  1. 堆内缓存(Heap):使用 JVM 堆内存,访问速度最快(纳秒级)
  2. 堆外缓存(Off-Heap):使用 DirectByteBuffer 分配内存,避免 GC 影响
  3. 磁盘缓存(Disk):持久化到 SSD/HDD,支持 TB 级数据
应用层
堆内缓存
堆外缓存
磁盘缓存

数据根据热度自动流动:高频访问数据保存在堆内,低频数据降级到磁盘。

二、核心算法与数据结构

1. 缓存淘汰算法
  • Window TinyLFU(默认算法):
    // 近似 LFU 的频率统计
    FrequencySketch sketch = new FrequencySketch(); 
    // 分段 LRU 队列
    AccessOrderDeque<Entry> accessQueue; 
    
    结合 LFU 的频率统计优势和 LRU 的时效性,通过频率草图(Count-Min Sketch) 低开销统计访问频率。
2. 数据结构
class CacheEntry<K,V> {
    K key;                  // 键对象
    V value;                // 值对象
    long accessTime;        // 最后访问时间戳
    int accessCount;        // 访问计数器
    int tier;               // 当前存储层级 (0=堆内,1=堆外,2=磁盘)
}

采用分段锁并发控制,将缓存分为 N 个段(默认 16×CPU 核数),减少锁竞争。

三、架构功能图

CacheManager
Cache
存储引擎
堆内存储
堆外存储
磁盘存储
过期策略
事件监听
集群服务

四、核心组件功能

组件功能说明
CacheManager缓存实例管理器,支持创建/销毁缓存
Cache缓存实例,提供 put/get/remove 等 API
Store存储引擎抽象层,实现多级存储协调
ExpiryPolicy过期策略控制器(TTL/TTI)
CacheLoaderWriter缓存穿透时自动加载数据源
TerracottaClient分布式集群通信组件

五、优缺点分析

优点

  1. 零 GC 停顿:堆外存储避免 Full GC
  2. 高命中率:Window TinyLFU 比 LRU 提升 25% 命中率
  3. 弹性扩展:支持 Terracotta 集群横向扩容
  4. 持久化:故障恢复后自动加载磁盘数据

缺点

  1. 集群依赖第三方服务(Terracotta)
  2. 配置复杂度高于 Guava Cache
  3. 堆外内存需手动管理

六、Java 代码示例

1. 基础缓存操作
// 创建缓存管理器
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build();
cacheManager.init();

// 配置分层缓存(堆内+堆外+磁盘)
CacheConfigurationBuilder<String, String> config = CacheConfigurationBuilder
    .newCacheConfigurationBuilder(
        String.class, 
        String.class,
        ResourcePoolsBuilder.newResourcePoolsBuilder()
            .heap(100, EntryUnit.ENTRIES)     // 堆内100条目
            .offheap(500, MemoryUnit.MB)      // 堆外500MB
            .disk(10, MemoryUnit.GB)          // 磁盘10GB
    )
    .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofHours(24)));

// 创建缓存实例
Cache<String, String> myCache = cacheManager.createCache("myCache", config);

// 写入缓存
myCache.put("key1", "Hello Ehcache!"); 

// 读取缓存(自动提升数据层级)
String value = myCache.get("key1"); 

// 移除缓存
myCache.remove("key1");
2. 注解驱动缓存(Spring Boot)
@Service
public class ProductService {
    
    // 自动缓存方法结果
    @Cacheable(cacheNames = "products", key = "#id")
    public Product getProduct(Long id) {
        return db.query("SELECT * FROM products WHERE id = ?", id);
    }
    
    // 更新时清除缓存
    @CacheEvict(cacheNames = "products", key = "#product.id")
    public void updateProduct(Product product) {
        db.update(product);
    }
}
3. 缓存事件监听
cache.getRuntimeConfiguration().registerCacheEventListener(
    new CacheEventListenerAdapter<String, String>() {
        @Override
        public void onCreation(String key, String value) {
            System.out.println("创建缓存: " + key); 
        }
        
        @Override
        public void onExpiration(String key, String value) {
            System.out.println("缓存过期: " + key);
        }
    },
    EventOrdering.ORDERED,
    EventFiring.ASYNCHRONOUS,
    EnumSet.of(EventType.CREATED, EventType.EXPIRED)
);

七、性能优化建议

  1. 热点数据:对高频访问数据设置 eternal=true 避免淘汰
  2. 分层配比:根据数据访问模式调整堆内/堆外/磁盘容量比例
  3. 序列化:使用 Kryo/FST 替代 JDK 序列化提升速度
  4. 监控指标:关注缓存命中率(Hit Ratio)和驱逐计数(Eviction Count)

通过合理配置,Ehcache 可达百万级 QPS,延迟低于 5ms

思维导图

在这里插入图片描述


Ehcache 深度解析(结合 Spring Boot 与 Java 环境)

1. 缓存过期策略

Ehcache 支持三种过期策略:

  • TTL (Time-To-Live):自缓存创建后的存活时间
  • TTI (Time-To-Idle):自最后一次访问后的存活时间
  • Eternal:永不过期(需手动清除)

Spring Boot 配置示例

<!-- ehcache.xml -->
<cache name="productCache"
       maxEntriesLocalHeap="1000"
       eternal="false"
       timeToIdleSeconds="300"   <!-- TTI: 5分钟未访问则过期 -->
       timeToLiveSeconds="3600"> <!-- TTL: 1小时后强制过期 -->
    <persistence strategy="localTempSwap"/> <!-- 磁盘持久化 -->
</cache>
// Spring Boot 配置类
@Configuration
@EnableCaching
public class CacheConfig {
    @Bean
    public CacheManager cacheManager() {
        return new EhCacheCacheManager(
            net.sf.ehcache.CacheManager.newInstance(
                new ClassPathResource("ehcache.xml").getInputStream()
            )
        );
    }
}
2. 多实例配置

在 Spring Boot 中配置多个缓存实例:

# application.yml
spring:
  cache:
    cache-names: productCache, userCache, orderCache
  ehcache:
    config: classpath:ehcache-multi.xml
<!-- ehcache-multi.xml -->
<cache name="productCache" ... />
<cache name="userCache" maxEntriesLocalHeap="500" ... />
<cache name="orderCache" maxEntriesLocalDisk="10000" ... />
3. 分布式缓存配置

Ehcache 通过 Terracotta 集群实现分布式缓存:

<ehcache>
    <terracottaConfig url="terracotta-server:9510"/> <!-- 集群服务器地址 -->
    
    <cache name="distributedCache"
           maxEntriesLocalHeap="1000">
        <persistence strategy="distributed"/> <!-- 分布式持久化策略 -->
        <terracotta clustered="true"/>       <!-- 启用集群 -->
    </cache>
</ehcache>

数据一致性机制

  • 写操作:通过 两阶段提交协议 保证集群节点间原子性
  • 读操作:采用 最终一致性模型,通过事件监听同步变更
  • 冲突解决:基于 版本向量(Version Vector) 检测并发写冲突
4. 监控机制

Spring Boot Actuator 集成

management:
  endpoints:
    web:
      exposure:
        include: health,metrics,caches
  metrics:
    export:
      prometheus:
        enabled: true

监控端点:

  • /actuator/caches:查看缓存实例列表
  • /actuator/metrics/ehcache.hits:缓存命中率
  • /actuator/metrics/ehcache.size:各层存储使用量

自定义监控

Cache cache = cacheManager.getCache("productCache");
Ehcache ehcache = (Ehcache) cache.getNativeCache();

// 获取堆内存使用情况
long heapSize = ehcache.getStatistics().getLocalHeapSize(); 

// 获取磁盘存储使用量
long diskSize = ehcache.getStatistics().getLocalDiskSize(); 
5. 与 Redis 性能对比
指标EhcacheRedis
本地读延迟0.1ms (堆内) / 0.5ms (堆外)1-5ms (网络往返)
本地写吞吐量150,000 ops/s (堆内)50,000 ops/s (单节点)
GC 影响堆外存储零 GC 停顿无影响 (独立进程)
数据一致性最终一致 (集群模式)强一致 (主从复制)
适用场景高频读本地缓存分布式共享缓存

实测:Ehcache 本地读性能是 Redis 的 10-50 倍,但 Redis 在分布式场景更成熟

6. 持久化与恢复

磁盘持久化配置

<cache name="persistentCache"
       maxEntriesLocalHeap="1000"
       maxEntriesLocalDisk="10000"
       diskExpiryThreadIntervalSeconds="300"> <!-- 每5分钟检查过期 -->
    <persistence strategy="localTempSwap"/> <!-- 磁盘存储策略 -->
</cache>

数据恢复流程

  1. 启动时自动加载磁盘数据文件(.data
  2. 根据 diskPersistent="true" 配置恢复元数据
  3. 重建内存索引(堆内/堆外)

注意:需确保应用关闭时调用 cacheManager.shutdown() 保证数据完整写入

7. 缓存淘汰策略

Ehcache 3.x 支持策略:

CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, String.class,
    ResourcePoolsBuilder.heap(100))
    .withEvictionAdvisor((key, value) -> key.startsWith("reserved_")) // 自定义保留规则
    .add(EvictionAdvisorConfiguration.of(
        new LeastRecentlyUsedEvictionAdvisor() // LRU 策略
    ))
    .add(EvictionAdvisorConfiguration.of(
        new LeastFrequentlyUsedEvictionAdvisor() // LFU 策略
    ));

策略对比

  • LRU:简单高效,但对突发访问模式敏感
  • LFU:适合长期热点数据,但需要频率计数开销
  • Window TinyLFU:平衡时效性与频率统计(默认推荐)
8. Window TinyLFU 优势

与传统 LRU 对比

特性Window TinyLFULRU
突发流量处理✅ 通过频率草图过滤偶发访问❌ 可能冲掉真正热点数据
空间开销12 bits/entry (Count-Min Sketch)64 bits/entry (指针)
命中率提升最高 25% (OLTP 场景)基准值
实现复杂度中 (分段队列+频率草图)低 (双向链表)

数据结构核心

// 频率草图(空间优化版布隆过滤器)
class FrequencySketch {
    long[] counters; // 4位计数器数组
    void increment(K key) {
        int hash = spread(key.hashCode());
        int index = index(hash);
        // 基于哈希的计数更新(避免冲突)
        if ((counters[index] & 0xff) < 15) {
            counters[index]++;
        }
    }
}
9. 分层存储监控

获取各层使用量

ResourcePools pools = cache.getRuntimeConfiguration().getResourcePools();

// 堆内存使用
long heapSize = pools.getPoolForResource(ResourceType.Core.HEAP).getSize();

// 堆外内存使用
long offheapSize = pools.getPoolForResource(ResourceType.Core.OFFHEAP).getSize();

// 磁盘使用
long diskSize = pools.getPoolForResource(ResourceType.Core.DISK).getSize();

JMX 监控配置

<ehcache xmlns:jmx="http://www.ehcache.org/v3/jmx" 
         updateCheck="false">
    <management-service>
        <jmx:enable/>
    </management-service>
</ehcache>

通过 JConsole 查看:net.sf.ehcache:type=CacheStatistics

10. 集群数据同步

Terracotta 集群机制

ClientA Terracotta Server ClientB put(key, value) 异步数据变更事件 确认接收 操作成功响应 ClientA Terracotta Server ClientB

同步特性

  • 最终一致性:变更通常在 100ms 内传播到所有节点
  • 批量更新:压缩网络传输量(默认 1KB/批次)
  • 冲突解决:基于向量时钟(Vector Clock)的版本合并
11. 堆外存储原理

GC 优化机制

  1. 零 GC 停顿:数据存储在 DirectByteBuffer(JVM 堆外)
  2. 手动内存管理:通过 sun.misc.Unsafe 直接操作内存
  3. 缓存专属分配器:避免内存碎片

堆外读操作示例

class OffHeapStore {
    ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
    
    void write(String key, String value) {
        byte[] data = value.getBytes(StandardCharsets.UTF_8);
        buffer.putInt(data.length);
        buffer.put(data);
    }
    
    String read() {
        int length = buffer.getInt();
        byte[] data = new byte[length];
        buffer.get(data);
        return new String(data);
    }
}

效果:堆外存储可将 Full GC 时间从秒级降至毫秒级

12. 自定义序列化器

实现步骤

  1. 实现 Serializer 接口
  2. 注册到缓存配置
  3. 配置 Kryo/FST 等高效序列化

Kryo 序列化示例

public class KryoSerializer implements Serializer<Object> {
    private final Kryo kryo = new Kryo();
    
    public KryoSerializer(ClassLoader classLoader) {
        kryo.register(Product.class); // 注册自定义类
    }

    @Override
    public ByteBuffer serialize(Object object) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        Output output = new Output(baos);
        kryo.writeObject(output, object);
        output.close();
        return ByteBuffer.wrap(baos.toByteArray());
    }

    @Override
    public Object deserialize(ByteBuffer binary) {
        Input input = new Input(binary.array());
        return kryo.readObject(input, Product.class);
    }
}

// 注册到缓存配置
CacheConfigurationBuilder.newCacheConfigurationBuilder()
    .withValueSerializer(KryoSerializer.class)
    .build();

性能对比

序列化方案吞吐量 (ops/sec)延迟 (μs/op)
JDK 序列化12,00083
Kryo150,0006.7
FST210,0004.8
最佳实践总结
  1. 分层策略:热数据存堆内 (100-10,000 entries),温数据存堆外 (GB级),冷数据存磁盘 (TB级)
  2. 监控指标
    • 命中率 > 95% (低于85%需优化键设计)
    • 驱逐率 < 5% (过高需扩容)
  3. 集群部署
    # 启动 Terracotta 服务器
    $ bin/start-tc-server.sh -f config/tc-config.xml
    
  4. 性能调优
    // 关闭严格模式提升并发
    CacheConfigurationBuilder.withoutStrictEviction() 
    

通过合理配置,Ehcache 可达百万级 QPS,延迟稳定在亚毫秒级

思维导图

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值