Google的Guava cache 應用

Guava Cache 建立
基本上能夠經過兩種方式來建立cache:

cacheLoader
callable callback


經過這兩種方法建立的cache,和一般用map來緩存的作法比,不一樣在於,這兩種方法都實現了一種邏輯——從緩存中取key X的值,若是該值已經緩存過了,則返回緩存中的值,若是沒有緩存過,能夠經過某個方法來獲取這個值。

但不一樣的在於cacheloader的定義比較寬泛,是針對整個cache定義的,能夠認爲是統一的根據key值load value的方法。

而callable的方式較爲靈活,容許你在get的時候指定。

下面是兩種方法的例子:

首先是基於cacheloader的方法 java

@Test
public void testCacheBuilder() throws ExecutionException {

	LoadingCache<String, String> graphs = CacheBuilder.newBuilder()
		.maximumSize(1000)
		.build(new CacheLoader<String, String>() {
			public String load(String key) {
				// 這裏是key根據實際去取值的方法
				return "value";
			}
		});

	String resultVal = graphs.get("testKey");
	System.out.println(resultVal);
}


 其次是基於實現callable的方法: 緩存

@Test
public void testCallable() throws ExecutionException {
	// 沒有使用CacheLoader
	Cache<String, String> cache = CacheBuilder.newBuilder()
		.maximumSize(1000)
		.build();

	String resultVal = cache.get("testKey", new Callable<String>() {
		public String call() {
			// 這裏先根據key實際去取值的方法
			return "value";
		}
	});
	System.out.println(resultVal);
}

Guava Cache 數據的移除
被動移除數據的方式,guava默認提供了三種方式:


基於大小的移除

看字面意思就知道就是按照緩存的大小來移除,若是即將到達指定的大小,那就會把不經常使用的鍵值對從cache中移除。

定義的方式通常爲 CacheBuilder.maximumSize(long),官方還介紹了一種能夠算權重的方法,我的認爲實際使用中不太用到,暫不討論。

就這個經常使用的來看有幾個注意點,
其一,這個size指的是cache中的條目數,不是內存大小或是其餘;
其二,並非徹底到了指定的size系統纔開始移除不經常使用的數據的,而是接近這個size的時候系統就會開始作移除的動做;
其三,若是一個鍵值對已經從緩存中被移除了,你再次請求訪問的時候,若是cachebuild是使用cacheloader方式的,那依然仍是會從cacheloader中再取一次值,若是這樣尚未,就會拋出異常


基於時間的移除

      guava提供了兩個基於時間移除的方法
      expireAfterAccess(long, TimeUnit)  這個方法是根據某個鍵值對最後一次訪問以後多少時間後移除
      expireAfterWrite(long, TimeUnit)    這個方法是根據某個鍵值對被建立或值被替換後多少時間移除

基於引用的移除

      這種移除方式主要是基於java的垃圾回收機制,根據鍵或者值的引用關係決定移除,我的對垃圾回收這塊不是很是瞭解,竊覺得不太可靠。。也不經常使用。。因此沒有研究,歡迎補充。


主動移除數據方式 
       主動移除有三種方法: 
             單獨移除用 Cache.invalidate(key)
     批量移除用 Cache.invalidateAll(keys)
             移除全部用 Cache.invalidateAll()


       若是須要在移除數據的時候有所動做還能夠定義Removal Listener,可是有點須要注意的是默認Removal Listener中的行爲是和移除動做同步執行的,若是須要改爲異步形式,能夠考慮使用RemovalListeners.asynchronous(RemovalListener, Executor)

Guava Cache 的清空,刷新及統計功能
主要介紹guava cache的清空,刷新和統計的功能。 
緩存數據的清空 
      guava沒有提供自動觸發清空緩存數據的功能,而是提供了一種手工調用的方式,使用者須要經過Cache.cleanUp()的方式來清空緩存。

      因此通常能夠有兩種選擇,一種是經過某個請求來觸發清空動做,這種至關於按需清空,另外一種則是經過定時任務,亦成爲調度程序來清空,這種至關於與按時清空

緩存數據的刷新 
      guava沒有提供相似refreshall的方法刷新緩存中的全部值,而只是提供了 LoadingCache.refresh(K)方法,用於刷新某個鍵值對,這裏有趣的是刷新動做是異步的,也就是在值被完全刷新以前,若是有人取這個key的值,返回的仍是沒有刷新的值。 異步

      若是你但願定義本身的刷新行爲,能夠重寫 CacheLoader.reload(K, V)方法

LoadingCache<Key, Graph> graphs = CacheBuilder.newBuilder()
   .maximumSize(1000)
   .refreshAfterWrite(1, TimeUnit.MINUTES)
   .build(
	   new CacheLoader<Key, Graph>() {
		 public Graph load(Key key) { // no checked exception
		   return getGraphFromDatabase(key);
		 }

		 public ListenableFuture<Graph> reload(final Key key, Graph prevGraph) {
		   if (neverNeedsRefresh(key)) {
			 return Futures.immediateFuture(prevGraph);
		   } else {
			 // asynchronous!
			 return ListenableFutureTask.create(new Callable<Graph>() {
			   public Graph call() {
				 return getGraphFromDatabase(key);
			   }
			 });
		   }
		 }
	   });
緩存數據統計 
      能夠經過 CacheBuilder.recordStats()方法打開統計, Cache.stats()方法會返回一個CacheStats對象,裏面有緩存條目訪問率等數據,若是你的緩存須要作一些調優,能夠參考這裏的數據。
相關文章
相關標籤/搜索