針對JBoss Cache的訪談
Manik,您能否首先跟大家講一下在您所接觸或者了解的客戶中,大部分人都是怎樣運用JBoss Cache的?緩存能帶來哪些優(yōu)點?尤其是在高度的可用性方面,緩存帶來了怎樣的進步?
從持續(xù)存儲、尤其是數據庫中讀取數據需要付出昂貴的代價。而且,數據庫在伸縮性方面也是臭名昭著(或者不便宜),當你想要擴展前端或增加更多客戶端時,這個弊端顯然就成了障礙。另一方面,CPU和內存的價格越來越便宜,這意味著更多的人可以負擔得起架設高可用系統(tǒng)所需的成本?!氨菊菊诰S護中”的暫停服務方式都應當成為歷史。
像JBoss Cache這樣的分布式緩存扮演的是一個處于應用服務前端和數據庫間的中間層的角色,提供對持久性數據狀態(tài)在內存中的快速訪問。JBoss Cache能夠確保緩存中的數據狀態(tài)和數據庫中的狀態(tài)一致、及時更新數據狀態(tài)、并且保證JVM不會出現堆溢出問題。
JBoss Cache和其它一些開源項目,例如Hibernate和JBoss Seam等的集成情況怎樣?
一些開源項目確實用到了JBoss Cache。Hibernate(以及JBoss Application Server的EJB3實現)使用JBoss Cache來存儲從數據庫后端讀取的實體數據,這樣一來在調用實體時就不需要每次都連接到數據庫去查找。我這樣說純粹只是一個簡單的概括,Hibernate運用分布式緩存的實際操作其實更復雜。
Seam也通過分布式緩存來緩存生成JSF頁面元素,從而改善那些頁面或者頁面元素生成速度比較緩慢的站點的伸縮性。
另外還有一些開源項目,如Lucene、Hibernate Search、GridGain、JBoss應用服務器的HTTP Session集群和集群的單點登錄(Single Sign-On)代碼等都用到了JBoss Cache。
JBoss Cache提供兩種緩存方式:核心緩存和POJO緩存。您是否能給我們概括一下這兩者主要區(qū)別在哪里?
核心緩存會直接把您傳遞給它的數據存儲在一個樹型結構中。鍵/值對被存儲在樹的節(jié)點上,出于復制或持續(xù)性的需要它們都被序列化了。
POJO 緩存則采用比較復雜的機制——利用字節(jié)碼編織來內省(introspecting)用戶類,并向用戶類的域添加偵聽器,一旦域值有任何變化,偵聽器會立刻通知緩存。例如,如果要在POJO緩存中存儲一個龐大、復雜的對象,會導致POJO緩存內省對象的字節(jié)碼,最終只把該對象的原始域存儲到樹結構中。一旦域值有所變化,緩存只復制這個改變了的域值而不會去復制整個用戶類,這是高效的細粒度復制。
當然還有一些其它的不同之處,但最主要的區(qū)別還是我剛才講的。
細粒度復制定然會導致POJO緩存和核心緩存間在性能方面巨大的差異。您有沒有對兩者之間差異做過評估呢?
這類評估很大程度上決定于系統(tǒng)配置,如果只是做一般評估沒多大意義。在緩存面對龐大、復雜的對象的時候,細粒度復制確實有助于提高性能。但如果只是用它來存儲一些String的話,細粒度復制就沒有什么特別價值。類似地,對簡單的用戶對象運用POJO緩存——比方說一個只擁有兩個String域的Person類,與其說對性能有什么幫助,倒不如說它是浪費開銷。
這就是為什么我一直建議大家依賴于用例編寫基準測試來做比較。我們開發(fā)了一個框架在不同緩存和不同配置情況下進行基準測試——開發(fā)這個框架主要還是為了方便我們內部比較不同版本的JBoss Cache之間的差異——但我們也提供該框架的下載,大家可以對它進行擴展,使用自定義的對象類型和訪問模式來重新編寫自定義測試。
你們如何管理引用完整性(referential integrity),尤其是POJO緩存?
如果你指的是對象的引用,那你剛好點到了之所以引進字節(jié)碼編織的原因。我們針對POJO添加了攔截器并在緩存內容中插入了引用域。
對于用戶來說,為什么要選擇本地緩存,而不用HashMap呢?
很多人認為Map是考慮緩存的出發(fā)點(實際上,JSR-107 JCACHE專家組曾經在Map的基礎上擴展實現javax.cache.Cache)。盡管Map非常適合用來存儲簡單的鍵/值對,在緩存必需的其它特性上,它就難免有點黔驢技窮,比如內存管理(eviction)、鈍化(passivation)和持續(xù)性、細粒度鎖定模型(首先,HashMap根本不是線程安全的;而ConcurrentHashMap采用的鎖是粗粒度級的,它甚至不允許非阻塞用戶或多用戶從map中讀取數據)等。而對于“合格的”緩存來說,它還需要具備一些“企業(yè)”特性,包括JTA兼容、附加偵聽器等功能。
Map雖然是個好的起點,但如果需要實現或者管理我剛才提到的那些特性的話,選擇緩存還是要比Map來得更合適一些。
分布式緩存中采用哪種鎖定機制?和傳統(tǒng)數據庫中采用的是同一種機制嗎?
JBoss Cache采用傳統(tǒng)的悲觀鎖(pessimistic locking)的方式,樹結構中的每個節(jié)點對應一個鎖。這些鎖的隔離級別和數據庫實施的隔離級別相同,允許多用戶同時讀取數據。
我們也提供樂觀鎖定(optimistically lock)方式,這個方式則牽涉到數據版本、每個事務的副本維護、主要樹結構提交的事務副本確認等等。在樂觀鎖定方式下,需要承載大量的數據讀取請求的系統(tǒng)因此可以獲得高度并發(fā)性。那些請求讀取數據的用戶不會因為并發(fā)數據庫寫入操作而受到阻塞。而且,樂觀鎖定方式還可以避免悲觀鎖定中有可能發(fā)生的死鎖。
我們攜帶多版本并發(fā)控制(Multi Versioned Concurrency Control--MVCC)功能的JBoss Cache 3.0.0正在發(fā)布階段,當前的開發(fā)任務非常重。大部分數據庫系統(tǒng)都用到了多版本并發(fā)控制這種鎖定方式,它為我們提供了最好的樂觀鎖定和悲觀鎖。由于我們的實現不會阻礙任何用戶讀取數據,因此在數據訪問速度上較之前者也勝出百倍。在MVCC功能相對穩(wěn)定之后,我們希望能把它設置為JBoss Cache默認的鎖定機制。
您能否談一下JGroups集成?
JBoss Cache用JGroups作為組通信類庫,用來偵測組成員和組建集群。我們也把JGroups作為一個信道,在其上我們實現了一個RPC機制與組中其它緩存進行通訊。由于JGoups的應用,JBoss Cache獲得了高度靈活性,并在網絡協(xié)議和調整方面也極具擴展性。JBoss Cache因此還使得緩存能夠擺脫LAN集群的框框,能夠穿透防火墻的限制并組建WAN集群等。
可以脫離JBoss AS單獨使用緩存嗎?
當然可以!很多人都誤認為JBoss Cache一定得在JBoss App Server下才能使用,其實不然。JBoss Cache可以在獨立的Java程序中使用,也可以在GUI前端使用,還能在其它一些應用服務器中使用。我們只是把它捆綁在JBoss App Server中發(fā)布而已。
失敗轉移的關鍵是把數據復制到多個節(jié)點,在實際開發(fā)中有很多策略可供選擇來復制數據。JBoss Cache支持的是哪種復制模式呢?
目前,我們支持兩種方式——全局復制(total replication——TR)和buddy復制(buddy replication——BR)。全局復制將狀態(tài)復制給小組中的所有成員。這種方式能夠幫助成員間共享數據狀態(tài),保證在失敗轉移時可以轉移到小組中的任何一個成員,但它限制了系統(tǒng)的伸縮性。Buddy復制則挑選特定成員擔當備份數據的責任,數據狀態(tài)相應地只會復制到這些特定節(jié)點上。也就是說直接轉移到復制節(jié)點的失敗轉移效率非常高,但即使轉移到任何非復制節(jié)點,失敗轉移也同樣都順利進行,因為數據狀態(tài)會根據請求轉移到相應的節(jié)點。BR最好用于 session密切相關(session affinity)的情況下,因為數據狀態(tài)的代價可能很高,所以應該盡量僅僅在發(fā)生失敗轉移的時候調用它。
某些特定的構架中,點對點的節(jié)點復制方式會影響到系統(tǒng)的伸縮性。JBoss Cache中有類似的問題存在嗎?
沒有。P2P網絡和小組通訊在使用LAN和IP多播的時候效率非常高,伸縮性很強。大多數現代網絡設施都支持IP多播。但P2P數據復制中,由于每個節(jié)點都擁有整個系統(tǒng)的數據狀態(tài),系統(tǒng)伸縮性因此受到影響。我下面會對全局復制稍加評論?;谇懊嫣岬降脑颍覀兘ㄗh用戶使用與session密切相關的buddy復制。
我們還在開發(fā)分區(qū)功能,這個功能能夠幫助我們在保證伸縮性的前提下真正地把數據狀態(tài)發(fā)送到各個數據組,而且不需要與session密切相關(session affinity)。希望這個功能的推出能夠取代全局復制和buddy復制。
在緩存和集群方面,您對近期的發(fā)展狀況有怎樣的期望?JBoss Cache將會如何去滿足新的用戶需求?
隨著硬件越來越便宜、CPU廠商在每塊芯片上放置越來越多的內核,分布式緩存將會越來越重要。這無疑意味著需要更多的“虛擬”機,意味著數據庫需要“竭盡全力”去管理高度的并發(fā)性,也意味著分布式緩存將會成為數據瓶頸(data bottleneck)最重要的解決方式之一。逐漸流行的數據網格和云計算也同樣會推動分布式緩存的發(fā)展,無論是“云”還是網格的數據節(jié)點都需要訪問和共享數據。
分區(qū)和MVCC功能也將助JBoss Cache一臂之力,能夠把集群伸縮性提高一個數量級。
【編輯推薦】