Infinispan分布式緩存分析

1. Infinispan是什么?

下述截自官方描述:
Infinispan是基于Apache 2.0協(xié)議的分布式鍵值存儲系統(tǒng),可以以普通java lib或者獨立服務(wù)的方式提供服務(wù),支持各種協(xié)議(Hot Rod, REST, Memcached and WebSockets)。
支持的高級特性包括:事務(wù)、事件通知、高級查詢、分布式處理、off-heap及故障遷移。

2. 部署模式

Infinispan按部署模式分為嵌入式(Embedded)模式、Client-Server(C\S)模式。

2.1 嵌入式模式

嵌入式模式下,Infinispan實例和應(yīng)用程序運行在相同的JVM中。如Infinispan運行在集群模式下,則每個應(yīng)用程序中內(nèi)嵌的Infinispan實例同時作為集群中的一個節(jié)點。

2.1.1 適用場景

應(yīng)用程序為Java程序、且自身可長期、穩(wěn)定運行。每個應(yīng)用程序做為一個集群節(jié)點,故應(yīng)用總數(shù)不宜過多。

此模式下,每當應(yīng)用啟動時都會涉及Infinispan實例啟動、集群拓撲結(jié)構(gòu)變更和state transfer

2.2 C\S模式

C\S模式下,Infinispan部署在多個獨立的節(jié)點上提供緩存服務(wù),應(yīng)用程序通過客戶端API訪問節(jié)點并獲存數(shù)據(jù)。目前,Infinispan支持的協(xié)議包括Memcached,HotRod,REST,WebSocket等。
對于集群模式的緩存實例,多個服務(wù)器節(jié)點組成一個數(shù)據(jù)網(wǎng)格,客戶端可采用Infinispan支持的任意協(xié)議訪問緩存服務(wù)。
Infinispan提供的HotRod Client除了做為基本的TCP連接客戶端外,還實現(xiàn)了拓撲感知(topology-aware)和hash分布感知(hash-distribution-aware)功能來提升客戶端的訪問性能和可靠性。

2.2.1 拓撲感知

在C\S模式下,客戶端連接到Infinispan服務(wù)器只需指定任意服務(wù)器的IP地址和端口號即可。連接成功后,服務(wù)器會將自身的拓撲信息發(fā)送給客戶端,并且當拓撲結(jié)構(gòu)發(fā)生變化時,新的拓撲信息也會同步到客戶端,這就是拓撲感知。這使得當客戶端連接的服務(wù)器發(fā)生異常時,客戶端仍舊可以正常訪問Infinispan服務(wù)。

2.2.2 Hash分布感知

Hash分布感知是指當需要操作某個數(shù)據(jù)時,客戶端知道數(shù)據(jù)分布在哪幾個節(jié)點上,并選擇最合適的一個節(jié)點發(fā)送TCP請求。hash分布感知將節(jié)點選擇落在客戶端完成,減少了服務(wù)器的計算負荷,減少了服務(wù)器間的通信數(shù)量,提升了程序性能。

2.2.3 適用場景

  1. 緩存部署在獨立節(jié)點上,其耗用CPU、內(nèi)存等對應(yīng)用程序自身運行不會帶來影響。
  2. 只要遵守Infinispan支持的協(xié)議,客戶端可運行在各種環(huán)境之下。另外,對于非Java應(yīng)用只能采用此種方式。
  3. 適用于Java應(yīng)用但自身并不需要長期、穩(wěn)定運行(如運行一次,或存在頻繁重啟場景)等場景。

3. 緩存模式

Infinispan支持四種緩存模式:本地(Local)模式、復(fù)制(Replicated)模式、失效(Invalidation)模式、分布式(Distribution)模式。除本地模式外,其他三種模式均為集群模式緩存。

3.1 本地模式

本地模式下,數(shù)據(jù)緩存在本地內(nèi)存,節(jié)點間數(shù)據(jù)不共享。Infinispan的cache對象繼承自Java的ConcurrentMap,和直接采用map相比,其優(yōu)勢在于:

  • 支持緩存數(shù)據(jù)持久化,支持mongodb、leveldb等多種數(shù)據(jù)庫。Infinispan通過設(shè)置cache store僅將將上述數(shù)據(jù)庫作為緩存數(shù)據(jù)的存儲介質(zhì),并不涉及數(shù)據(jù)庫本身的其他高級特性。
  • 支持eviction策略,避免內(nèi)存耗盡。
  • 支持expiration策略,保證長期未被使用的數(shù)據(jù)被清除。
  • 基于MVCC的并發(fā)處理策略,采用CAS和其他lock-free算法保證高性能。
    *事務(wù)性保證。

3.2 失效模式

失效模式下,數(shù)據(jù)需持久化到數(shù)據(jù)庫(或其他持久化設(shè)備)中,節(jié)點間并不共享任何數(shù)據(jù)。當發(fā)生數(shù)據(jù)更新時,更新數(shù)據(jù)庫并通知其他節(jié)點該數(shù)據(jù)已過期。節(jié)點發(fā)現(xiàn)數(shù)據(jù)過期后,采用lazy策略從數(shù)據(jù)庫更新至緩存。這樣做的好處在于:

  • 網(wǎng)絡(luò)負荷最小化。和復(fù)制模式下更新數(shù)據(jù)相比,失效消息要小的多,有效降低了網(wǎng)絡(luò)負荷。
  • 延遲更新。節(jié)點發(fā)現(xiàn)數(shù)據(jù)失效后,無需立即更新數(shù)據(jù),僅當需訪問該數(shù)據(jù)時才執(zhí)行更新。
  • 支持同步、異步兩種失效方式。
    同步失效:發(fā)送失效通知,并等待所有節(jié)點響應(yīng)(收到失效消息,并逐出過期數(shù)據(jù))后返回。
    異步失效:發(fā)送失效通知,廣播至所有節(jié)點,并直接返回。
  • 數(shù)據(jù)存在持久化需求,緩存作為持久數(shù)據(jù)的中間層。在讀操作頻繁的場景下,采用Infinispan,避免每次直接訪問數(shù)據(jù)庫,提高讀取性能。

3.3 復(fù)制模式

復(fù)制模式是集群模式的一種,在該模式任何一個節(jié)點的數(shù)據(jù)變更將復(fù)制到其他所有節(jié)點上,這使得集群中任何一個節(jié)點都包含了完整的緩存數(shù)據(jù)。
和嵌入式模式組合時,所有數(shù)據(jù)均保存在應(yīng)用程序本地,讀操作僅需訪問本地內(nèi)存,性能最高。
和C\S模式組合時,因為數(shù)據(jù)都保存在遠端,讀寫都需要進行一次遠端訪問,此時復(fù)制模式和分布式模式相比并無明顯優(yōu)勢。
Infinispan設(shè)計了同步、異步兩種方式用于將本節(jié)點的數(shù)據(jù)變更操作通知到其他節(jié)點,對于每種操作又支持TCP、UDP兩種通信方式。采用UDP協(xié)議時,通過疊加JGroups的NAKACK2和UNICAST3保證傳輸?shù)目煽啃?,具體可參見[JGroups支持]。

3.3.1 同步復(fù)制

執(zhí)行寫操作時,先在本地執(zhí)行預(yù)提交(更新到MVCCEntry中),如本地節(jié)點是Primary節(jié)點,則向其他所有節(jié)點發(fā)起RPC調(diào)用并等待返回。如本節(jié)點不是primary節(jié)點,則向Primary節(jié)點發(fā)起RPC調(diào)用并等待結(jié)果返回。當RPC調(diào)用成功后,本地執(zhí)行真正的提交動作。(Primary節(jié)點即根據(jù)一致性Hash算法計算出的第一個owner節(jié)點)。
如果在寫值過程中發(fā)生拓撲結(jié)構(gòu)變化或某個節(jié)點進入Suspect狀態(tài),此時Infinispan內(nèi)部將發(fā)起重試,直到操作成功。
同步復(fù)制的優(yōu)點在于強一致性,一旦寫操作執(zhí)行完畢,我們可以確定所有的遠端節(jié)點都已更新。但缺點也很明顯,寫值動作相比異步模式要慢很多,它要等待所有的RPC調(diào)用。另外,隨著節(jié)點增多,每次寫操作需通知的節(jié)點增多。
按《Infinispan User Guide》的建議,對于復(fù)制模式在節(jié)點數(shù)量較少時(10個以下)時,采用TCP協(xié)議會獲得更好的性能,但當節(jié)點數(shù)量增多時采用UDP會是更好的選擇。

Infinispan只在拓撲結(jié)構(gòu)發(fā)生變化或發(fā)生Suspect異常時,才會進行重試,而對于其他異常,如網(wǎng)絡(luò)狀況不佳導(dǎo)致的TimeOutException等不會重試,而是僅僅拋出異常。在這種情況下,不同節(jié)點節(jié)出現(xiàn)數(shù)據(jù)不一致,無法保證強一致性。關(guān)于Infinispan存在的全部一致性問題請參見[Infinispan一致性分析]。

3.3.2 異步復(fù)制

Infinispan提供了兩種異步復(fù)制方法。

  • 執(zhí)行寫操作時,先在本地執(zhí)行預(yù)提交(更新到MVCCEntry中),如本地節(jié)點是Primary節(jié)點則向其他所有節(jié)點發(fā)起RPC調(diào)用并直接返回。如本節(jié)點不是primary節(jié)點,則向Primary節(jié)點發(fā)起RPC調(diào)用并直接返回,最后本地執(zhí)行真正的提交動作。
  • 執(zhí)行寫操作時,先在本地執(zhí)行預(yù)提交(更新到MVCCEntry中),隨后將寫值命令插入到Replication Queue中,最后再本地執(zhí)行真正的提交動作。Replication Queue根據(jù)設(shè)定的時間間隔(或達到最大數(shù)量時)將隊列中的請求推送到所有節(jié)點。

采用Replication Queue方式的異步復(fù)制性能上更優(yōu),因為它會將發(fā)送的請求批量處理,減少了節(jié)點間的RPC請求數(shù)量和數(shù)據(jù)包處理數(shù)量。但數(shù)據(jù)延遲上會比第一種方式更高,因為前者采用立即發(fā)送RPC請求方式,而Replication Queue采用是周期輪詢方式。
異步復(fù)制的優(yōu)點在于優(yōu)異的寫值性能,一旦本地寫值成功即認為操作成功。但數(shù)據(jù)一致性無法保證,異步寫值失敗時不會發(fā)起重試,僅將錯誤消息記入LOG中。

3.3.3 適用場景

在小規(guī)模集群中,嵌入式的復(fù)制模式效果最佳。在此種模式下,讀操作只需訪問本地內(nèi)存,寫操作也只需同步到有限的幾個節(jié)點。
在小規(guī)模集群中,當無法采用嵌入式模式時,采用C\S的復(fù)制模式也是一種合理的選擇。但此種模式下,節(jié)點數(shù)量建議控制在3個以下,當節(jié)點數(shù)量超過3個時,采用C\S的分布式模式更為合理。
當集群規(guī)模增大時,嵌入式的復(fù)制模式在讀操作上依舊保持高性能,但寫值由于同步節(jié)點增多導(dǎo)致性能下降明顯。如果緩存單位時間內(nèi)的寫操作非常少可以考慮此類方式。
如對數(shù)據(jù)沒有強一致性訴求,可考慮采用異步模式(建議采用Replication Queue方式)。另外,采用UDP協(xié)議也可以有效減少節(jié)點間發(fā)送的數(shù)據(jù)包數(shù)量。

3.4 分布式(Distributed)模式

分布模式是Infinispan支持的可擴展性最好的一種模式。在這種模式下,用戶可以配置固定數(shù)量(numOwners)的副本數(shù),而不需要復(fù)制數(shù)據(jù)到所有的節(jié)點上。復(fù)制有限個副本既可以控制開銷,也可以帶來數(shù)據(jù)訪問性能和可靠性的提升。
在集群中,Infinispan通過一致性哈希(Consistent Hashing)算法來確定數(shù)據(jù)訪問和存儲的位置。使用一致性哈希是好處是:當現(xiàn)有節(jié)點失效或新節(jié)點加入時,系統(tǒng)不需要重新計算哈希來重新分配數(shù)據(jù)在集群中的存儲位置。
和復(fù)制模式相比,優(yōu)勢如下:

  • 可擴展性:對集群節(jié)點數(shù)量沒有限制,可根據(jù)業(yè)務(wù)需要,靈活的增、刪節(jié)點。
  • 數(shù)據(jù)網(wǎng)格:假設(shè)集群中有三個節(jié)點A,B,C,內(nèi)存大小為8G,復(fù)制模式下集群容量為8G。分布式模式下,如果每個條目保存在2個節(jié)點上,集群的容量為(8 G* 3) / 2 = 12G。

和復(fù)制模式一樣,分布式模式也支持同步和異步兩種模式

4. 并發(fā)處理

上節(jié)中提到Infinispan在寫值時采用了先寫入MVCCEntry的方式執(zhí)行預(yù)提交,最后才執(zhí)行真正的提交。MVCC(multi-versioned concurrency control)是多版本并發(fā)控制的簡稱,是目前流行的高性能并發(fā)處理機制,它有如下特點:

  • 多個并發(fā)讀操作和單個寫操作可并發(fā)運行,且無需加鎖。
  • 不同key的寫操作可并發(fā)運行,互不影響。
  • 相同key的寫操作排隊運行,鎖粒度低。
  • write skew可以被檢測并正確處理。

4.1 鎖

4.1.1 鎖類型

Infinispan支持兩種類型的鎖管理方式:為每個key維護一把鎖或者使用分離鎖(Lock striping)。

默認情況下,Infinispan采用的是為每個key維護一把鎖的方式,這種方式鎖粒度最小,并發(fā)性更高,但占用資源更多。
采用分離鎖(Lock striping)時,為每個cache分配固定數(shù)量的lock,每個lock負責(zé)鎖定一組entries(由key的hash code確定),這和ConcurrentHashMap類似。例如,ConcurrentHashMap的實現(xiàn)使用了一個包含16個鎖的數(shù)組,每一個鎖都守護HashMap的1/16。假設(shè)Hash值均勻分布,這將會把對于鎖的請求減少到約為原來的1/16。這項技術(shù)使得ConcurrentHashMap能夠支持16個的并發(fā)Writer。當多處理器系統(tǒng)的大負荷訪問需要更好的并發(fā)性時,鎖的數(shù)量還可以增加。

4.1.2 鎖應(yīng)用

在如下三種場景下需加鎖保護:

  • 非事務(wù)cache。寫操作發(fā)送到key所屬的primary節(jié)點,primary節(jié)點嘗試獲取鎖,成功則通知其他節(jié)點更新數(shù)據(jù),失敗則拋出異常。
  • 悲觀事務(wù)cache。寫操作或鎖請求操作發(fā)送到primary節(jié)點,primary節(jié)點嘗試獲取鎖,成功則繼續(xù)運行,失敗返回并回滾事務(wù)??梢杂行У叵龥_突,保證數(shù)據(jù)一致性,但是性能較低。
  • 樂觀事務(wù)cache。樂觀事務(wù)直到事務(wù)預(yù)提交階段才嘗試獲取鎖,primary節(jié)點嘗試獲取鎖,成功則執(zhí)行write skew檢查,如果write skew檢查成功則執(zhí)行事務(wù)操作,否則失敗并回滾事務(wù)。這樣的好處是減少占有鎖的時間,提高系統(tǒng)的數(shù)據(jù)訪問的吞吐量。該方法適用于多用戶并發(fā)修改相同緩存數(shù)據(jù)概率較低的場景。

4.2 事務(wù)隔離

Infinispan提供兩種級別的事務(wù)隔離機制:READ_COMMITTED(默認)和REPEATABLE_READ。

5 事件通知

5.1 Cache-level事件

Cache-level事件是指cache級別的事件通知,通過對指定cache添加listener的方式,應(yīng)用可監(jiān)聽cache的數(shù)據(jù)變化。對于集群cache,通知事件類型包括鍵值的新增、修改、刪除、過期。
集群模式下,嵌入式模式和C\S模式推送的事件類型相同,但處理方式上存在如下差別:

Cache-level事件

5.2 Cache manager-level事件

Cache manager level事件包括:cache start、cache stop、merged及viewchanged四種。并無特別之處,可參見Infinispan官網(wǎng)。

6. 高級用法

6.1 過濾器

Infinispan還支持自定義過濾器,特定讀值接口允許指定過濾器并返回滿足條件的一組數(shù)據(jù)。
嵌入式模式下,支持按key、value、metadata過濾,需實現(xiàn)KeyValueFilter接口。C\S式模式下,支持按key、value、metadata過濾,需實現(xiàn)KeyValueFilterConverterFactory接口,并且該實現(xiàn)類需提前部署到server上。

6.2 提高本地命中率

6.2.1 L1 caching

L1 caching是Infinispan自定義的本地一級緩存,它和本地其他緩存數(shù)據(jù)一起存放到ConcurrentMap中。在首次訪問時獲取遠端數(shù)據(jù)并保存至L1 cache,當再次訪問該數(shù)據(jù)時,直接訪問本地L1 cache。
L1 caching中的數(shù)據(jù)在超過指定的超時時間(l1-lifespan)后自動清除,或者當遠端數(shù)據(jù)發(fā)生變化是通知失效。
L1 caching的失效通知機制基本流程為:

  1. 當變更操作完成后,如果檢測到當前cache啟用了了caching,則發(fā)起失效通知。
  2. 首先檢測變更key(s)的所有請求者,如果沒有其他節(jié)點緩存了該key-value數(shù)據(jù),則不發(fā)起通知。
  3. 將一個或多個key的變更請求打包成單個RPC請求,如配置為TCP協(xié)議則采用單播方式發(fā)送。如配置為UDP協(xié)議,則判定該key值的請求者是否超過設(shè)定閾值,如超過則采用組播方式,否則采用單播方式發(fā)送。

L1 caching維護了一個key到多個請求者的對應(yīng)關(guān)系,每當其他節(jié)點請求本節(jié)點的某個key值,在映射表中增加一項。一旦數(shù)據(jù)發(fā)生變化,通過查找該結(jié)構(gòu)以確定需推送失效信息的節(jié)點。Infinispan啟動了一個定時任務(wù)來維護這組對應(yīng)關(guān)系,時間間隔可配置,默認為10分鐘,負責(zé)定時清理過期的對應(yīng)關(guān)系。
如A節(jié)點訪問了B節(jié)點”Hello”-“Value”數(shù)據(jù),此時B節(jié)點將A節(jié)點添加到”Hello”鍵的請求者列表中。之后即便A節(jié)點永遠不再訪問”Hello”數(shù)據(jù),在”Hello”數(shù)據(jù)發(fā)生變化時依舊會向A節(jié)點發(fā)送失效消息。直到B節(jié)點的定時任務(wù)觸發(fā)將A節(jié)點從”Hello”的請求者列表中移除。
L1 caching適用于集群中某些節(jié)點存在頻繁訪問相同數(shù)據(jù)的場景,在這種場景下,將遠端數(shù)據(jù)訪問轉(zhuǎn)換為一次本地內(nèi)存訪問,極大提高讀操作性能。

6.2.2 Capacity factor

在分布式模式下,每個節(jié)點作為數(shù)據(jù)網(wǎng)格的一部分存儲緩存數(shù)據(jù)。默認情況下,一致性hash選擇將數(shù)據(jù)放到哪個節(jié)點時,采用的是“公平的”算法,其認定每個節(jié)點在存儲能力上是一致的。
而在實際情況當中,各個節(jié)點的內(nèi)存數(shù)據(jù)可能是不一致的,或者某個節(jié)點相比其他節(jié)點訪問數(shù)據(jù)訪問更加頻繁。對于這種情況,我們希望一致性hash在做數(shù)據(jù)到節(jié)點映射時可以根據(jù)實際情況做相應(yīng)的調(diào)整。
Infinispan提供了capacity factor來滿足這種需求,默認情況下所有節(jié)點的capacity為1。如設(shè)置為2,則建議本地節(jié)點存儲的鍵值數(shù)量是其他節(jié)點的兩倍。注意,這里指明的是建議值,實際根據(jù)集群的運行情況向建議值靠近。

6.2.3 Key Affinity

這種技術(shù)指的是通過隨機生成key的方式,可以指定該key的存放節(jié)點,以做到用戶自主選擇服務(wù)節(jié)點的目的。使用場景有限,切在數(shù)據(jù)遷移場景下,舊數(shù)據(jù)無法保證始終在指定的節(jié)點上。

7. 一致性分析

:下述一致性分析默認基于Embedded模式,如C\S模式行為和Embedded模式不一致將在每節(jié)的末尾處指明。

7.1 復(fù)制(Replicate)模式

7.1.1 非事務(wù)模式

對于single key的寫值操作,寫值操作會發(fā)送到primary節(jié)點,由primary節(jié)點獲取全局鎖,并廣播更新到所有其他節(jié)點(包括originator節(jié)點)。如果originator即primary節(jié)點,則省去發(fā)送到primary節(jié)點操作,直接獲得全解鎖并廣播。在集群處于穩(wěn)定狀態(tài)時,數(shù)據(jù)保證一致性。
對于multi-key的寫值操作,將不同的key發(fā)送到primary節(jié)點,在每個primary節(jié)點上單獨處理寫值操作。當key分散在不同的節(jié)點上時,操作并不保證原子性。
clear操作不獲取全局鎖,而是各自清理各自的本地內(nèi)存,同樣不保證原子性。

7.1.1.1 拓撲結(jié)構(gòu)變更

新節(jié)點加入
新節(jié)點加入時,現(xiàn)有節(jié)點將復(fù)制所有數(shù)據(jù)到新節(jié)點上。
如果在復(fù)制過程中,新節(jié)點上發(fā)起KeyA的read操作,此時本地節(jié)點不存在KeyA數(shù)據(jù),Infinispan將向其他所有節(jié)點發(fā)送read請求,并將最快返回的數(shù)據(jù)作為read的結(jié)果。這可能導(dǎo)致如下問題:
由于本地沒有key的數(shù)據(jù),多次發(fā)起遠端請求時由于最快響應(yīng)的節(jié)點不同導(dǎo)致數(shù)據(jù)不一致,但這只發(fā)生在state transfer過程中,一旦同步完畢,則不存在該問題。

發(fā)起者(originator)異常
節(jié)點A發(fā)起write請求后,該節(jié)點異常。
如果其他節(jié)點在處理write請求時,發(fā)生拓撲結(jié)構(gòu)變化,將拋出OutdatedTopologyException,并且不會重試(因為重試之后發(fā)生在originator上)。同時,primary節(jié)點也將更新失敗(因為primary節(jié)點一定是最后一個節(jié)點)。此時可能出現(xiàn)部分節(jié)點已更新,但部分節(jié)點更新失敗問題,數(shù)據(jù)不一致。

C\S模式下,write請求的originator和primary為同一節(jié)點

新節(jié)點加入\移除
在寫操作執(zhí)行過程中,如果存在節(jié)點加入\移除,此時將產(chǎn)生OutdatedTopologyException或SuspectException異常,并由originator節(jié)點發(fā)起重試,以保證所有節(jié)點的數(shù)據(jù)一致性。
當originator同時是primary節(jié)點時,retry符合重試預(yù)期,但如果originator不是primary節(jié)點可能存在如下問題:
線程1、線程2同時執(zhí)行put操作,線程3執(zhí)行g(shù)et操作。線程1首次put動作執(zhí)行失敗并準備重試,此時部分節(jié)點已經(jīng)更新成功,而另外節(jié)點未更新,線程3節(jié)點已更新故讀到v1。在線程1的put動作重試之前,線程2執(zhí)行了put操作并更新成功,此時線程3的get操作將讀到線程2更新的結(jié)果。隨后線程1的put重試并成功,線程3又讀到了線程1更新的結(jié)果,并且該結(jié)果作為集群中該key的最終結(jié)果。注意:C\S模式下,不存在該問題。

7.1.1.2 網(wǎng)絡(luò)分區(qū)處理

Partition handlingdisabled
在此模式下,拆分的兩個分區(qū)將做為兩個集群獨立運行。
兩個分區(qū)獨立運行,數(shù)據(jù)更新并不互通,數(shù)據(jù)不一致。
當分區(qū)合并時,infinispan并不嘗試merge不同的數(shù)據(jù)。infinispan將最大的分區(qū)(節(jié)點數(shù)最多的)做為新集群的初始狀態(tài),另外分區(qū)的所有節(jié)點上的數(shù)據(jù)將被覆蓋。這時,集群內(nèi)數(shù)據(jù)保證一致,但數(shù)據(jù)可能并不是用戶預(yù)期的數(shù)據(jù),而是“過時”的數(shù)據(jù)。
Partition handling enabled
在分區(qū)前,集群中所有的節(jié)點視為穩(wěn)定狀態(tài)(stable topology)。如果出現(xiàn)至少一半的節(jié)點快速異常脫離本集群,此時該集群將被降級“Degraded”,降級的集群即不可讀也不可寫。Infinispan將集群降級是出于如下假設(shè):異常脫離本集群的超過半數(shù)的節(jié)點可能組成了新的集群,并且該集群是可讀寫的。
合并時存在以下幾種場景:

  • 兩個分區(qū)都被降級,合并后的分區(qū)足夠恢復(fù)到avaliable狀態(tài),合并后的集群重新變?yōu)閍vailable。
  • 兩個分區(qū)都被降級,合并后的分區(qū)不足以恢復(fù)到available狀態(tài),合并后的集群仍舊處于降級狀態(tài)。
  • 一個分區(qū)為available狀態(tài),另外分區(qū)為degraded狀態(tài),合并后的集群變?yōu)閍vailable狀態(tài),并且degraded的分區(qū)數(shù)據(jù)被覆蓋。
    對降級分區(qū)的讀、寫操作均會產(chǎn)生AvailabilityException異常。

C\S模式下,推測所有客戶端均連到相同的分區(qū),待確認

7.1.2 超時異常

當RPC請求超過設(shè)定的replication超時時間依舊未返回時,將拋出TimeoutException。如NAKACK2協(xié)議采用的是消極確認重發(fā)機制,消息重發(fā)可能導(dǎo)致超過設(shè)定的replication timeout。
如果primary節(jié)點向其他節(jié)點發(fā)起的RPC請求拋出TimeoutException異常,此時primary節(jié)點更新失敗。如果originator向primary節(jié)點發(fā)起的RPC請求超時,可能所有節(jié)點成功也可能部分成功。
獲取鎖也可能出現(xiàn)超時,出現(xiàn)在單個key的寫操作時,寫操作失敗。如果是multi-key的寫操作,其他primary節(jié)點的寫操作依舊執(zhí)行成功。
一般來說,當出現(xiàn)TimeoutException時,可以認定在部分節(jié)點上更新成功,另外節(jié)點上更新失敗,數(shù)據(jù)不一致。

7.2 分布式(Distributed)模式

7.2.1 非事務(wù)模式

基本行為和復(fù)制模式下的類似,請參見12.1.1非事務(wù)模式。

7.2.1.1 讀一致性

當一個節(jié)點試圖讀取本節(jié)點不存在的數(shù)據(jù)時,將向所有其他節(jié)點發(fā)送讀請求,并以最快返回的結(jié)果為準。當讀、寫并發(fā)時可能出現(xiàn)如下問題:
在線程1的cache.put(key,v2)處理過程中,節(jié)點依次更新,線程2的讀取行為可能由于讀到了不同的節(jié)點而出現(xiàn)讀到之前數(shù)據(jù)的問題。

7.2.1.2 拓撲結(jié)構(gòu)變更

當originator發(fā)起一次讀請求時,處理方式如下:

  • 如果某個節(jié)點返回了正確的數(shù)據(jù),讀請求結(jié)束。
  • 如果所有節(jié)點都沒有響應(yīng),并且檢測到拓撲結(jié)構(gòu)變化,發(fā)起重試。
  • 如果讀請求返回的結(jié)果為null,并且當前正在做reblance處理,以新的WriteCH(寫一致性hash)替代當前的ReadCH(讀一致性hash),發(fā)起重試。
  • 如果讀請求返回結(jié)果為null,并且即沒有拓撲結(jié)構(gòu)變化,也沒有reblance處理,則返回null。
    其他特性和復(fù)制模式相同,請參見復(fù)制模式的拓撲結(jié)構(gòu)變更一節(jié)。

7.2.1.3 網(wǎng)絡(luò)分區(qū)處理

Partition handlingdisabled
基本處理和復(fù)制模式相同。
當集群被拆分成兩個獨立的分區(qū)時,每個分區(qū)獨立的執(zhí)行reblance,保證分區(qū)中每個key的owner數(shù)量和設(shè)定值相同。對于key值來說,如果分區(qū)中該key有n個owner,則復(fù)制的數(shù)量為numOwners-n,如果分區(qū)中該key沒有owner,則該數(shù)據(jù)丟失。
當分區(qū)合并時,infinispan將topology id最大的分區(qū)做為新集群的基準。另外分區(qū)的所有節(jié)點上的數(shù)據(jù)將被覆蓋。這時,集群內(nèi)數(shù)據(jù)保證一致,但數(shù)據(jù)可能并不是用戶預(yù)期的數(shù)據(jù),而是“過時”的數(shù)據(jù)。另外,如果基準分區(qū)在split時丟失了某些key-value數(shù)據(jù),而另外分區(qū)中持有這些key-vale,合并后這部分數(shù)據(jù)丟失。
Partition handling enabled
在分區(qū)前,集群中所有的節(jié)點視為穩(wěn)定狀態(tài)(stable topology),出現(xiàn)集群拆分時處理方式如下:

  • 如果分區(qū)中包含的節(jié)點數(shù)量少于原集群數(shù)量的一半時,分區(qū)降級。
  • 如果分區(qū)中至少有一個segment的全部owners丟失,分區(qū)降級。
  • 如不是以上兩種情況,分區(qū)視為正常集群,并啟動reblance。
    和復(fù)制模式不同,分布式模式下降級的分區(qū)處理方式如下:
  • 如果該分區(qū)包含了該key的所有owner,課執(zhí)行正常的讀寫操作。
  • 如果該分區(qū)僅包含了該key的部分owner或全部owner丟失,讀寫操作將拋出AvailabilityException異常。
    其他處理方式和復(fù)制模式一致性。
    超時異常?

7.3 小結(jié)

Partition handling enabled的集群模式下,Infinispan負責(zé)保證系統(tǒng)的一致性。
對于當前版本的Infinispan來說,主要存在如下兩種數(shù)據(jù)不一致場景:

  • 發(fā)起者異常+拓撲結(jié)構(gòu)更新。在infinispan中,拓撲結(jié)構(gòu)引發(fā)的異常由發(fā)起者發(fā)起重試。如拓撲結(jié)構(gòu)更新時,發(fā)起者已經(jīng)異常,此時無法發(fā)起重試,可能存在部分節(jié)點更新成功而部分節(jié)點更新失敗問題。
  • 超時異常。當出現(xiàn)超時異常時,infinispan并不發(fā)起重試,而僅僅拋出異常,對于此種場景,集群中節(jié)點會出現(xiàn)數(shù)據(jù)不一致。

8. 總結(jié)

Infinispan采用Java開發(fā),性能上和redis相當,但資源消耗和CPU耗費上高于redis。Infinispan支持各種Java類型存儲,集成度更好。
可靠性上,redis和infinispan均不能保證100%的可靠性、數(shù)據(jù)一致性,相較來說,個人認為infinispan可靠性更高。


轉(zhuǎn)載請注明:【隨安居士】http://www.itdecent.cn/p/d9e6912aaab1

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 分布式系統(tǒng)面臨的第一個問題就是數(shù)據(jù)分布,即將數(shù)據(jù)均勻地分布到多個存儲節(jié)點。另外,為了保證可靠性和可用性,需要將數(shù)據(jù)...
    olostin閱讀 4,934評論 2 26
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,647評論 19 139
  • 《高性能MySQL》&《MySQL技術(shù)內(nèi)幕 InnoDB存儲引擎》筆記 第一章 MySQL架構(gòu)與歷史 MySQL的...
    xiaogmail閱讀 13,142評論 0 39
  • 3.2 彈性分布式數(shù)據(jù)集 本節(jié)簡單介紹RDD,并介紹RDD與分布式共享內(nèi)存的異同。 3.2.1 RDD簡介 在集群...
    Albert陳凱閱讀 1,737評論 0 0
  • 2017年7月30日 聚焦網(wǎng)初五原創(chuàng) 張婷 鄭州 分享第五十八天 星期天回鄭路上 歲月讓人成長,人生...
    心愿幸福閱讀 203評論 0 0

友情鏈接更多精彩內(nèi)容