和《Hibernate 關(guān)系映射 收集、總結整理》 一樣,本篇文章也是我很早之前收集、總結整理的,在此也發(fā)上來(lái) 希望對大家有用。因為是很早之前寫(xiě)的,不當之處請指正。
1、緩存:緩存是什么,解決什么問(wèn)題?
位于速度相差較大的兩種硬件/軟件之間的,用于協(xié)調兩者數據傳輸速度差異的結構,均可稱(chēng)之為 Cache(摘自Robbin的《緩存技術(shù)淺談》)。目的:讓數據更接近于應用程序,協(xié)調速度不匹配,使訪(fǎng)問(wèn)速度更快。(請參考http://baike.baidu.com/view/907.htm 了解更多緩存知識)
高速緩存不屬于Hibernate等,屬于獨立產(chǎn)品或框架,可單獨使用。
常見(jiàn)緩存算法:
a) LFU(Least Frequently Used):最近不常被使用(命中率低),一定時(shí)間段內使用次數最少的
b) LRU(Least Recently Used):最近很少使用(LinkedHashMap),沒(méi)有被使用時(shí)間最長(cháng)的
c) FIFO(First In First Out):先進(jìn)先出
2、緩存策略
1.對象緩存
2.查詢(xún)緩存
3.頁(yè)面緩存
1.動(dòng)態(tài)頁(yè)面緩存
2.Servlet緩存
3.頁(yè)面片段緩存
3、緩存分類(lèi)
1. Web緩存:
i. 瀏覽器緩存:ajax(在客戶(hù)端緩存)、HTTP協(xié)議
ii. 代理服務(wù)器緩存
2. 操作系統緩存:如用于減少磁盤(pán)操作
3. 數據庫緩存:
i. 結果緩存:
ii. 排序緩存
iii. 插入緩存
iv. 日志緩存
v. ………………
4. 應用程序緩存
i. 對象緩存
ii. 查詢(xún)緩存
iii. 頁(yè)面緩存
1. 動(dòng)態(tài)頁(yè)面靜態(tài)化:網(wǎng)頁(yè)靜態(tài)化、獨立圖片服務(wù)器
2. 頁(yè)面局部緩存:
3. 請求回應緩存:
4、常見(jiàn)Java緩存框架
EHCache
OSCache
JBossCache
SwarmCache
5、通用緩存產(chǎn)品
Memcached:在大規?;ヂ?lián)網(wǎng)應用下使用,可用于分布式環(huán)境,每秒支撐1.5萬(wàn)~2萬(wàn)次請求
Tokyo Tyrant:兼容memcached協(xié)議,可以持久化存儲,支持故障切換,對緩存服務(wù)器有高可靠性要求可以使用,每秒支撐0.5萬(wàn)~0.8萬(wàn)次請求
6、基于Web應用的緩存應用場(chǎng)景:

(摘自bluedavy的《大型網(wǎng)站架構演化》)
8、緩存實(shí)戰:
8.4、ORM緩存
8.4.1、目的:
Hibernate緩存:使當前數據庫狀態(tài)的表示接近應用程序,要么在內存中,要么在應用程序服務(wù)器機器的磁盤(pán)上。高速緩存是數據的一個(gè)本地副本,處于應用程序和數據庫之間,可用來(lái)避免數據庫的命中。
8.4.2、避免數據庫命中:
應用程序根據標識符到緩存查,有就返回,沒(méi)有再去數據庫.
8.4.3、ORM緩存分類(lèi)
一級緩存、二級緩存
8.4.4、緩存范圍
1、事務(wù)范圍高速緩存,對應于一級緩存(單Session)
2、過(guò)程(JVM)范圍高速緩存,對應于二級緩存(單SessionFactory)
3、集群范圍高速緩存,對應于二級緩存(多SessionFactory)
8.4.5、緩存哪些數據
1、很少改變的數據;
2、不重要的數據,如論壇帖子,無(wú)需實(shí)時(shí)的數據;
3、應用程序固有的而非共享的。
4、讀大于寫(xiě)有用
8.4.6、Hibernate緩存架構

圖摘自《Hibernate in Action》
Hibernate中的二級緩存是可插拔的。
Hibernate二級緩存支持對象緩存、集合緩存、查詢(xún)結果集緩存,對于查詢(xún)結果集緩存可選。
查詢(xún)緩存:需要兩個(gè)額外的物理高速緩存區域:一個(gè)用于存放查詢(xún)的結果集;另一個(gè)用于存儲表上次更新的時(shí)間戳

8.4.6.2、高速緩存實(shí)戰(ehcache)
8.4.6.2.1、全局配置(hibernate.cfg.xml)
8.4.6.2.2、ehcache配置(ehcache.xml)
8.4.6.2.3、實(shí)體只讀緩存
1、修改FarmModel.hbm.xml,添加如下紅色部分配置,表示實(shí)體緩存并只讀
2、測試代碼
只讀緩存不允許更新,將報錯Can't write to a readonly object。
允許新增,(現在2。0 新增直接添加到二級緩存)
8.4.6.2.4、實(shí)體非嚴格讀/寫(xiě)緩存
1、修改FarmModel.hbm.xml,添加如下紅色部分配置,表示實(shí)體緩存并非嚴格讀/寫(xiě)
2、測試代碼
允許更新,更新后緩存失效,需再查詢(xún)一次。
允許新增,新增記錄自動(dòng)加到二級緩存中。
整個(gè)過(guò)程不加鎖,不保證。
8.4.6.2.5、實(shí)體讀/寫(xiě)緩存
1、修改FarmModel.hbm.xml,添加如下紅色部分配置,表示實(shí)體緩存并讀/寫(xiě)
2、測試代碼
允許更新,更新后自動(dòng)同步到緩存。
允許新增,新增記錄后自動(dòng)同步到緩存。
保證read committed隔離級別及可重復讀隔離級別(通過(guò)時(shí)間戳實(shí)現)
整個(gè)過(guò)程加鎖,如果當前事務(wù)的時(shí)間戳早于二級緩存中的條目的時(shí)間戳,說(shuō)明該條目已經(jīng)被別的事務(wù)修改了,此時(shí)重新查詢(xún)一次數據庫,否則才使用緩存數據,因此保證可重復讀隔離級別。
8.4.6.2.6、實(shí)體事務(wù)緩存
需要特定緩存的支持和JTA事務(wù)支持,此處不演示。
8.4.6.2.7、集合緩存
此處演示讀/寫(xiě)緩存示例,其他自測
1、修改FarmModel.hbm.xml,添加如下紅色部分配置,表示實(shí)體緩存并讀/寫(xiě)
2、測試代碼
和實(shí)體并發(fā)策略有相同含義;
但集合緩存只緩存集合元素的標識符,在二級緩存中只存放相應實(shí)體的標識符,然后再通過(guò)標識符去二級緩存查找相應的實(shí)體最后組合為集合返回。
8.4.6.2.8、查詢(xún)緩存
1、保證全局配置中有開(kāi)啟了查詢(xún)緩存。
2、修改FarmModel.hbm.xml,添加如下紅色部分配置,表示實(shí)體緩存并讀/寫(xiě)
3、測試代碼
和實(shí)體并發(fā)策略有相同含義;
和集合緩存類(lèi)似,只緩存集合元素的標識符,在二級緩存中只存放相應實(shí)體的標識符,然后再通過(guò)標識符 去二級緩存查找相應的實(shí)體最后組合為集合返回。
8.4.6.2.9、高速緩存區域
Hibernate在不同的高速緩存區域保存不同的類(lèi)(實(shí)體)/集合,如果不配置區域默認都保存到“默認緩存”(defaultCache)中。
每一個(gè)區域可以設置過(guò)期策略、緩存條目大小等等。
對于類(lèi)緩存,默認區域名是全限定類(lèi)名,如cn.javass.h3test.model.UserModel。
對于集合而言,默認區域名是全限定類(lèi)名+屬性名,如cn.javass.….UserModel.farms。
可通過(guò)hibernate.cache.region_prefix指定特定SessionFactory的區域前綴,如前綴是h3test,則如類(lèi)緩存的區域名就是h3test.cn.javass.h3test.model.UserModel。如果應用程序使用多個(gè)SessionFactory 這可能是必須的。
可通過(guò)<cache usage="read-write" region="區域名"/>自定義區域名,不過(guò)默認其實(shí)就可以了。
8.4.6.2.10、ehcache配置詳解:
1、默認cache:如果沒(méi)有對應的特定區域的緩存,就使用默認緩存。
2、指定區域cache:通過(guò)name指定,name對應到Hibernate中的區域名即可。
3、cache參數詳解:
name:指定區域名
maxElementsInMemory :緩存在內存中的最大數目
maxElementsOnDisk:緩存在磁盤(pán)上的最大數目
eternal :緩存是否持久
overflowToDisk : 硬盤(pán)溢出數目
timeToIdleSeconds :當緩存條目閑置n秒后銷(xiāo)毀
timeToLiveSeconds :當緩存條目存活n秒后銷(xiāo)毀
memoryStoreEvictionPolicy:緩存算法,有LRU(默認)、LFU、FIFO
4、StandardQueryCache
用于查詢(xún)緩存使用,如果指定了該緩存,那么查詢(xún)緩存將放在該緩存中。
如果不給查詢(xún)設置區域名默認緩存到這,可以通過(guò)“query.setCacheRegion("區域名");”來(lái)設置查詢(xún)的區域名。
時(shí)間戳緩存,內部使用,用于保存最近更新的表的時(shí)間戳,這是非常重要的,無(wú)需失效,關(guān)閉時(shí)間戳緩存區域的過(guò)期時(shí)間。
Hibernate使用時(shí)間戳區域來(lái)決定被高速緩存的查詢(xún)結果集是否是失效的。當你重新執行了一個(gè)啟用了高速緩存的查詢(xún)時(shí),Hibernate就在時(shí)間戳緩存中查找對被查詢(xún)的(幾張)表所做的最近插入、更新或刪除的時(shí)間戳。如果找到的時(shí)間戳晚于高速緩存查詢(xún)結果的時(shí)間戳,那么緩存結果將被丟棄,重新執行一次查詢(xún)。
8.4.6.2.11、什么時(shí)候需要查詢(xún)緩存
大多數時(shí)候無(wú)法從結果集高速緩存獲益。必須知道:每隔多久重復執行同一查詢(xún)。
對于那些查詢(xún)非常多但插入、刪除、更新非常少的應用程序來(lái)說(shuō),查詢(xún)緩存可提升性能。但寫(xiě)入多查詢(xún)少的沒(méi)有用,總失效。
8.4.6.2.12、管理一級緩存
無(wú)論何時(shí),當你給save()、update()或 saveOrUpdate()方法傳遞一個(gè)對象時(shí),或使用load()、get()、list()、iterate() 或scroll()方法獲得一個(gè)對象時(shí), 該對象都將被加入到Session的內部緩存中。
當隨后flush()方法被調用時(shí),對象的狀態(tài)會(huì )和數據庫取得同步。 如果你不希望此同步操作發(fā)生,或者你正處理大量對象、需要對有效管理內存時(shí),你可以調用evict()方法,從一級緩存中去掉這些對象及其集合。
ScrollableResult cats =sess.createQuery("from Cat as cat").scroll(); //a huge result set
while ( cats.next() ) {
Cat cat = (Cat) cats.get(0);
doSomethingWithACat(cat);
sess.evict(cat);
}
Session還提供了一個(gè)contains()方法,用來(lái)判斷某個(gè)實(shí)例是否處于當前session的緩存中。
如若要把所有的對象從session緩存中徹底清除,則需要調用Session.clear()。
CacheMode參數用于控制具體的Session如何與二級緩存進(jìn)行交互。
CacheMode.NORMAL - 從二級緩存中讀、寫(xiě)數據。
CacheMode.GET - 從二級緩存中讀取數據,僅在數據更新時(shí)對二級緩存寫(xiě)數據。
CacheMode.PUT - 僅向二級緩存寫(xiě)數據,但不從二級緩存中讀數據。
CacheMode.REFRESH - 僅向二級緩存寫(xiě)數據,但不從二級緩存中讀數據。通過(guò)hibernate.cache.use_minimal_puts的設置,強制二級緩存從數據庫中讀取數據,刷新緩存內容。
8.4.6.2.12、管理二級緩存
對于二級緩存來(lái)說(shuō),在SessionFactory中定義了許多方法, 清除緩存中實(shí)例、整個(gè)類(lèi)、集合實(shí)例或者整個(gè)集合。
sessionFactory.evict(Cat.class, catId); //evict a particular Cat
sessionFactory.evict(Cat.class); //evict all Cats
sessionFactory.evictCollection("Cat.kittens", catId); //evict aparticular collection of kittens
sessionFactory.evictCollection("Cat.kittens"); //evict allkitten collections
sessionFactory.evictQueries()//evict all queries
8.4.6.2.13、監控二級緩存
如若需要查看二級緩存或查詢(xún)緩存區域的內容,你可以使用統計(Statistics) API。
通過(guò)sessionFactory.getStatistics();獲取Hibernate統計信息。
此時(shí),你必須手工打開(kāi)統計選項。
hibernate.generate_statistics true
hibernate.cache.use_structured_entriestrue
具體詳見(jiàn)“hibernate監控.rar”(需要自己稍微改改才能用)
需要修改head.jsp中的如下代碼獲取sessionFactory
參考資料:
Robbin的《緩存技術(shù)淺談》
百度百科的高速緩存知識 http://baike.baidu.com/view/907.htm
bluedavy的《大型網(wǎng)站架構演化》(http://www.blogjava.net/BlueDavy/archive/2008/09/03/226749.html)
《Hibernate in Action》
聯(lián)系客服