Ehcache 使用指南与配置详解
Ehcache 是一个高性能的 Java 分布式缓存框架,可显著减少数据库访问压力。以下是基于 Ehcache 3 的完整配置指南:
一、环境准备
-
添加依赖(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> -
启用缓存
在 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 集成
-
配置缓存管理器
在application.yml中指定配置文件:spring: cache: jcache: config: classpath:ehcache.xml type: jcache # 明确使用JCache标准 -
使用缓存注解
在 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) { ... } }
四、高级特性
-
分层存储(堆外+磁盘)
<cache alias="largeDataCache"> <heap unit="MB">100</heap> <offheap unit="MB">500</offheap> <!-- 堆外内存 --> <disk unit="GB" persistent="true">1</disk> <!-- 持久化到磁盘 --> </cache> -
分布式集群
通过 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 采用分层存储架构实现高性能缓存,通过多级存储介质平衡速度与容量:
- 堆内缓存(Heap):使用 JVM 堆内存,访问速度最快(纳秒级)
- 堆外缓存(Off-Heap):使用 DirectByteBuffer 分配内存,避免 GC 影响
- 磁盘缓存(Disk):持久化到 SSD/HDD,支持 TB 级数据
数据根据热度自动流动:高频访问数据保存在堆内,低频数据降级到磁盘。
二、核心算法与数据结构
1. 缓存淘汰算法
- Window TinyLFU(默认算法):
结合 LFU 的频率统计优势和 LRU 的时效性,通过频率草图(Count-Min Sketch) 低开销统计访问频率。// 近似 LFU 的频率统计 FrequencySketch sketch = new FrequencySketch(); // 分段 LRU 队列 AccessOrderDeque<Entry> accessQueue;
2. 数据结构
class CacheEntry<K,V> {
K key; // 键对象
V value; // 值对象
long accessTime; // 最后访问时间戳
int accessCount; // 访问计数器
int tier; // 当前存储层级 (0=堆内,1=堆外,2=磁盘)
}
采用分段锁并发控制,将缓存分为 N 个段(默认 16×CPU 核数),减少锁竞争。
三、架构功能图
四、核心组件功能
| 组件 | 功能说明 |
|---|---|
CacheManager | 缓存实例管理器,支持创建/销毁缓存 |
Cache | 缓存实例,提供 put/get/remove 等 API |
Store | 存储引擎抽象层,实现多级存储协调 |
ExpiryPolicy | 过期策略控制器(TTL/TTI) |
CacheLoaderWriter | 缓存穿透时自动加载数据源 |
TerracottaClient | 分布式集群通信组件 |
五、优缺点分析
优点:
- 零 GC 停顿:堆外存储避免 Full GC
- 高命中率:Window TinyLFU 比 LRU 提升 25% 命中率
- 弹性扩展:支持 Terracotta 集群横向扩容
- 持久化:故障恢复后自动加载磁盘数据
缺点:
- 集群依赖第三方服务(Terracotta)
- 配置复杂度高于 Guava Cache
- 堆外内存需手动管理
六、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)
);
七、性能优化建议
- 热点数据:对高频访问数据设置
eternal=true避免淘汰 - 分层配比:根据数据访问模式调整堆内/堆外/磁盘容量比例
- 序列化:使用 Kryo/FST 替代 JDK 序列化提升速度
- 监控指标:关注缓存命中率(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 性能对比
| 指标 | Ehcache | Redis |
|---|---|---|
| 本地读延迟 | 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>
数据恢复流程:
- 启动时自动加载磁盘数据文件(
.data) - 根据
diskPersistent="true"配置恢复元数据 - 重建内存索引(堆内/堆外)
注意:需确保应用关闭时调用
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 TinyLFU | LRU |
|---|---|---|
| 突发流量处理 | ✅ 通过频率草图过滤偶发访问 | ❌ 可能冲掉真正热点数据 |
| 空间开销 | 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 集群机制:
同步特性:
- 最终一致性:变更通常在 100ms 内传播到所有节点
- 批量更新:压缩网络传输量(默认 1KB/批次)
- 冲突解决:基于向量时钟(Vector Clock)的版本合并
11. 堆外存储原理
GC 优化机制:
- 零 GC 停顿:数据存储在
DirectByteBuffer(JVM 堆外) - 手动内存管理:通过
sun.misc.Unsafe直接操作内存 - 缓存专属分配器:避免内存碎片
堆外读操作示例:
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. 自定义序列化器
实现步骤:
- 实现
Serializer接口 - 注册到缓存配置
- 配置 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,000 | 83 |
| Kryo | 150,000 | 6.7 |
| FST | 210,000 | 4.8 |
最佳实践总结
- 分层策略:热数据存堆内 (100-10,000 entries),温数据存堆外 (GB级),冷数据存磁盘 (TB级)
- 监控指标:
- 命中率 > 95% (低于85%需优化键设计)
- 驱逐率 < 5% (过高需扩容)
- 集群部署:
# 启动 Terracotta 服务器 $ bin/start-tc-server.sh -f config/tc-config.xml - 性能调优:
// 关闭严格模式提升并发 CacheConfigurationBuilder.withoutStrictEviction()
通过合理配置,Ehcache 可达百万级 QPS,延迟稳定在亚毫秒级
思维导图

356

被折叠的 条评论
为什么被折叠?



