架構雜談《五》


架構雜談《五》

保證最終一致性的模式

  在大規模、高並發服務化系統中,一個功能被拆分成多個具有功能單一的子功能,一個流程會有多個系統的多個單一功能的服務組合實現,如果使用兩階段提交協議和三階段提交協議,確實能解決系統間的一致性問題。其實現也比較復雜、成本比較高,最重要的是性能不夠好,相比來看,TCC協議簡單、更容易實現,但TCC協議由於每個事務都需要執行Try再執行Confirm 顯得有點臃腫,實現最終一致性有一些非常有效、簡單的模式。

一、查詢模式

  任何服務操作都需要提供一個查詢接口,用來向外部輸出操作執行的狀態。服務操作的使用方可通過查詢接口得知服務執行的狀態,然后根據不同的狀態來做不同的處理操作。

  為了實現查詢,每個服務操作都需要有唯一的標識符。

  首先,單筆查詢操作的必須提供的(也鼓勵使用單筆訂單查詢),因為每次調用需要占用的負載是可控的。批量查詢則根據需要來提高(如果使用了批量查詢,需要有合理的分頁機制,並且必須限制分頁的大小,以及對批量查詢的吞吐量有熔斷、隔離和限流等措施)。

(查詢模式圖)

二、補償模式

  有了查詢模式,可以在任何情況下都可得知具體操作所處的狀態,如果整個操作都處於不正常狀態,則需要我們修正操作中有問題的子操作,這可能需要重新執行未完成的子操作,或者取消已經完成的子操作,通過修復使整個分布式系統達到一致。為了讓系統最終達到一致狀態而做的努力都叫做補償。

  對於服務化系統中同步調用的操作,若業務操作發起方沒有收到業務操作執行方的明確返回或者調用超時,這時業務發起方需要及時地調用業務執行方來獲得操作執行的狀態(這就是查詢模式)。在獲得業務操作執行方的狀態后,如果業務執行方已完成預設工作,則業務發起方向業務的使用方返回成功;如果業務操作執行方的狀態為失敗或者未知,則會立即告訴業務使用方失敗(也叫做快速失敗策略),然后調用業務操作的逆向操作,保證操作不被執行或者回滾已經執行的操作,讓業務使用方、業務操作發起方和業務操作執行方最終達到一致狀態。

(補償模式圖)

  補償操作模式發起形式分為以下幾種:

  (1)自動恢復:程序根據發生不一致的環境,通過繼續執行未完成的操作或者回滾已經完成的操作達到一致性狀態。

  (2)通知運營:如果程序無法自動恢復,並且設計師考慮到了不一致的場景,則可以提供運營功能,通過運營手工進行補償。

  (3)技術運營:如果程序無法自動恢復、又沒有運營功能,那么必須通過技術手段來解決,技術手段包括進行數據庫變更或者代碼變更,這是最糟的種場景也是我們在生中盡避免的場景 。 

三、異步確保模式

  異步確保模式是補償模式的一個典型案例,經常應用到使用方對響應時間要求不太高的場景中,通常把這類操作從主流程中摘除,通過異步的方式進行處理,處理后把結果通過通知系統通知給使用方。這種方案的最大好處是能夠對高並發流量進行消峰,例如:電商系統中的物流、配迭,以及支付系統中的計費、入賬等。
  在實踐中將要執行的異步操作封裝后持久入庫,然后通過定時撈取未完成的任務進行補償操作來實現異步確保模式,只要定時系統足夠健壯,則任何任務最終都會成功執行 。

(異步確保模式圖)

四、定期校對模式

  系統在沒有達到一致之前,系統間的狀態是不一致的,甚至是混亂的,需要通過補償操作來達到最終一致性的目的,但是如何來發現需要補償的操作呢?

  在操作主流程中的系統間執行校對操作,可以在事后異步地批量校對操作的狀態,如果發現不一致的操作則進行補償,另外,實現定期校對的一個關鍵就是分布式系統中需要有一個自始至終唯一的ID。

  在實踐中想在分布式系統中迅速定位問題時,可通過分布式系統的調用鏈跟蹤系統進行,它能夠跟蹤一個請求的調用鏈。調用鏈是從二維的維度跟蹤一個調用請求 , 最后形成一個調用樹。

  全局的唯一ID 可以將一個請求在分布式系統中的流轉路徑聚合,而調用鏈中的SpanID 可以將聚合的請求路徑通過樹形結構進行展示,讓技術支持工作人員輕松地發現系 統出現的問題 , 能夠快速定位出現問題的服務節點,提高應急效率。

  在分布式系統中構建了唯一 ID、調用鏈等基礎設施后,我們很容易對系統間的不一致進行核對 。 通常我們需要構建第三方的定期核對系統,從第三方的角度來監控服務執行的健康程度 。

(定期核對模式圖)

 

五、可靠消息模式

  在分布式系統中,對於主流程中優先級 比較低的操作,大多采用異步的方式執行,也就是前面提到的異步確保模型,為了讓異步操作的調用方和被調用方充分解耦,也由於專業的消息隊列本身具有可伸縮、可分片、可持久等功能,我們通常通過消息隊列實現異步化。對於消息隊列,我們需要建立特殊的設施來保證可靠的消息發送及處理機的幕等性。

  (1)消息的可靠發送

      消息的可靠發送可以認為是盡最大努力發送消息通知,有以下兩種實現方法。

      a)在發送消息之前將消息持久到數據庫,狀態標記為待發送 , 然后發送消息,如果發送成功,則將消息改為發送成功。定時任務定時從數據庫撈取在一定時間內未發送的消息並將消息發送。

 

可靠消息發送模式1 

       b)該實現方式與第 1 種類似,不同的是持久消息的數據庫是獨立 的, 並不藕合在業務系統中。發送消息前,先發送一個預消息給某個第三方的消息管理器,消息管理器將其持久到數據庫,並標記狀態為待發送,在發送成功后,標記消息為發送成功。定時任務定時從數據庫中撈取一定時間內未發送的消息,查詢業務系統是否要繼續發送,根據查詢結果來確定消息的狀態。

 

 

 

(可靠消息發送模式 2 )

  

(2)消息處理器的冪等性  

  如果我們要保證可靠地發送消息,簡單來說就是要保證消息一定發送出去,那么需要有重試機制。有了重試機制后,消息就一定會重復,那么我們需要對重復的問題進行處理。處理重復問題的最佳方式是保證操作的幕等性,幕等性的數學公式為:
        f (j(x)) =f (x)
  保證操作的幕等性的常用方法如下。
    1、使用數據庫表的唯一鍵進行濾重,拒絕重復的請求。
    2、使用分布式表對請求進行濾重。
    3、使用狀態流轉的方向性來濾重,通常使用數據庫的行級鎖來實現。
    4、根據業務的特點,操作本身就是幕等的 , 例如 : 刪除一個資源、增加一個資源、獲得一個資源等。

六、緩存一致性模式

  在大規模、高並發系統中的一個常見的核心需求就是億級的讀需求,顯然,關系型數據庫並不是解決高並發讀需求的最佳方案,互聯網的經典做法就是使用緩存來抗住讀流量。下面是使用緩存來保證一致性的最佳實踐。

  1、如果性能要求不是非常高,則盡量使用分布式緩存,而不要使用本地緩存。

  2、寫緩存時數據一定要完整

  3、使用緩存犧牲了一致性,為了提高性能,數據庫與緩存只需要保持弱一致性,而不需要保持強一致性,否則違背了使用緩存的初衷。

  4、讀的順序是先讀緩存,后讀數據庫,寫的順序要先寫數據庫,后寫緩存。 

說明:

  1、參考書籍:《分布式服務架構:原理、設計與實戰》

  2、如有不合適的地方請反饋。綜合后更改。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM