Java Cache 的HashMap實現, 適用場景及分布式ehcache實例

openkk 12年前發布 | 82K 次閱讀 Ehcache 緩存組件

cache是老生常談的事情,但開始這個題目之前,我想先強調一下KISS原則,就是keep it simple and stupid。最近看到很多場景下cache使用的不適當,特別是被過度使用了。一個簡單鍵值存儲并不需要復雜的cache方案,好的方案就是用最簡單的方法解決問題。簡潔是美!

 

一個標準Cache的主要特征是:

過期時間       

容量規劃(重要)

清除策略(重要)

命中率統計 

 

基于以上特征,使用HashMap作為本地cache似乎很不適當。更重要的是,有不少朋友認為HashMap可能會使內存耗盡。其實不然,自 jdk1.2后,Java就引入了WeakHashMap。看看api文檔是怎么說的:對于一個給定的鍵,其映射的存在并不阻止垃圾回收器對該鍵的丟棄,這就使該鍵成為可終止的,被終止,然后被回收。丟棄某個鍵時,其條目從映射中有效地移除,因此,該類的行為與其他的 Map 實現有所不同。

 

這個翻譯明顯有點爛,總結一下,和強引用的HashMap相比,WeakHashMap在本身引用不被回收的前提下允許GC回收它的鍵值對。當GC 發現內存即將耗盡且沒有其他對象可以釋放時,會主動回收WeakHashMap所占用的對象。因此使用WeakHashMap作為本地cache是不會造成內存耗盡。如果你僅僅需要一個簡單的鍵值對存儲,而并不關心命中率統計,那么放心的使用WeakHashMap作為cache吧。

 

通過簡單的包裝,就可以為你的HashMap增加過期時間和容量規劃。而且比其他cache更高效。openfire的DefaultCache就是一個很好的例子:http://svn.igniterealtime.org/svn/repos/openfire/trunk/src/java /org/jivesoftware/util/cache/DefaultCache.java

 

DefaultCache的核心是HashMap,另外增加了一層很薄的包裝來實現過期和LRU。DefaultCache包括兩個 LinkedList,一個用于存儲插入順序,另一個用于存儲插入時間。當添加cache時,都addFirst。當cache size達到臨界值時,從最尾部刪除。有朋友測試過,比ehcache快5倍。

 

如果本地cache不能滿足你的要求,ehcache是個很好的選擇。不僅僅作為分布式的cache,甚至作為狀態同步,ehcache都有非常優秀的案例。也可以實現多機copy。分享一個數據,某生產系統中ehcache每天處理17,466,415次replication。

 

基于ehcache的分布式緩存,你可以簡單的實現分布式計算。分析一個場景,某ios后端服務要求用戶先注冊ios設備,可以按下圖處理設備信息。DeviceServer接受device注冊后同步copy的本地cache和ehcache。該ehcache按以下方式配置成對。本地 cache再定期(每隔幾秒鐘)從ehcache中加載peer server注冊的數據。

 

Java Cache 的HashMap實現, 適用場景及分布式ehcache實例

 

 

 

ehcache.xml
<cacheManagerPeerProviderFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerProviderFactory"
properties="peerDiscovery=manual,rmiUrls=//192.168.0.1:20121/testCache"/>
<cacheManagerPeerListenerFactory
class="net.sf.ehcache.distribution.RMICacheManagerPeerListenerFactory"
properties="hostName=192.168.0.2,port=20121,socketTimeoutMillis=60000"/>

<cache name="testCache"
maxElementsInMemory="20000"
eternal="false"
overflowToDisk="false"
memoryStoreEvictionPolicy="LRU">
<cacheEventListenerFactory class="net.sf.ehcache.distribution.RMICacheReplicatorFactory"
properties="replicateAsynchronously=true,
replicatePuts=true,
replicateUpdates=true,
replicateUpdatesViaCopy=true,
asynchronousReplicationIntervalMillis=2000"
/>
</cache>

peer server的hostName和rmiUrls配置需要做相應改動。

 

根據KISS原則,建議簡單狀態同步都使用ehcache完成。知識投入低,且易于維護。

 本文由用戶 openkk 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!