java 緩存

1. 
  Cache簡介:

緩存(Cache)是計算機領域非常通用的概念。它介於應用程序和永久性數據存儲源(如硬盤上的文件或者數據庫)之間,其作用是降低應用程序直接讀寫永久性數據存儲源的頻率,從而提高應用的運行性能。緩存中的數據是數據存儲源中數據的拷貝,應用程序在運行時直接讀寫緩存中的數據,只在某些特定時刻按照緩存中的數據來同步更新數據存儲源。

緩存的物理介質通常是內存,而永久性數據存儲源的物理介質通常是硬盤或磁盤,應用程序讀寫內在的速度顯然比讀寫硬盤的速度快,如果緩存中存放的數據量非常大,也會用硬盤作爲緩存的物理介質。

緩存的實現不僅需要作爲物理介質的硬件,同時還需要用於管理緩存的併發訪問和過期等策略的軟件。因此,緩存是通過軟件和硬件共同實現的。

1.1.   持久化層的緩存的範圍

緩存的範圍決定了緩存的生命週期以及可以被誰訪問。緩存的範圍分爲三類。

1)事務範圍:緩存只能被當前事務訪問。緩存的生命週期依賴於事務的生命週期,當事務結束時,緩存也就結束生命週期。在此範圍下,緩存的介質是內存。事務可以是數據庫事務或者應用事務,每個事務都有獨自的緩存,緩存內的數據通常採用相互關聯的對象形式。

2)進程範圍:緩存被進程內的所有事務共享。這些事務有可能是併發訪問緩存,因此必須對緩存採取必要的事務隔離機制。緩存的生命週期依賴於進程的生命週期,進程結束時,緩存也就結束了生命週期。進程範圍的緩存可能會存放大量的數據,所以存放的介質可以是內存或硬盤。緩存內的數據既可以是相互關聯的對象形式也可以是對象的鬆散數據形式。鬆散的對象數據形式有點類似於對象的序列化數據,但是對象分解爲鬆散的算法比對象序列化的算法要求更快。

3)集羣範圍:在集羣環境中,緩存被一個機器或者多個機器的進程共享。緩存中的數據被複制到集羣環境中的每個進程節點,進程間通過遠程通信來保證緩存中的數據的一致性,緩存中的數據通常採用對象的鬆散數據形式。

對大多數應用來說,應該慎重地考慮是否需要使用集羣範圍的緩存,因爲訪問的速度不一定會比直接訪問數據庫數據的速度快多少。



持久化層可以提供多種範圍的緩存。如果在事務範圍的緩存中沒有查到相應的數據,還可以到進程範圍或集羣範圍的緩存內查詢,如果還是沒有查到,那麼只有到數據庫中查詢。事務範圍的緩存是持久化層的第一級緩存,通常它是必需的;進程範圍或集羣範圍的緩存是持久化層的第二級緩存,通常是可選的。

1.2.   持久化層的緩存的併發訪問策略

當多個併發的事務同時訪問持久化層的緩存的相同數據時,會引起併發問題,必須採用必要的事務隔離措施。

在進程範圍或集羣範圍的緩存,即第二級緩存,會出現併發問題。因此可以設定以下四種類型的併發訪問策略,每一種策略對應一種事務隔離級別。

1) 事務型(Transactional)策略:僅僅在受管理環境中適用。它提供了RepeatableRead事務隔離級別。對於經常被讀但很少修改的數據,可以採用這種隔離類型,因爲它可以防止髒讀和不可重複讀這類的併發問題。

2) 讀寫型(read-write)策略:提供了ReadCommitted事務隔離級別。僅僅在非集羣的環境中適用。對於經常被讀但很少修改的數據,可以採用這種隔離類型,因爲它可以防止髒讀這類的併發問題。

3)非嚴格讀寫型(nonstrict-read-write)策略:不保證緩存與數據庫中數據的一致性。如果存在兩個事務同時訪問緩存中相同數據的可能,必須爲該數據配置一個很短的數據過期時間,從而儘量避免髒讀。對於極少被修改,並且允許偶爾髒讀的數據,可以採用這種併發訪問策略。

4) 只讀型策略(read-only):對於從來不會修改的數據,如參考數據,可以使用這種併發訪問策略。

事務型併發訪問策略是事務隔離級別最高,只讀型的隔離級別最低。事務隔離級別越高,併發性能就越低。

2.   Hibernate中的緩存:

Hibernate中提供了兩級Cache,第一級別的緩存是Session級別的緩存,它是屬於事務範圍的緩存。這一級別的緩存由hibernate管理的,一般情況下無需進行干預;第二級別的緩存是SessionFactory級別的緩存,它是屬於進程範圍或羣集範圍的緩存。這一級別的緩存可以進行配置和更改,並且可以動態加載和卸載。

Hibernate還爲查詢結果提供了一個查詢緩存,它依賴於第二級緩存。

2.1.   一級緩存和二級緩存的比較:

  第一級緩存 第二級緩存

存放數據的形式 相互關聯的持久化對象 對象的散裝數據

緩存的範圍 事務範圍,每個事務都有單獨的第一級緩存 進程範圍或集羣範圍,緩存被同一個進程或集羣範圍內的所有事務共享

併發訪問策略 由於每個事務都擁有單獨的第一級緩存,不會出現併發問題,無需提供併發訪問策略由於多個事務會同時訪問第二級緩存中相同數據,因此必須提供適當的併發訪問策略,來保證特定的事務隔離級別

數據過期策略 沒有提供數據過期策略。處於一級緩存中的對象永遠不會過期,除非應用程序顯式清空緩存或者清除特定的對象必須提供數據過期策略,如基於內存的緩存中的對象的最大數目,允許對象處於緩存中的最長時間,以及允許對象處於緩存中的最長空閒時間

物理存儲介質 內存內存和硬盤。對象的散裝數據首先存放在基於內在的緩存中,當內存中對象的數目達到數據過期策略中指定上限時,就會把其餘的對象寫入基於硬盤的緩存中。

緩存的軟件實現 在Hibernate的Session的實現中包含了緩存的實現由第三方提供,Hibernate僅提供了緩存適配器(CacheProvider)。用於把特定的緩存插件集成到Hibernate中。

啓用緩存的方式只要應用程序通過Session接口來執行保存、更新、刪除、加載和查詢數據庫數據的操作,Hibernate就會啓用第一級緩存,把數據庫中的數據以對象的形式拷貝到緩存中,對於批量更新和批量刪除操作,如果不希望啓用第一級緩存,可以繞過HibernateAPI,直接通過JDBC API來執行指操作。用戶可以在單個類或類的單個集合的粒度上配置第二級緩存。如果類的實例被經常讀但很少被修改,就可以考慮使用第二級緩存。只有爲某個類或集合配置了第二級緩存,Hibernate在運行時纔會把它的實例加入到第二級緩存中。

用戶管理緩存的方式第一級緩存的物理介質爲內存,由於內存容量有限,必須通過恰當的檢索策略和檢索方式來限制加載對象的數目。Session的evit()方法可以顯式清空緩存中特定對象,但這種方法不值得推薦。第二級緩存的物理介質可以是內存和硬盤,因此第二級緩存可以存放大量的數據,數據過期策略的maxElementsInMemory屬性值可以控制內存中的對象數目。管理第二級緩存主要包括兩個方面:選擇需要使用第二級緩存的持久類,設置合適的併發訪問策略:選擇緩存適配器,設置合適的數據過期策略。

2.2.   一級緩存的管理:

當應用程序調用Session的save()、update()、savaeOrUpdate()、get()或load(),以及調用查詢接口的list()、iterate()或filter()方法時,如果在Session緩存中還不存在相應的對象,Hibernate就會把該對象加入到第一級緩存中。當清理緩存時,Hibernate會根據緩存中對象的狀態變化來同步更新數據庫。

Session爲應用程序提供了兩個管理緩存的方法:

evict(Object obj):從緩存中清除參數指定的持久化對象。

clear():清空緩存中所有持久化對象。

2.3.   二級緩存的管理:

2.3.1.     Hibernate的二級緩存策略的一般過程如下:

1) 條件查詢的時候,總是發出一條select * from table_name where ….(選擇所有字段)這樣的SQL語句查詢數據庫,一次獲得所有的數據對象。

2) 把獲得的所有數據對象根據ID放入到第二級緩存中。

3)當Hibernate根據ID訪問數據對象的時候,首先從Session一級緩存中查;查不到,如果配置了二級緩存,那麼從二級緩存中查;查不到,再查詢數據庫,把結果按照ID放入到緩存。

4) 刪除、更新、增加數據的時候,同時更新緩存。

  Hibernate的二級緩存策略,是針對於ID查詢的緩存策略,對於條件查詢則毫無作用。爲此,Hibernate提供了針對條件查詢的QueryCache。

2.3.2.     什麼樣的數據適合存放到第二級緩存中?

1 很少被修改的數據

2 不是很重要的數據,允許出現偶爾併發的數據

3 不會被併發訪問的數據

4 參考數據,指的是供應用參考的常量數據,它的實例數目有限,它的實例會被許多其他類的實例引用,實例極少或者從來不會被修改。

2.3.3.     不適合存放到第二級緩存的數據?

1 經常被修改的數據

2 財務數據,絕對不允許出現併發

3 與其他應用共享的數據。



2.3.4.     常用的緩存插件

Hibernater 的二級緩存是一個插件,下面是幾種常用的緩存插件:

l EhCache:可作爲進程範圍的緩存,存放數據的物理介質可以是內存或硬盤,對Hibernate的查詢緩存提供了支持。

lOSCache:可作爲進程範圍的緩存,存放數據的物理介質可以是內存或硬盤,提供了豐富的緩存數據過期策略,對Hibernate的查詢緩存提供了支持。

l SwarmCache:可作爲羣集範圍內的緩存,但不支持Hibernate的查詢緩存。

l JBossCache:可作爲羣集範圍內的緩存,支持事務型併發訪問策略,對Hibernate的查詢緩存提供了支持。



2.3.5.     配置二級緩存的主要步驟:

1)     選擇需要使用二級緩存的持久化類,設置它的命名緩存的併發訪問策略。這是最值得認真考慮的步驟。

2)     選擇合適的緩存插件,然後編輯該插件的配置文件。

2.4.   使用EhCache配置二級緩存:

2.4.1.     配置準備:

1)     把ehcache-1.2.3.jar加入到當前應用的classpath中。

2)     在hibernate.cfg.xml文件中加入EhCache緩存插件的提供類。

< !--配置緩存插件 -->

< propertyname="hibernate.cache.provider_class">

   org.hibernate.cache.EhCacheProvider

< /property>

3)     挎貝ehcache.xml文件到類路徑(項目工程的src目錄下),這個文件在Hibernate安裝目錄的etc下。

2.4.2.     配置步驟:

Hibernate允許在類和集合的粒度上設置第二級緩存。在映射文件中,<class>和<set>元素都有一個<cache>子元素,這個子元素用來配置二級緩存。

示例:以category(產品類別)和product(產品)的映射爲例:

1)     修改要配置緩存的那個持久化類的對象關係映射文件:

Category.hbm.xml

< ?xml version="1.0"encoding="utf-8"?>

< !DOCTYPE hibernate-mapping PUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN"

"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">



< hibernate-mapping>

   < class name="org.qiujy.domain.cachedemo.Category"table="categories">

      < !?

            配置緩存,必須緊跟在class元素後面

           對緩存中的Category對象採用讀寫型的併發訪問策略

       -->

      < cache usage="read-write"/>

      

      < id name="id"type="java.lang.Long">

          < column name="id" />

          < generator class="native" />

      < /id>

      < !-- 配置版本號,必須緊跟在id元素後面 -->

      < version name="version" column="version"type="java.lang.Long" />

      

      < property name="name"type="java.lang.String">

          < column name="name" length="32"not-null="true"/>

      < /property>

      

      < property name="description"type="java.lang.String">

          < column name="description"length="255"/>

      < /property>

      

    
發佈了0 篇原創文章 · 獲贊 1 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章