前面一節已經知道如何通過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;
}
}
執行結果:
執行結果.png
上面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;
}
}
執行結果:
demo2執行結果.png
從結果可以看出如果在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
myData.png
當然這三種策略可以混合在一起使用。讀取速度對比:
heap > off-heap > disk