Java實現cache的基本機制


 我這里說的cache不是指CPU和RAM之間的緩存,而是Java應用中間常用的緩存。最常使用的場合就是訪問數據庫的時候為了提高效率而使用的 cache。一般的用法就是把數據從數據庫讀到內存,然后之后的數據訪問都從內存來讀,從而減少對數據庫的讀取次數來提高效率。

   在使用cache的時候最容易犯的錯誤就是cache涉及了業務邏輯。使用cache的原意是只是提高程序效率,而不應該干涉程序結果。按照cahce的定義,cache應該是對數據訪問端透明 地工作。所以在使用cache的時候我們可以問一下自己:“我把cache拿掉后程序還能運行嗎?” “cache拿掉前后程序運行的結果一直嗎?”。如果答案是否,那您就得重新考慮您的cache方案。我自己就碰到過這樣的bug:數據庫的有個表里面都 是些配置信息,也就是說是些讀訪問遠大於寫訪問 的數據。然后這些數據被理所應當地在程序里面做成內存 cache。問題是有個delete方法刪除了一條數據,但是沒有更新內存cache。所以讀操作的客戶代碼還是能讀到這條數據。問題的根本就是后台數據和cache不一致。

   cache的容量一般相對后台數據量都比較有限。一旦cache滿了就勢必要選擇最沒用的數據從cache里面刪除掉,為新數據騰出空間。這里就涉及 cahce算法cache algorithm或者叫替換算法。在java的cache產品中一般叫evict policy。下面我們來看一下常用的cache algorithm。

  • 最近最少使用算法 Least Recently Used (LRU):
 這個算法就是把最近一次使用時間離現在時間最遠的數據刪除掉。最直觀的結構應該是List,采取的算法是:每次訪問一個元素后把這個元素放在 List一端,這樣一來最遠使用的元素自然就被放到List的另一端。每次evict的時候就把那最遠使用的元素remove掉。但是現實中常采用的數據 結構是HashMap + List。因為List太慢,List只能提供O(n)的算法,要使得它的add,remove和get的算法為O(1)就必須使用HashMap。最簡 單的實現就是利用JDK自帶的LinkedHashMap,你可以把它看作普通的HashMap之外,每個元素的key都用鏈表連接起來從而實現順序結 構。LinkedHashMap默認的元素順序是put的順序,但是如果使用帶參數的構造函數,那么LinkedHashMap會根據訪問順序來調整內部 順序。 LinkedHashMap的get()方法除了返回元素之外還可以把被訪問的元素放到鏈表的底端,這樣一來每次頂端的元素就是remove的元素。
  • First In, First Out算法
這個比較直觀,就是個Queue。但是還是為了保證O(1)的效率,還是要用LinkedHashMap。但是這次使用默認的無參數的構造函數,LinkedHashMap內部使用的是put的順序。因此每次remove頂端即可。
  • 最近最多時用算法Most Recently Used (MRU)
這個算法和LRU是相反操作,所以沒什么新鮮的東西。每次remove LinkedHashMap底端的元素就可以實現。
  • 使用次數最小算法 Least Frequently Used (LFU)
這 個算法的核心是每次訪問元素的時候,這個元素的次數屬性加1。所以每次remove操作就是次數屬性最小的元素。這次沒法用LinkedHashMap來 實現了,因為LinkedHashMap沒有接受comparator參數的功能。有些程序是用LinkedList + HashMap來實現。這樣add和get操作還是O(1),只是remove操作的時候先要排序然后再remove,最快也就是O(n*log n),譬如利用快速排序。或者干脆在remove的時候只是做查找最小元素的算法來除去訪問次數最小的元素。

   另外還有其他的cache算法,譬如按照元素自帶的過期值expiration和隨機random來evict元素的算法。在真正的cache產品中數據結構和算法要比上面描述的要復雜。有些產品自己定義一些數據結構來提高效率,畢竟cache是為了提高效率而產生的。高級的cache產品還可能包括事務機制,JMX和支持cluster環境這樣復雜的特性。
 
   目前比較主流的cache產品有EHCache,OSCache,SwarmCache和JBoss Cache,很多使用Hibernate的人都對都此有些了解。關於JBoss Cache,它在將來可能被JBoss的另外一個叫 infinispan 的數據網格平台項目所替代。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM