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);