Ehcache詳細(xì)解讀

Ehcache是現(xiàn)在最流行的純Java開源緩存框架,配置簡單、結(jié)構(gòu)清晰光督、功能強(qiáng)大唉窃,最初知道它,是從Hibernate的緩存開始的枝冀。網(wǎng)上中文的EhCache材料以簡單介紹和配置方法居多,如果你有這方面的問題,請自行g(shù)oogle愕够;對于API,官網(wǎng)上介紹已經(jīng)非常清楚佛猛,請參見官網(wǎng)惑芭;但是很少見到特性說明和對實(shí)現(xiàn)原理的分析,因此在這篇文章里面继找,我會詳細(xì)介紹和分析EhCache的特性遂跟,加上一些自己的理解和思考,希望對緩存感興趣的朋友有所收獲婴渡。

一幻锁、特性一覽,來自官網(wǎng)边臼,簡單翻譯一下:

1哄尔、快速輕量

過去幾年,諸多測試表明Ehcache是最快的Java緩存之一柠并。

Ehcache的線程機(jī)制是為大型高并發(fā)系統(tǒng)設(shè)計(jì)的岭接。

大量性能測試用例保證Ehcache在不同版本間性能表現(xiàn)得一致性。

很多用戶都不知道他們正在用Ehcache臼予,因?yàn)椴恍枰裁刺貏e的配置鸣戴。

API易于使用,這就很容易部署上線和運(yùn)行粘拾。

很小的jar包窄锅,Ehcache 2.2.3才668kb。

最小的依賴:唯一的依賴就是SLF4J了缰雇。

2酬滤、伸縮性

緩存在內(nèi)存和磁盤存儲可以伸縮到數(shù)G签餐,Ehcache為大數(shù)據(jù)存儲做過優(yōu)化。

大內(nèi)存的情況下盯串,所有進(jìn)程可以支持?jǐn)?shù)百G的吞吐氯檐。

為高并發(fā)和大型多CPU服務(wù)器做優(yōu)化。

線程安全和性能總是一對矛盾体捏,Ehcache的線程機(jī)制設(shè)計(jì)采用了Doug Lea的想法來獲得較高的性能冠摄。

單臺虛擬機(jī)上支持多緩存管理器。

通過Terracotta服務(wù)器矩陣几缭,可以伸縮到數(shù)百個(gè)節(jié)點(diǎn)河泳。

3、靈活性

Ehcache 1.2具備對象API接口和可序列化API接口年栓。

不能序列化的對象可以使用除磁盤存儲外Ehcache的所有功能拆挥。

除了元素的返回方法以外,API都是統(tǒng)一的某抓。只有這兩個(gè)方法不一致:getObjectValue和getKeyValue纸兔。這就使得緩存對象、序列化對象來獲取新的特性這個(gè)過程很簡單否副。

支持基于Cache和基于Element的過期策略汉矿,每個(gè)Cache的存活時(shí)間都是可以設(shè)置和控制的。

提供了LRU备禀、LFU和FIFO緩存淘汰算法洲拇,Ehcache 1.2引入了最少使用和先進(jìn)先出緩存淘汰算法,構(gòu)成了完整的緩存淘汰算法曲尸。

提供內(nèi)存和磁盤存儲赋续,Ehcache和大多數(shù)緩存解決方案一樣,提供高性能的內(nèi)存和磁盤存儲另患。

動態(tài)蚕捉、運(yùn)行時(shí)緩存配置,存活時(shí)間柴淘、空閑時(shí)間、內(nèi)存和磁盤存放緩存的最大數(shù)目都是可以在運(yùn)行時(shí)修改的秘通。

4为严、標(biāo)準(zhǔn)支持

Ehcache提供了對JSR107 JCACHE API最完整的實(shí)現(xiàn)。因?yàn)镴CACHE在發(fā)布以前肺稀,Ehcache的實(shí)現(xiàn)(如net.sf.jsr107cache)已經(jīng)發(fā)布了第股。

實(shí)現(xiàn)JCACHE API有利于到未來其他緩存解決方案的可移植性。

Ehcache的維護(hù)者Greg Luck话原,正是JSR107的專家委員會委員夕吻。

5诲锹、可擴(kuò)展性

監(jiān)聽器可以插件化。Ehcache 1.2提供了CacheManagerEventListener和CacheEventListener接口涉馅,實(shí)現(xiàn)可以插件化归园,并且可以在ehcache.xml里配置。

節(jié)點(diǎn)發(fā)現(xiàn)稚矿,冗余器和監(jiān)聽器都可以插件化庸诱。

分布式緩存,從Ehcache 1.2開始引入晤揣,包含了一些權(quán)衡的選項(xiàng)桥爽。Ehcache的團(tuán)隊(duì)相信沒有什么是萬能的配置。

實(shí)現(xiàn)者可以使用內(nèi)建的機(jī)制或者完全自己實(shí)現(xiàn)昧识,因?yàn)橛型暾牟寮_發(fā)指南钠四。

緩存的可擴(kuò)展性可以插件化。創(chuàng)建你自己的緩存擴(kuò)展跪楞,它可以持有一個(gè)緩存的引用缀去,并且綁定在緩存的生命周期內(nèi)。

緩存加載器可以插件化习霹。創(chuàng)建你自己的緩存加載器朵耕,可以使用一些異步方法來加載數(shù)據(jù)到緩存里面。

緩存異常處理器可以插件化淋叶。創(chuàng)建一個(gè)異常處理器阎曹,在異常發(fā)生的時(shí)候,可以執(zhí)行某些特定操作煞檩。

6处嫌、應(yīng)用持久化

在VM重啟后,持久化到磁盤的存儲可以復(fù)原數(shù)據(jù)斟湃。

Ehcache是第一個(gè)引入緩存數(shù)據(jù)持久化存儲的開源Java緩存框架熏迹。緩存的數(shù)據(jù)可以在機(jī)器重啟后從磁盤上重新獲得。

根據(jù)需要將緩存刷到磁盤凝赛。將緩存條目刷到磁盤的操作可以通過cache.flush()方法來執(zhí)行注暗,這大大方便了Ehcache的使用。

7墓猎、監(jiān)聽器

緩存管理器監(jiān)聽器捆昏。允許注冊實(shí)現(xiàn)了CacheManagerEventListener接口的監(jiān)聽器:

notifyCacheAdded()

notifyCacheRemoved()

緩存事件監(jiān)聽器。允許注冊實(shí)現(xiàn)了CacheEventListener接口的監(jiān)聽器毙沾,它提供了許多對緩存事件發(fā)生后的處理機(jī)制:

notifyElementRemoved/Put/Updated/Expired

8骗卜、開啟JMX

Ehcache的JMX功能是默認(rèn)開啟的,你可以監(jiān)控和管理如下的MBean:

CacheManager、Cache寇仓、CacheConfiguration举户、CacheStatistics

9、分布式緩存

從Ehcache 1.2開始遍烦,支持高性能的分布式緩存俭嘁,兼具靈活性和擴(kuò)展性。

分布式緩存的選項(xiàng)包括:

通過Terracotta的緩存集群:設(shè)定和使用Terracotta模式的Ehcache緩存乳愉。緩存發(fā)現(xiàn)是自動完成的兄淫,并且有很多選項(xiàng)可以用來調(diào)試緩存行為和性能。

使用RMI蔓姚、JGroups或者JMS來冗余緩存數(shù)據(jù):節(jié)點(diǎn)可以通過多播或發(fā)現(xiàn)者手動配置捕虽。狀態(tài)更新可以通過RMI連接來異步或者同步完成。

Custom:一個(gè)綜合的插件機(jī)制坡脐,支持發(fā)現(xiàn)和復(fù)制的能力泄私。

可用的緩存復(fù)制選項(xiàng)。支持的通過RMI备闲、JGroups或JMS進(jìn)行的異步或同步的緩存復(fù)制晌端。

可靠的分發(fā):使用TCP的內(nèi)建分發(fā)機(jī)制。

節(jié)點(diǎn)發(fā)現(xiàn):節(jié)點(diǎn)可以手動配置或者使用多播自動發(fā)現(xiàn)恬砂,并且可以自動添加和移除節(jié)點(diǎn)咧纠。對于多播阻塞的情況下,手動配置可以很好地控制泻骤。

分布式緩存可以任意時(shí)間加入或者離開集群漆羔。緩存可以配置在初始化的時(shí)候執(zhí)行引導(dǎo)程序員。

BootstrapCacheLoaderFactory抽象工廠狱掂,實(shí)現(xiàn)了BootstrapCacheLoader接口(RMI實(shí)現(xiàn))演痒。

緩存服務(wù)端。Ehcache提供了一個(gè)Cache Server趋惨,一個(gè)war包鸟顺,為絕大多數(shù)web容器或者是獨(dú)立的服務(wù)器提供支持。

緩存服務(wù)端有兩組API:面向資源的RESTful器虾,還有就是SOAP讯嫂。客戶端沒有實(shí)現(xiàn)語言的限制兆沙。

RESTful緩存服務(wù)器:Ehcached的實(shí)現(xiàn)嚴(yán)格遵循RESTful面向資源的架構(gòu)風(fēng)格欧芽。

SOAP緩存服務(wù)端:Ehcache RESTFul Web Services API暴露了單例的CacheManager,他能在ehcache.xml或者IoC容器里面配置挤悉。

標(biāo)準(zhǔn)服務(wù)端包含了內(nèi)嵌的Glassfish web容器。它被打成了war包,可以任意部署到支持Servlet 2.5的web容器內(nèi)装悲。Glassfish V2/3昏鹃、Tomcat 6和Jetty 6都已經(jīng)經(jīng)過了測試。

10诀诊、搜索

標(biāo)準(zhǔn)分布式搜索使用了流式查詢接口的方式洞渤,請參閱文檔。

11属瓣、Java EE和應(yīng)用緩存

為普通緩存場景和模式提供高質(zhì)量的實(shí)現(xiàn)载迄。

阻塞緩存:它的機(jī)制避免了復(fù)制進(jìn)程并發(fā)操作的問題。

SelfPopulatingCache在緩存一些開銷昂貴操作時(shí)顯得特別有用抡蛙,它是一種針對讀優(yōu)化的緩存护昧。它不需要調(diào)用者知道緩存元素怎樣被返回,也支持在不阻塞讀的情況下刷新緩存條目粗截。

CachingFilter:一個(gè)抽象惋耙、可擴(kuò)展的cache filter。

SimplePageCachingFilter:用于緩存基于request URI和Query String的頁面熊昌。它可以根據(jù)HTTP request header的值來選擇采用或者不采用gzip壓縮方式將頁面發(fā)到瀏覽器端绽榛。你可以用它來緩存整個(gè)Servlet頁面,無論你采用的是JSP婿屹、velocity灭美,或者其他的頁面渲染技術(shù)。

SimplePageFragmentCachingFilter:緩存頁面片段昂利,基于request URI和Query String届腐。在JSP中使用jsp:include標(biāo)簽包含。

已經(jīng)使用Orion和Tomcat測試過页眯,兼容Servlet 2.3梯捕、Servlet 2.4規(guī)范。

Cacheable命令:這是一種老的命令行模式窝撵,支持異步行為傀顾、容錯(cuò)。

兼容Hibernate碌奉,兼容Google App Engine短曾。

基于JTA的事務(wù)支持,支持事務(wù)資源管理赐劣,二階段提交和回滾嫉拐,以及本地事務(wù)。

12魁兼、開源協(xié)議

Apache 2.0 license

二婉徘、Ehcache的加載模塊列表,他們都是獨(dú)立的庫,每個(gè)都為Ehcache添加新的功能盖呼,可以在此下載

ehcache-core:API儒鹿,標(biāo)準(zhǔn)緩存引擎,RMI復(fù)制和Hibernate支持

ehcache:分布式Ehcache几晤,包括Ehcache的核心和Terracotta的庫

ehcache-monitor:企業(yè)級監(jiān)控和管理

ehcache-web:為Java Servlet Container提供緩存约炎、gzip壓縮支持的filters

ehcache-jcache:JSR107 JCACHE的實(shí)現(xiàn)

ehcache-jgroupsreplication:使用JGroup的復(fù)制

ehcache-jmsreplication:使用JMS的復(fù)制

ehcache-openjpa:OpenJPA插件

ehcache-server:war內(nèi)部署或者單獨(dú)部署的RESTful cache server

ehcache-unlockedreadsview:允許Terracotta cache的無鎖讀

ehcache-debugger:記錄RMI分布式調(diào)用事件

Ehcache for Ruby:Jruby and Rails支持

Ehcache的結(jié)構(gòu)設(shè)計(jì)概覽:

三、核心定義

cache manager:緩存管理器蟹瘾,以前是只允許單例的圾浅,不過現(xiàn)在也可以多實(shí)例了

cache:緩存管理器內(nèi)可以放置若干cache,存放數(shù)據(jù)的實(shí)質(zhì)憾朴,所有cache都實(shí)現(xiàn)了Ehcache接口

element:單條緩存數(shù)據(jù)的組成單位

system of record(SOR):可以取到真實(shí)數(shù)據(jù)的組件狸捕,可以是真正的業(yè)務(wù)邏輯、外部接口調(diào)用伊脓、存放真實(shí)數(shù)據(jù)的數(shù)據(jù)庫等等府寒,緩存就是從SOR中讀取或者寫入到SOR中去的。

代碼示例:

Java代碼

CacheManager?manager?=?CacheManager.newInstance("src/config/ehcache.xml");

manager.addCache("testCache");

Cache?test?=?singletonManager.getCache("testCache");

test.put(newElement("key1","value1"));

manager.shutdown();

當(dāng)然报腔,也支持這種類似DSL的配置方式株搔,配置都是可以在運(yùn)行時(shí)動態(tài)修改的:

Java代碼

Cache?testCache?=newCache(

newCacheConfiguration("testCache",?maxElements)

.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LFU)

.overflowToDisk(true)

.eternal(false)

.timeToLiveSeconds(60)

.timeToIdleSeconds(30)

.diskPersistent(false)

.diskExpiryThreadIntervalSeconds(0));

事務(wù)的例子:

Java代碼

Ehcache?cache?=?cacheManager.getEhcache("xaCache");

transactionManager.begin();

try{

Element?e?=?cache.get(key);

Object?result?=?complexService.doStuff(element.getValue());

cache.put(newElement(key,?result));

complexService.doMoreStuff(result);

transactionManager.commit();

}catch(Exception?e)?{

transactionManager.rollback();

}

四、一致性模型

說到一致性纯蛾,數(shù)據(jù)庫的一致性是怎樣的纤房?不妨先來回顧一下數(shù)據(jù)庫的幾個(gè)隔離級別:

未提交讀(Read Uncommitted):在讀數(shù)據(jù)時(shí)不會檢查或使用任何鎖。因此翻诉,在這種隔離級別中可能讀取到?jīng)]有提交的數(shù)據(jù)炮姨。會出現(xiàn)臟讀、不可重復(fù)讀碰煌、幻象讀舒岸。

已提交讀(Read Committed):只讀取提交的數(shù)據(jù)并等待其他事務(wù)釋放排他鎖。讀數(shù)據(jù)的共享鎖在讀操作完成后立即釋放芦圾。已提交讀是數(shù)據(jù)庫的默認(rèn)隔離級別蛾派。會出現(xiàn)不可重復(fù)讀、幻象讀个少。

可重復(fù)讀(Repeatable Read):像已提交讀級別那樣讀數(shù)據(jù)洪乍,但會保持共享鎖直到事務(wù)結(jié)束。會出現(xiàn)幻象讀夜焦。

可序列化(Serializable):工作方式類似于可重復(fù)讀壳澳。但它不僅會鎖定受影響的數(shù)據(jù),還會鎖定這個(gè)范圍茫经,這就阻止了新數(shù)據(jù)插入查詢所涉及的范圍巷波。

基于以上萎津,再來對比思考下面的一致性模型:

1、強(qiáng)一致性模型:系統(tǒng)中的某個(gè)數(shù)據(jù)被成功更新(事務(wù)成功返回)后抹镊,后續(xù)任何對該數(shù)據(jù)的讀取操作都得到更新后的值姜性。這是傳統(tǒng)關(guān)系數(shù)據(jù)庫提供的一致性模型,也是關(guān)系數(shù)據(jù)庫深受人們喜愛的原因之一髓考。強(qiáng)一致性模型下的性能消耗通常是最大的。

2弃酌、弱一致性模型:系統(tǒng)中的某個(gè)數(shù)據(jù)被更新后氨菇,后續(xù)對該數(shù)據(jù)的讀取操作得到的不一定是更新后的值,這種情況下通常有個(gè)“不一致性時(shí)間窗口”存在:即數(shù)據(jù)更新完成后在經(jīng)過這個(gè)時(shí)間窗口妓湘,后續(xù)讀取操作就能夠得到更新后的值查蓉。

3、最終一致性模型:屬于弱一致性的一種榜贴,即某個(gè)數(shù)據(jù)被更新后豌研,如果該數(shù)據(jù)后續(xù)沒有被再次更新,那么最終所有的讀取操作都會返回更新后的值唬党。

最終一致性模型包含如下幾個(gè)必要屬性鹃共,都比較好理解:

讀寫一致:某線程A,更新某條數(shù)據(jù)以后驶拱,后續(xù)的訪問全部都能取得更新后的數(shù)據(jù)霜浴。

會話內(nèi)一致:它本質(zhì)上和上面那一條是一致的,某用戶更改了數(shù)據(jù)蓝纲,只要會話還存在阴孟,后續(xù)他取得的所有數(shù)據(jù)都必須是更改后的數(shù)據(jù)。

單調(diào)讀一致:如果一個(gè)進(jìn)程可以看到當(dāng)前的值税迷,那么后續(xù)的訪問不能返回之前的值永丝。

單調(diào)寫一致:對同一進(jìn)程內(nèi)的寫行為必須是保序的,否則箭养,寫完畢的結(jié)果就是不可預(yù)期的了慕嚷。

4、Bulk Load:這種模型是基于批量加載數(shù)據(jù)到緩存里面的場景而優(yōu)化的露懒,沒有引入鎖和常規(guī)的淘汰算法這些降低性能的東西闯冷,它和最終一致性模型很像,但是有批量懈词、高速寫和弱一致性保證的機(jī)制蛇耀。

這樣幾個(gè)API也會影響到一致性的結(jié)果:

1、顯式鎖(Explicit Locking):如果我們本身就配置為強(qiáng)一致性坎弯,那么自然所有的緩存操作都具備事務(wù)性質(zhì)纺涤。而如果我們配置成最終一致性時(shí)译暂,再在外部使用顯式鎖API,也可以達(dá)到事務(wù)的效果撩炊。當(dāng)然這樣的鎖可以控制得更細(xì)粒度外永,但是依然可能存在競爭和線程阻塞。

2拧咳、無鎖可讀取視圖(UnlockedReadsView):一個(gè)允許臟讀的decorator伯顶,它只能用在強(qiáng)一致性的配置下,它通過申請一個(gè)特殊的寫鎖來比完全的強(qiáng)一致性配置提升性能骆膝。

舉例如下祭衩,xml配置為強(qiáng)一致性模型:

Xml代碼

maxElementsInMemory="500"

eternal="false"

overflowToDisk="false"

但是使用UnlockedReadsView:

Java代碼

Cache?cache?=?cacheManager.getEhcache("myCache");

UnlockedReadsView?unlockedReadsView?=newUnlockedReadsView(cache,"myUnlockedCache");

3、原子方法(Atomic methods):方法執(zhí)行是原子化的阅签,即CAS操作(Compare and Swap)掐暮。CAS最終也實(shí)現(xiàn)了強(qiáng)一致性的效果,但不同的是政钟,它是采用樂觀鎖而不是悲觀鎖來實(shí)現(xiàn)的路克。在樂觀鎖機(jī)制下,更新的操作可能不成功养交,因?yàn)樵谶@過程中可能會有其他線程對同一條數(shù)據(jù)進(jìn)行變更精算,那么在失敗后需要重新執(zhí)行更新操作。現(xiàn)代的CPU都支持CAS原語了碎连。

Java代碼

cache.putIfAbsent(Element?element);

cache.replace(Element?oldOne,?Element?newOne);

cache.remove(Element);

五殖妇、緩存拓?fù)漕愋?/b>:

1、獨(dú)立緩存(Standalone Ehcache):這樣的緩存應(yīng)用節(jié)點(diǎn)都是獨(dú)立的破花,互相不通信谦趣。

2、分布式緩存(Distributed Ehcache):數(shù)據(jù)存儲在Terracotta的服務(wù)器陣列(Terracotta Server Array座每,TSA)中前鹅,但是最近使用的數(shù)據(jù),可以存儲在各個(gè)應(yīng)用節(jié)點(diǎn)中峭梳。

邏輯視角:

L1緩存就在各個(gè)應(yīng)用節(jié)點(diǎn)上舰绘,而L2緩存則放在Cache Server陣列中。

組網(wǎng)視角:

模型存儲視角:

L1級緩存是沒有持久化存儲的葱椭。另外捂寿,從緩存數(shù)據(jù)量上看,server端遠(yuǎn)大于應(yīng)用節(jié)點(diǎn)孵运。

3秦陋、復(fù)制式緩存(Replicated Ehcache):緩存數(shù)據(jù)時(shí)同時(shí)存放在多個(gè)應(yīng)用節(jié)點(diǎn)的,數(shù)據(jù)復(fù)制和失效的事件以同步或者異步的形式在各個(gè)集群節(jié)點(diǎn)間傳播治笨。上述事件到來時(shí)驳概,會阻塞寫線程的操作赤嚼。在這種模式下,只有弱一致性模型顺又。

它有如下幾種事件傳播機(jī)制:RMI更卒、JGroups、JMS和Cache Server稚照。

RMI模式下蹂空,所有節(jié)點(diǎn)全部對等:

JGroup模式:可以配置單播或者多播,協(xié)議棧和配置都非常靈活果录。

Xml代碼

class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory"

properties="connect=UDP(mcast_addr=231.12.21.132;mcast_port=45566;):PING:

MERGE2:FD_SOCK:VERIFY_SUSPECT:pbcast.NAKACK:UNICAST:pbcast.STABLE:FRAG:pbcast.GMS"

propertySeparator="::"

/>

JMS模式:這種模式的核心就是一個(gè)消息隊(duì)列腌闯,每個(gè)應(yīng)用節(jié)點(diǎn)都訂閱預(yù)先定義好的主題,同時(shí)雕憔,節(jié)點(diǎn)有元素更新時(shí),也會發(fā)布更新元素到主題中去糖声。JMS規(guī)范實(shí)現(xiàn)者上斤彼,Open MQ和Active MQ這兩個(gè),Ehcache的兼容性都已經(jīng)測試過蘸泻。

Cache Server模式:這種模式下存在主從節(jié)點(diǎn)琉苇,通信可以通過RESTful的API或者SOAP。

無論上面哪個(gè)模式悦施,更新事件又可以分為updateViaCopy或updateViaInvalidate并扇,后者只是發(fā)送一個(gè)過期消息,效率要高得多抡诞。

復(fù)制式緩存容易出現(xiàn)數(shù)據(jù)不一致的問題穷蛹,如果這成為一個(gè)問題,可以考慮使用數(shù)據(jù)同步分發(fā)的機(jī)制昼汗。

即便不采用分布式緩存和復(fù)制式緩存肴熏,依然會出現(xiàn)一些不好的行為,比如:

緩存漂移(Cache Drift):每個(gè)應(yīng)用節(jié)點(diǎn)只管理自己的緩存顷窒,在更新某個(gè)節(jié)點(diǎn)的時(shí)候蛙吏,不會影響到其他的節(jié)點(diǎn),這樣數(shù)據(jù)之間可能就不同步了鞋吉。這在web會話數(shù)據(jù)緩存中情況尤甚鸦做。

數(shù)據(jù)庫瓶頸(Database Bottlenecks ):對于單實(shí)例的應(yīng)用來說,緩存可以保護(hù)數(shù)據(jù)庫的讀風(fēng)暴谓着;但是泼诱,在集群的環(huán)境下,每一個(gè)應(yīng)用節(jié)點(diǎn)都要定期保持?jǐn)?shù)據(jù)最新赊锚,節(jié)點(diǎn)越多坷檩,要維持這樣的情況對數(shù)據(jù)庫的開銷也越大却音。

六、存儲方式

1矢炼、堆內(nèi)存儲:速度快系瓢,但是容量有限。

2句灌、堆外(OffHeapStore)存儲:被稱為BigMemory夷陋,只在企業(yè)版本的Ehcache中提供,原理是利用nio的DirectByteBuffers實(shí)現(xiàn)胰锌,比存儲到磁盤上快骗绕,而且完全不受GC的影響,可以保證響應(yīng)時(shí)間的穩(wěn)定性资昧;但是direct buffer的在分配上的開銷要比heap buffer大酬土,而且要求必須以字節(jié)數(shù)組方式存儲,因此對象必須在存儲過程中進(jìn)行序列化格带,讀取則進(jìn)行反序列化操作撤缴,它的速度大約比堆內(nèi)存儲慢一個(gè)數(shù)量級。

(注:direct buffer不受GC影響叽唱,但是direct buffer歸屬的的JAVA對象是在堆上且能夠被GC回收的屈呕,一旦它被回收,JVM將釋放direct buffer的堆外空間棺亭。)

3虎眨、磁盤存儲。

七镶摘、緩存使用模式

cache-aside:直接操作嗽桩。先詢問cache某條緩存數(shù)據(jù)是否存在,存在的話直接從cache中返回?cái)?shù)據(jù)凄敢,繞過SOR涤躲;如果不存在,從SOR中取得數(shù)據(jù)贡未,然后再放入cache中种樱。

Java代碼

publicV?readSomeData(K?key)

{

Element?element;

if((element?=?cache.get(key))?!=null)?{

returnelement.getValue();

}

if(value?=?readDataFromDataStore(key))?!=null)?{

cache.put(newElement(key,?value));

}

returnvalue;

}

cache-as-sor:結(jié)合了read-through、write-through或write-behind操作俊卤,通過給SOR增加了一層代理嫩挤,對外部應(yīng)用訪問來說,它不用區(qū)別數(shù)據(jù)是從緩存中還是從SOR中取得的消恍。

read-through岂昭。

write-through。

write-behind(write-back):既將寫的過程變?yōu)楫惒降暮菰梗诌M(jìn)一步延遲寫入數(shù)據(jù)的過程约啊。

Copy Cache的兩個(gè)模式:CopyOnRead和CopyOnWrite邑遏。

CopyOnRead指的是在讀緩存數(shù)據(jù)的請求到達(dá)時(shí),如果發(fā)現(xiàn)數(shù)據(jù)已經(jīng)過期恰矩,需要重新從源處獲取记盒,發(fā)起的copy element的操作(pull);

CopyOnWrite則是發(fā)生在真實(shí)數(shù)據(jù)寫入緩存時(shí)外傅,發(fā)起的更新其他節(jié)點(diǎn)的copy element的操作(push)纪吮。

前者適合在不允許多個(gè)線程訪問同一個(gè)element的時(shí)候使用,后者則允許你自由控制緩存更新通知的時(shí)機(jī)萎胰。

更多push和pull的變化和不同碾盟,也可參見這里

八技竟、多種配置方式

包括配置文件冰肴、聲明式配置、編程式配置榔组,甚至通過指定構(gòu)造器的參數(shù)來完成配置熙尉,配置設(shè)計(jì)的原則包括:

所有配置要放到一起

緩存的配置可以很容易在開發(fā)階段、運(yùn)行時(shí)修改

錯(cuò)誤的配置能夠在程序啟動時(shí)發(fā)現(xiàn)瓷患,在運(yùn)行時(shí)修改出錯(cuò)則需要拋出運(yùn)行時(shí)異常

提供默認(rèn)配置,幾乎所有的配置都是可選的遣妥,都有默認(rèn)值

九擅编、自動資源控制(Automatic Resource Control,ARC):

它是提供了一種智能途徑來控制緩存箫踩,調(diào)優(yōu)性能爱态。特性包括:

內(nèi)存內(nèi)緩存對象大小的控制,避免OOM出現(xiàn)

池化(cache manager級別)的緩存大小獲取境钟,避免單獨(dú)計(jì)算緩存大小的消耗

靈活的獨(dú)立基于層的大小計(jì)算能力锦担,下圖中可以看到,不同層的大小都是可以單獨(dú)控制的

可以統(tǒng)計(jì)字節(jié)大小慨削、緩存條目數(shù)和百分比

優(yōu)化高命中數(shù)據(jù)的獲取洞渔,以提升性能,參見下面對緩存數(shù)據(jù)在不同層之間的流轉(zhuǎn)的介紹

緩存數(shù)據(jù)的流轉(zhuǎn)包括了這樣幾種行為:

Flush:緩存條目向低層次移動缚态。

Fault:從低層拷貝一個(gè)對象到高層磁椒。在獲取緩存的過程中,某一層發(fā)現(xiàn)自己的該緩存條目已經(jīng)失效玫芦,就觸發(fā)了Fault行為浆熔。

Eviction:把緩存條目除去。

Expiration:失效狀態(tài)桥帆。

Pinning:強(qiáng)制緩存條目保持在某一層医增。

下面的圖反映了數(shù)據(jù)在各個(gè)層之間的流轉(zhuǎn)慎皱,也反映了數(shù)據(jù)的生命周期:

十、監(jiān)控功能

監(jiān)控的拓?fù)洌?/p>

每個(gè)應(yīng)用節(jié)點(diǎn)部署一個(gè)監(jiān)控探針叶骨,通過TCP協(xié)議與監(jiān)控服務(wù)器聯(lián)系茫多,最終將數(shù)據(jù)提供給富文本客戶端或者監(jiān)控操作服務(wù)器。

十一邓萨、廣域網(wǎng)復(fù)制

緩存數(shù)據(jù)復(fù)制方面地梨,Ehcache允許兩個(gè)地理位置各異的節(jié)點(diǎn)在廣域網(wǎng)下維持?jǐn)?shù)據(jù)一致性,同時(shí)它提供了這樣幾種方案(注:下面的示例都只繪制了兩個(gè)節(jié)點(diǎn)的情形缔恳,實(shí)際可以推廣到N個(gè)節(jié)點(diǎn)):

第一種方案:Terracotta Active/Mirror Replication宝剖。

這種方案下,服務(wù)端包含一個(gè)活躍節(jié)點(diǎn)歉甚,一個(gè)備份節(jié)點(diǎn)万细;各個(gè)應(yīng)用節(jié)點(diǎn)全部靠該活躍節(jié)點(diǎn)提供讀寫服務(wù)。這種方式最簡單纸泄,管理容易赖钞;但是,需要寄希望于理想的網(wǎng)絡(luò)狀況聘裁,服務(wù)器之間和客戶端到服務(wù)器之間都存在走WAN的情況雪营,這樣的方案其實(shí)最不穩(wěn)定。

第二種方案:Transactional Cache Manager Replication衡便。

這種方案下献起,數(shù)據(jù)讀取不需要經(jīng)過WAN,寫入數(shù)據(jù)時(shí)寫入兩份镣陕,分別由兩個(gè)cache manager處理谴餐,一份在本地Server,一份到其他Server去呆抑。這種方案下讀的吞吐量較高而且延遲較低岂嗓;但是需要引入一個(gè)XA事務(wù)管理器,兩個(gè)cache manager寫兩份數(shù)據(jù)導(dǎo)致寫開銷較大鹊碍,而且過WAN的寫延遲依然可能導(dǎo)致系統(tǒng)響應(yīng)的瓶頸厌殉。

第三種方案:Messaging based (AMQ) replication。

這種方案下侈咕,引入了批量處理和隊(duì)列双絮,用以減緩WAN的瓶頸出現(xiàn)套才,同時(shí)蚓炬,把處理讀請求和復(fù)制邏輯從Server Array物理上就剝離開亡容,避免了WAN情況惡化對節(jié)點(diǎn)讀取業(yè)務(wù)的影響。這種方案要較高的吞吐量和較低的延遲,讀/復(fù)制的分離保證了可以提供完備的消息分發(fā)保證摩桶、沖突處理等特性桥状;但是它較為復(fù)雜,而且還需要一個(gè)消息總線硝清。

有一些Ehcache特性應(yīng)用較少或者比較邊緣化辅斟,沒有提到,例如對于JMX的支持芦拿;還有一些則是有類似的特性和介紹了士飒,例如對于WEB的支持,請參見我這篇關(guān)于OSCache的解讀蔗崎,其中的“web支持”一節(jié)有詳細(xì)的原理分析酵幕。

最后,關(guān)于Ehcache的性能比對缓苛,下面這張圖來自Ehcache的創(chuàng)始人Greg Luck的blog

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芳撒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子未桥,更是在濱河造成了極大的恐慌笔刹,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件冬耿,死亡現(xiàn)場離奇詭異舌菜,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)亦镶,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進(jìn)店門日月,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人染乌,你說我怎么就攤上這事山孔《叮” “怎么了荷憋?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長褐望。 經(jīng)常有香客問我勒庄,道長,這世上最難降的妖魔是什么瘫里? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任实蔽,我火速辦了婚禮,結(jié)果婚禮上谨读,老公的妹妹穿的比我還像新娘局装。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布铐尚。 她就那樣靜靜地躺著拨脉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宣增。 梳的紋絲不亂的頭發(fā)上玫膀,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機(jī)與錄音爹脾,去河邊找鬼帖旨。 笑死,一個(gè)胖子當(dāng)著我的面吹牛灵妨,可吹牛的內(nèi)容都是我干的解阅。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼闷串,長吁一口氣:“原來是場噩夢啊……” “哼瓮钥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起烹吵,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤碉熄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后肋拔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锈津,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年凉蜂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了琼梆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡窿吩,死狀恐怖茎杂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情纫雁,我是刑警寧澤煌往,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站轧邪,受9級特大地震影響刽脖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜忌愚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一曲管、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧硕糊,春花似錦院水、人聲如沸腊徙。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽昧穿。三九已至,卻和暖如春橙喘,著一層夾襖步出監(jiān)牢的瞬間时鸵,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工厅瞎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留饰潜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓和簸,卻偏偏與公主長得像彭雾,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子锁保,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容