前面一节已经知道如何通过CacheManager获取Cache。在使用JavaAPI直接创建Cache对象时相信大家已经注意到了ResourcePoolsBuilder.newResourcePoolsBuilder().heap()这个方法了。下面我们详细说一说着三种缓存策略。
- heap堆内内存
- off-heap堆外内存
- desk写到磁盘的内存
heap
ResourcePoolsBuilder.newResourcePoolsBuilder().heap(10)
heap表示使用堆内内存,10表示只能存放put10个对象,当put第11个那么前面10个对象将有一个会被移除。看看下面的demo
public class EhcacheTest4 {
public static void main(String[] args){
CacheManager cacheManager = EhcacheTest4.heapDemo();
Cache<String,String> cache = cacheManager.getCache("heapDemo",String.class, String.class);
//放10个对象进去。但是heap的大小只有5
for(int i = 0 ; i < 10 ; i++){
cache.put(i+"a",i+"aaa");
}
//按顺序取出着10个对象
for(int i = 0 ; i < 10 ; i++){
String key = i+"a";
String v = cache.get(key);
System.out.println("key:"+key+"value:"+v);
}
}
public static CacheManager heapDemo(){
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().withCache("heapDemo",
CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, String.class,
ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(5, EntryUnit.ENTRIES) //只能put5个对象
)).build(true);
return cacheManager;
}
}
执行结果:
上面demo可以看出超过5个对象Ehcache会将之前的数据移除
off-heap
off-heap叫做堆外内存,将你的对象从堆中脱离出来序列化,然后存储在一大块内存中,这就像它存储到磁盘上一样,但它仍然在RAM中。对象在这种状态下不能直接使用,它们必须首先反序列化,也不受垃圾收集。序列化和反序列化将会影响部分性能(所以可以考虑使用FST-serialization)使用堆外内存能够降低GC导致的暂停。我们看看下面这个demo
public class EhcacheTest2 {
public static void main(String[] args){
CacheManager cacheManager = EhcacheTest2.OffHeapDemo();
Cache<String,String> cache = cacheManager.getCache("tieredCache",String.class, String.class);
for(int i = 0 ; i < 10 ; i++){
cache.put(i+"a",Math.random()+"aaa");
}
for(int i = 0 ; i < 10 ; i++){
String v = cache.get(i+"a");
System.out.println(v);
}
System.out.println("---------------------------------------------------------------------------");
CacheManager cacheManagerHeap = heapDemo();
Cache<String,String> cacheHeap = cacheManagerHeap.getCache("tieredCache",String.class, String.class);
for(int i = 0 ; i < 10 ; i++){
cacheHeap.put(i+"a",Math.random()+"aaa");
}
for(int i = 0 ; i < 10 ; i++){
String v = cacheHeap.get(i+"a");
System.out.println(v);
}
System.out.println("---------------------------------------------------------------------------");
}
public static CacheManager OffHeapDemo(){
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().withCache("tieredCache",
CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, String.class,
ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(5, EntryUnit.ENTRIES) //和之前的创建CacheManager一样
.offheap(10, MemoryUnit.MB)) //增加offHeap
).build(true);
return cacheManager;
}
public static CacheManager heapDemo(){
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder().withCache("tieredCache",
CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, String.class,
ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(5, EntryUnit.ENTRIES) //和之前的创建CacheManager一样
)
).build(true);
return cacheManager;
}
}
执行结果:
从结果可以看出如果在heap上配合使用off-heap那么如果超过heap大小限制之后,对象会被放到off-heap中,这样对象就不会出现null值了。
disk
disk表示将对象写到磁盘中,这样有个好处是当服务重启时可以直接读取磁盘上面的内容将数据加载到服务中。off-heap和disk都需要序列化下面在来看一个disk例子。使用disk需要指定磁盘路径demo如下:
public class EhcacheTest5 {
public static void main(String[] args){
CacheManager cacheManager = EhcacheTest5.diskDemo();
Cache<String,String> cache = cacheManager.getCache("diskDemo",String.class, String.class);
//放10个对象进去。但是heap的大小只有5
for(int i = 0 ; i < 10 ; i++){
cache.put(i+"a",i+"aaa");
}
//按顺序取出着10个对象
for(int i = 0 ; i < 10 ; i++){
String key = i+"a";
String v = cache.get(key);
System.out.println("key:"+key+"value:"+v);
}
}
public static CacheManager diskDemo(){
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
// 设置缓存存目录
.with(CacheManagerBuilder.persistence(System.getProperty("user.dir") + File.separator + "myData"))
.withCache("diskDemo",
CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, String.class,
ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(5, EntryUnit.ENTRIES) //只能put5个对象
.disk(10, MemoryUnit.MB)
)).build(true);
return cacheManager;
}
}
这样你可以在你的项目中看到新建了一个文件夹叫myData。打印结果还是全部打印,不会出现null
当然这三种策略可以混合在一起使用。读取速度对比:
heap > off-heap > disk