Coherence簡介
(雖然這篇文章不是完全翻譯自這篇,但大意也差不多了。希望能讓大家多了解一點Coherence。)
Coherence是基於一種mesh-based(網狀)P2P的高延展性技術,主要用於資料可用性與效能都十分重要的系統上。簡單來說,Coherence其實就是一種分散式的快取服務(distributed cache service),其主要目的便是快取資料。之所以稱為分散式快取,是因為Coherence能將一堆資料加以分散(distribute,或說分割 - partition),並放到任意數目的節點上,這些節點便成為一個叢集(cluster)中的成員。因此,每個節點都擁有整堆資料的其中一部份。Coherence能確保資料不會通通擺放在單獨某台節點上,所以這又可以達到負載分散的效果。資料本身是放在節點上的記憶體內(in-memory),但因為所有節點的記憶體可組成一塊很大的快取儲存空間,所以Coherence也是分散式的in-memory資料網格(data grid)。 既然是網格技術,所以任意節點加入或離開這個網格(或說叢集)都是很簡單的,不會造成整個叢集運作與管理的龐大負擔。而資料本身是被保存在整個叢集裡,所以也可達成HA(high availability,高可用性)。因此網格規模可以大量延展、整體運作效能可以倍數提升、資料的穩定度(reliability)亦可被確保。
分散式快取需要考慮幾個重點:
- Partitioned(資料分割):在整個分散式快取中資料是被打散放到所有伺服器所構成的叢集中的任一節點上,但是不會有兩個節點(或以上)存放了同一份資料片段。也就是說任一資料片段,只會也只能從一個節點上取得。這代表快取的大小和處理效能及相關的快取管理工作,會隨著叢集的大小而線性成長;亦即多增一台節點,效能就會隨之比例成長。另外這也意味著快取資料的操作可以用「一次跳躍」(single-hop)就完成,也就是說最多只需要再另外一台節點幫忙就行了。(詳情請見底下第一張圖)
- Load-Balanced(負載平衡):因為資料是被平均分散到各伺服器節點上,因此管理資料的責任,就會自動平均分擔到整個叢集中。
- Location Transparency(位置透通):雖然資料是分佈到整個叢集中,但存取這些資料卻是用同樣的一套API,而且可用API中不同的方法來都得到相同的結果。這就叫做位置透通性,亦即開發人員不用依照快取的架構(topology,見下下段)來開發,只需要遵照API用法就可以了,而且這結果是可以相信的。
- Failover(錯誤移轉):所有的Coherence服務都提供錯誤移轉(failover)和錯誤復原(failback),確保資料不會漏失。Coherence的分散式快取服務能夠設定一個資料的備份數量,因此只要備份數目是大於等於1,任何節點掛掉Coherence就都能確保儲存於其上的資料不會就此漏失。
既然資料是分散擺放的,那你可能就會問說,如果要一小塊資料卻要繞一大段路(訪問過一大堆節點)才能找到這個資料是被放在哪個節點上,那豈不是太瞎了嗎?當然Coherence不會如此地瞎,不然神諭公司還買它做啥(Coherence前身叫做Tangosol Coherence,就是Tangosol這家公司的產品)。基本上,Coherence的分散式處理機制,屬於一種DHT(Distributed Hash Table,分散式雜湊表)。有沒有看到關鍵字hash?任何學過演算法的人都知道,hash table能夠快速地按照關鍵字(key)來尋找資料記錄。因此我們就能大致上想像出Coherence的分散式原理了。
除此之外,Coherence為了讓資料取得效能最佳化,絞盡腦汁設計了好幾種caching schemes,讓資料存在與擺放的時間、地點、方式能夠依據應用系統的不同需求而有所調整適應。這些scheme(或稱topology)詳情可見此,本處不談。不過Coherence預設的scheme是「Partitioned」scheme,也就是本篇接下來會談到的快取處理方式。
前面提過,存取使用分散式快取,經常會經由網路走到其他節點上去。一般來說,如果叢集中有n個節點,那大約會有 (n - 1) / n 的動作是會跨到網路上的。

前面亦提到,因為每個資料片段都只能由一個節點來控管,所以任何經過網路的存取都只是「一次跳躍」的行為。這種方式非常具有延展性,因為這樣就可以採用點對點的傳輸方式,很適合於一般交換式網路。同樣地,要在快取裡面做更新動作,也是可利用一次跳躍的點對點傳輸方式。不過這卻會產生兩種限制。其一是必須將更新過的資料傳播給整個快取叢集:

在上圖中,更新過的資料被傳遞給擁有此資料的主節點(primary)與其備份節點(backup)。這樣做是為了錯誤復原的目的,而且這裡的備份數目是只有一個。如果快取資料不是很重要,可從磁碟中再次取出來,那就可以不要有備份,也就是能允許某些快取資料可能因為伺服器掛掉而導致的資料漏失。但如果快取資料很重要,那就可以設多一點的備份數目,譬如兩個或以上。不過備份數目多寡會影響快取資料被更新時的效能,如新增、修改和刪除快取項目等。
修改快取資料動作的完成與否,取決於備份節點是否也有回應收到了更新,所以這可能會對效能有些影響。但這能保證一旦有節點掛掉,資料既不會漏失也不會不一致。Coherence的錯誤移轉作法是,找出掛掉節點上的資料其備份是放在哪一台,然後將此備份所屬節點提昇為該資料的主節點,接著再從剩下的節點中選出一個當作備份節點。如下圖所示:

如果備份有很多層,那第一層的備份節點就會變成主節點,第二層的就變成新的第一層備份,依此類推。
另外,Coherence可為每個節點設定成是否要負擔資料儲存任務,也就是啟動「本地儲存」(local storage)與否。有啟動本地儲存的節點,就能夠為整個分散式叢集提供一部分快取儲存空間。但不論節點有沒有啟動儲存功能,所有叢集中的節點,都能知道所有資料的存放位置,即下圖中的Logical層機制。這Logical就是一個資料分布圖,任何人透過它就可瞭解所有資料的primary和backup各是放在哪些節點上,這就叫做所謂的「共識」(consensus)。前述的位置透通性就是透過共識而達成的。

這個本地儲存的選項有幾項好處:
- 若將某節點的本地儲存選項關掉,則其Java heap的大小就完全不會被快取所吃掉的記憶體容量給影響到。因為若沒有本地儲存,則資料將不會被放到這個節點上,而是其他節點。這種情況特別常見於執行在較舊版本JVM上的應用程式伺服器,而且又佔用了很大塊的heap。 因為舊版JVM的垃圾回收機制可能不是很健全,導致這些應用程式伺服器的處理程序便會因為JVM在做垃圾回收時,受到效能拖累(因為若heap愈大反而垃圾回收就要做愈久)。
- Coherence可允許叢集中每個節點皆能執行於任何受支援的JVM版本之上。因此有啟動本地儲存的節點就可以用新版的JVM來跑,以支援更大容量的heap;或是可設定Coherence的off-heap儲存空間(heap之外,如檔案系統),並改用Java NIO來操作存取。
- 本地儲存選項可令某些節點的責任是只負責儲存快取資料,此即所謂的Coherence快取伺服器。快取伺服器通常是用於延展(scale up)Coherence的分散查詢能力,因為愈多節點負責做查詢運算處理,效能理應就更好。
有機會的話,會再放demo影片給大家看。不過你要是有時間就先來看看Google TechTalks 2007上對Coherence的介紹:
有任何問題歡迎留言。
PS.1 failover與failback的差異,請見此。
PS.2 Coherence Getting Started wiki




















