国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
Hibernate二級(jí)緩存

  2010年11月7號(hào),立冬,星期天。北京外面風(fēng)好大,躲在家里整理一下這篇文章,發(fā)出來與大家分享,對(duì)大家有幫助是我最高興的事兒。

 

    不要想當(dāng)然的認(rèn)為使用了Hibernate的二級(jí)緩存就一定能夠提高應(yīng)用程序的性能,僅僅在你能夠駕馭它,并且條件適合的情況下才是這樣的。
    使用hibernate的二級(jí)緩存限制還是比較多的。在不了解原理的情況下,可能緩存中的數(shù)據(jù)頻繁的被清空性能下降,可能會(huì)有1+N的問題,在批量insert,update數(shù)據(jù)時(shí)二級(jí)緩存會(huì)占用大量內(nèi)存,就算不溢出也會(huì)花費(fèi)長時(shí)間來GC,不了解緩存的鎖可能會(huì)出現(xiàn)死鎖、臟數(shù)據(jù)。

 

一、緩存應(yīng)用的場(chǎng)景:
1、對(duì)于新聞,論壇,博客等互聯(lián)網(wǎng)應(yīng)用適合在前端做緩存,比如url做為key來緩存整個(gè)頁面的內(nèi)容。一條新聞a被如前所述的緩存起來了,在網(wǎng)站并發(fā)訪問量大時(shí),會(huì)大大提高網(wǎng)站的吞吐能力。好了現(xiàn)再須要編輯這條新聞,如何同步更新緩存呢?須要立即同步更新緩存嗎?不須要,互聯(lián)網(wǎng)應(yīng)用允許用戶在5-10分鐘之后再看到更新之后的新聞,這是可以接受的。沒有較高的時(shí)效性,允許延遲。這樣我們?cè)O(shè)定緩存對(duì)象的最大生命時(shí)間為10分鐘,一個(gè)被緩存的對(duì)象存活時(shí)間超過10分鐘就被清理,當(dāng)新的訪問請(qǐng)求到來時(shí),再從數(shù)據(jù)庫中加載他,再次被緩存10分鐘。Hibernate二級(jí)緩存不適合這個(gè)場(chǎng)景,這個(gè)場(chǎng)景對(duì)緩存的鎖、事務(wù)沒有要求,對(duì)高并發(fā),高數(shù)據(jù)量有要求。
    總結(jié)一下:被緩存的對(duì)象沒有較高的時(shí)效性,允許對(duì)象更新后延遲(10分鐘內(nèi))展示,允許(10分鐘內(nèi))的數(shù)據(jù)不一致。

2、對(duì)于企業(yè)應(yīng)用,要保證數(shù)據(jù)的一致性是第一位的,即使數(shù)據(jù)被修改,最終用戶看到的數(shù)據(jù)與數(shù)據(jù)庫中的數(shù)據(jù)要時(shí)時(shí)一致。適合在應(yīng)用程序持久層上做緩存,Hibernate二級(jí)緩存就適合這個(gè)場(chǎng)景。
    總結(jié)一下:這個(gè)場(chǎng)景對(duì)緩存的鎖,事務(wù)要求是第一的。對(duì)高并發(fā)高數(shù)據(jù)量的要求是第二的,通過鎖保證數(shù)據(jù)的一致性。Hibernate對(duì)數(shù)據(jù)庫是獨(dú)占的,修改給數(shù)據(jù)庫的操作都通過他.

 

二、頻繁更新的數(shù)據(jù)要不要被緩存:
網(wǎng)上有人說頻繁更新的數(shù)據(jù)不適合使用緩存。這樣說是不全面的,因?yàn)樗僬f了前提條件。

 

數(shù)據(jù)一致性:本文章的數(shù)據(jù)一致性是指緩存中的數(shù)據(jù)與數(shù)據(jù)庫中的數(shù)據(jù)就保持一致,嚴(yán)格的一致。決對(duì)沒有臟數(shù)據(jù)。

 

當(dāng)你須要數(shù)據(jù)一致性,而又不能保存數(shù)據(jù)一致性時(shí),頻繁更新的數(shù)據(jù)就不可以被緩存。不緩存直接操作數(shù)據(jù)庫,就一致了,沒有不一致的問題了。

      你的Hibernate對(duì)數(shù)據(jù)庫不是獨(dú)占的,有其它程序來修改數(shù)據(jù)庫中的記錄,這時(shí)Hibernate是不知道的,也會(huì)發(fā)生數(shù)據(jù)不一致.

      當(dāng)使用url或sql語句做為KEY來緩存時(shí),一句select 語句查出n個(gè)對(duì)象,無法在緩存中精準(zhǔn)的找到被修改的某一個(gè)對(duì)象,當(dāng)修改一個(gè)對(duì)象時(shí)就不能在緩存中精準(zhǔn)的找到他,為了保證數(shù)據(jù)一致性,就要清除緩存中所有的同類對(duì)象,使下次查詢時(shí)無法命中緩存。而不清除,很有可能發(fā)生數(shù)據(jù)不一致。這相當(dāng)于Hibernate的查詢緩存。這時(shí)個(gè)不要使用緩存。

     
當(dāng)你須要數(shù)據(jù)一致性,而又能保存數(shù)據(jù)一致性時(shí),頻繁更新的數(shù)據(jù)是可以被緩存的。這里我們使用緩存的“鎖”機(jī)制來保證,你使用的Hibernate第三方緩存要支持“鎖”,就是read-write模式。這是重點(diǎn)啊。第三方緩存鎖的實(shí)現(xiàn)方法不同性能也不同,鎖是緩存性能下降第一原因,一定要使用高性能的鎖,這就要了解多款Hibernate第三方緩存.

      因?yàn)榻?jīng)常被更新修改的對(duì)象,一定也更加經(jīng)常的被查詢,需要緩存他來提高應(yīng)用程序的性能。如果執(zhí)行修改sql時(shí),同時(shí)鎖住緩存中的這個(gè)對(duì)象并更新他,之后解鎖是最理想的。Hibernate的二級(jí)緩存策略,是針對(duì)于ID查詢的緩存策略,所以可以做到精準(zhǔn)的找到緩存中的目標(biāo),加之“鎖”的幫助,可實(shí)現(xiàn)數(shù)據(jù)一致性。

但限制也有比如使用HQL時(shí)就不能精準(zhǔn)的找到緩存中的目標(biāo),只好清除緩存中所有的同類對(duì)象來保證數(shù)據(jù)的一致性(緩存中沒數(shù)據(jù)就沒一致性問題了)。


三、Hibernate二級(jí)緩存中的對(duì)象什么時(shí)候會(huì)被清理:
在read-write模式下:
我們有一個(gè)Order對(duì)象,是一個(gè)實(shí)體對(duì)象,對(duì)應(yīng)數(shù)據(jù)庫中order表中的一條記錄,經(jīng)過查詢已有n個(gè)Order對(duì)象被放入二級(jí)緩存中。現(xiàn)在我們要修改order表中任意任x條記錄,執(zhí)行以下HQL:

template.bulkUpdate("update Order set owner = ? where id in (?,?,?)");

 

 這時(shí)Hibernate會(huì)直接將二級(jí)緩存中的n個(gè)Order對(duì)象清除掉。 天啊,居然不是你想像的修改誰就同步更新二級(jí)緩存中的誰,而是清除了二級(jí)緩存中全部的Order類型的對(duì)象。為什么?這一切是為了保證“數(shù)據(jù)一致性”。你執(zhí)行了HQL修改了order表中的x條記錄,這x條是哪幾條?如果sql是子查詢:update Order set owner =? where id in(select id from *** ),誰知道你修改了order表中的哪幾條記錄,你自己都不知道,Hibernate更不知道了。所以為了保證二級(jí)緩存中的數(shù)據(jù)與order表中的數(shù)據(jù)一致,只能清除了二級(jí)緩存中全部的Order類型的對(duì)象。二級(jí)緩存頻繁的載入與清除,這樣緩存命中率就會(huì)下降。

試驗(yàn):
看到這里后,我很擔(dān)心,這樣命中率下降后,沒有起到緩存的作用。今天特意做一個(gè)實(shí)驗(yàn),看看被緩存的對(duì)象在被修改后會(huì)怎樣。

環(huán)境:Hibernate3.4 , OsCache(usage="read-write"),JUnit
緩存狀態(tài):Hibernate二級(jí)緩存中已緩存了5個(gè)Order對(duì)象。
測(cè)試結(jié)果:
1 使用saveOrUpdate()方法更新一個(gè)實(shí)體對(duì)象a時(shí),新的a對(duì)象被put到二級(jí)緩存中,同時(shí)寫入數(shù)據(jù)庫,二級(jí)緩存中的其它4個(gè)Order對(duì)象沒有變化。
這時(shí)再查詢這5個(gè)Order對(duì)象中的任意,是可以命中二級(jí)緩存的。
2 使用HQL "update Order set name = ? where id =?" 方法更新一個(gè)實(shí)體對(duì)象a時(shí),所有Order對(duì)象被從二級(jí)緩存中清除,同時(shí)a對(duì)象被寫入數(shù)據(jù)庫。
這時(shí)再查詢這5個(gè)Order對(duì)象中的任意,無法命中二級(jí)緩存,會(huì)去查數(shù)據(jù)庫,查出來的對(duì)象又put進(jìn)二級(jí)緩存。

Hibernate的二級(jí)緩存策略,是以ID做為key 的緩存策略,在刪除、更新、增加數(shù)據(jù)的時(shí)候,同時(shí)更新緩存。
對(duì)于條件查詢,條件修改,條件刪除(一般是執(zhí)行HQL)則起不到緩存的作用。條件修改,條件刪除時(shí)(一般是執(zhí)行HQL)會(huì)清空所有在緩存中的同類對(duì)象。
為此,Hibernate提供了針對(duì)條件查詢的Query Cache,其實(shí)它并不好用。

關(guān)于是否命中,是使用Statistics類監(jiān)測(cè)的(通過SessionFactory的getStatistics()方法得到)。

總結(jié)一下:如果你打算開啟hibernate的二級(jí)緩存,在修改與刪除時(shí),就要使用session.update(),session.delete()方法按ID一條一條的操作,這樣對(duì)二級(jí)緩存是最優(yōu)的。
    但循環(huán)中使用sesion.update(),session.delete()方法,會(huì)產(chǎn)生多條sql語句,原本使用一條HQL完成的工作,現(xiàn)在要執(zhí)行多條,你擔(dān)心Hibernate與數(shù)據(jù)庫服務(wù)器的網(wǎng)絡(luò)通信次數(shù)嗎?其實(shí)這多條sql是使用JDBC的批處理一次發(fā)送到數(shù)據(jù)庫服務(wù)器的,所以你不用擔(dān)心?,F(xiàn)在到了數(shù)據(jù)庫服務(wù)器端,我們以oracle為例,oracle要執(zhí)行多條sql,就要進(jìn)行多次的“分析sql語句的正確性,并解析成oracle的原子操作,并制定執(zhí)行計(jì)劃”,你擔(dān)心這“多次”分析會(huì)給oracle帶來性能的影響嗎?不用擔(dān)心,請(qǐng)使用oracle的綁定參數(shù),就是Hibernate中的?代替參數(shù)。


四、Hibernate二級(jí)緩存的并發(fā)策略你了解嗎:

1 只讀緩存 read only
不須要鎖與事務(wù),因?yàn)榫彺孀詳?shù)據(jù)從數(shù)據(jù)庫加載后就不會(huì)改變。

    如果數(shù)據(jù)是只讀的,例如引用數(shù)據(jù),那么總是使用“read-only”策略,因?yàn)樗亲詈?jiǎn)單、最高效的策略,也是集群安全的策略。是性能第一的策略 。

2 讀寫緩存 read write
對(duì)緩存的更新發(fā)生在數(shù)據(jù)庫事務(wù)完成后。緩存需要支持鎖。
在一個(gè)事務(wù)中更新數(shù)據(jù)庫,在這個(gè)事務(wù)成功完成后更新緩存,并釋放鎖。
鎖只是一種特定的緩存值失效表述方式,在它獲得新數(shù)據(jù)庫值前阻止其他事務(wù)讀寫緩存。那些事務(wù)會(huì)轉(zhuǎn)而直接讀取數(shù)據(jù)庫。
緩存必須支持鎖,事務(wù)支持則不是必須的。如果緩存是一個(gè)集群,“更新緩存”的調(diào)用會(huì)將新值推送給所有副本,這通常被稱為“推(push)”更新策略。

    如果你的數(shù)據(jù)是又讀又寫的,那么使用“read-write”策略。這通常是性能第三的策略,因?yàn)樗笥芯彺骀i,緩存集群中使用重量級(jí)的“推”更新策略。

3 非嚴(yán)格讀寫緩存 nonstrict read write
在一個(gè)事務(wù)中更新數(shù)據(jù)庫,在這個(gè)事務(wù)完成前就清除緩存,為了安全起見,無論事務(wù)成功與否,在事務(wù)完成后再次清除緩存。
既不需要支持緩存鎖,也不需要支持事務(wù)。如果是緩存集群,“清除緩存”調(diào)用會(huì)讓所有副本都失效,這通常被稱為“拉(pull)”更新策略。

    如果你的數(shù)據(jù)讀很多或者很少有并發(fā)緩存訪問和更新,那么可以使用“nonstrict-read-write”策略。感謝它的輕量級(jí)“拉”更新策略,它通常是性能第二好的策略。

4 事務(wù)緩存 transactional (一定要在JTA環(huán)境中)
對(duì)緩存和數(shù)據(jù)庫的更新被包裝在同一個(gè)JTA事務(wù)中,這樣緩存與數(shù)據(jù)庫總是保持同步的。數(shù)據(jù)庫和緩存都必須支持JTA。

    除非你真的想將緩存更新和數(shù)據(jù)庫更新放在一個(gè)JTA事務(wù)里,否則不要使用“transactional”策略,因?yàn)镴TA需要漫長的兩階段提交處理,這導(dǎo)致它基本是性能最差的策略。


五、緩存鎖的性能也要了解,知道加了鎖后性能會(huì)下降:
    為了保證數(shù)據(jù)的安全性,不發(fā)生臟數(shù)據(jù),各個(gè)緩存通常使用鎖來保證
在本地方式運(yùn)行時(shí),緩存最大的開銷就是使用鎖來在保證共享數(shù)據(jù)完整性。
在集群環(huán)境中,RPC調(diào)用,鎖,是性能上大開銷。

 

下面以JBoss Cache為例說一說鎖:
JBoss Cache1.* 和 2.* 時(shí)代,提供樂觀鎖,悲觀鎖,但是性能不高。
JBoss Cache3.0 MVCC鎖方案性能很高。

悲觀鎖:這些鎖的隔離級(jí)別和數(shù)據(jù)庫實(shí)施的隔離級(jí)別相同,這種方案簡(jiǎn)單而且健壯,允許多用戶同時(shí)讀取數(shù)據(jù)。讀操作阻塞寫操作,悲觀鎖的讀寫是互斥的,無法同時(shí)進(jìn)行的,寫的性能不好。

樂觀鎖:這個(gè)方式則牽涉到數(shù)據(jù)版本,可以獲得高度并發(fā)性。那些請(qǐng)求讀取數(shù)據(jù)的用戶不會(huì)因?yàn)椴l(fā)數(shù)據(jù)庫寫入操作而受到阻塞。而且,樂觀鎖定方式還可以避免悲觀鎖定中有可能發(fā)生的死鎖。但它仍然有兩個(gè)主要的缺點(diǎn):一是性能問題。因?yàn)椴粩嗟膶⒔Y(jié)點(diǎn)的狀態(tài)拷貝到每個(gè)并發(fā)線程所造成的內(nèi)存和 CPU 開銷是不容忽略的。二是盡管并發(fā)時(shí)允許了寫操作,但是一旦發(fā)現(xiàn)數(shù)據(jù)的版本不對(duì),事務(wù)提交時(shí)不可避免的還是會(huì)失敗。也就是說,此時(shí)寫事務(wù)雖然可以不受限制的進(jìn)行大量處理和寫操作,但是這樣在事務(wù)結(jié)束的時(shí)候容易出現(xiàn)提交失敗。

多版本并發(fā)控制(MVCC):在數(shù)據(jù)訪問速度上較之前者也勝出百倍。MVCC 提供了非阻塞 (non-blocking) 讀操作 ( 它并不會(huì)去阻塞 wirter threads) ,在避免死鎖的同時(shí)也提供了更高級(jí)的并發(fā)機(jī)制。更棒的是,我們的 MVCC 實(shí)現(xiàn)甚至可以對(duì) reader threads 完全不采用任何鎖 ( 對(duì)于像緩存這樣頻繁讀取的系統(tǒng)來說,意義太大了 ) ,

 

六、批量處理時(shí)請(qǐng)不要使用二級(jí)緩存
當(dāng)你執(zhí)行大量的 添加與修改時(shí),并且這個(gè)實(shí)體對(duì)象被配置為啟用二級(jí)緩存,你考慮過二級(jí)緩存會(huì)怎么樣嗎?請(qǐng)看下面代碼:

Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( int i=0; i<100000; i++ ) { Customer customer = new Customer(.....); //如果你的 hibernate.cache.use_second_level_cache 是 true, 請(qǐng)?jiān)跁?huì)話級(jí)別上關(guān)閉他 //向(任何一級(jí))緩存中加載大量數(shù)據(jù)通常也意味著它們很快會(huì)被清除出去,這會(huì)增加GC開銷。 session.setCacheMode(CacheMode.IGNORE); session.save(customer); if ( i % 50 == 0 ) { //將本批插入的對(duì)象立即寫入數(shù)據(jù)庫并釋放內(nèi)存 session.flush(); session.clear(); } } tx.commit(); session.close();

 

 

 

批處理通常不需要數(shù)據(jù)緩存,否則你會(huì)將內(nèi)存耗盡并大量增加GC開銷。如果內(nèi)存有限,那這種情況會(huì)很明顯。


七、了解幾種優(yōu)秀緩存方案:
1、Memcached
分布式緩存系統(tǒng),memcached 要求set的對(duì)象必須是可序列化對(duì)象,jboss cache等java obect cache是沒有這個(gè)說法的,這是本質(zhì)的不同的,但是他可以在網(wǎng)絡(luò)上用,所以必須序列化也可理解。
獨(dú)立服務(wù)器+java 客戶端。
Memcached java 客戶端有:
memcache-client-forjava,
XMemcached,
spymemcached,
memcache-client-forjava
參考文章:
XMemcached——一個(gè)新的開源Java memcached客戶端
緩存系統(tǒng)MemCached的Java客戶端優(yōu)化歷程

2、JBOSS CACHE
JBoss Cache是非常優(yōu)秀的,前面介紹鎖的時(shí)候已說過了。
參考文章:
深入理解JBoss Cache3.0——Naga

JBoss Cache分布式緩存:Manik Surtani訪談

3、EhCache
Ehcache 2.1起提供了針對(duì)Hibernate的JTA支持。
參考:
Ehcache 2.0:后寫式緩存和JTA支持

4、Infinispan
開源數(shù)據(jù)網(wǎng)格平臺(tái) ,是新東東。
參考:
開源數(shù)據(jù)網(wǎng)格平臺(tái)Infinispan訪談

 

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Hibernate緩存機(jī)制(十)
hibernate的工作原理以及為什么要使用hibernate
全面講解Hibernate二級(jí)緩存
Hibernate4之二級(jí)緩存
hibernate 臟數(shù)據(jù)與緩存 延遲加載
Hibernate?緩存問題
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服