架構學習筆記系列三

cdh0805010118發表於2018-06-25

阿里架構

《破解世界性技術難題!GTS 讓分散式事務簡單高效》一文,在分散式或者微服務流行的今天,一個外部的請求可能會呼叫多個服務。分散式事務就是為了保證某個服務出錯時,能保證資料的一致性,這個請求的所有服務操作,要麼全部成功、要麼全部失敗。

本質上來說,分散式事務就是為了保證不同資料庫或者訊息系統的資料一致性

分散式事務三大難題:

  1. 資料一致性
  2. 高效能
  3. 易用性

一般情況都是,確保資料一致性所付出的成本代價高昂,會損耗掉高效能和易用性。前者:由於處理資料一致性,導致業務邏輯過於繁瑣,效能地下、且業務程式碼生涉難懂。

但是如果三者缺一,則使用場景大大受限,實用價值不高。

  1. 資料一致性。要求在各種異常情況下保證資料是強一致的,目前最常見的一致性解決方案是最終一致性方案,例如:分散式系統中的 CAP 理論,三個特性不能同時滿足的情況下,P 是肯定滿足,CA 二者選其一,我們一般都會選擇高可用的情況,保證資料的最終一致性,這樣就能夠間接滿足 CAP 理論。為了實現資料的最終一致性,通常是結合訊息中介軟體實現。
  2. 高效能:目前基於 XA 協議的兩階段提交時最常見的分散式事務解決方案。但是 XA 類產品的典型不足時效能低下,往往不能接受。
  3. 易用性:為了滿足一致性和高效能要求,出現了一些特定場景下的分散式事務方案,但是一般都會對業務侵入強,無法做到簡單易用,成本高。

阿里針對世界級應用場景,提出了世界級分散式事務解決方案-GTS, 該專案負責人姜宇。該文指出了微服務下分散式事務目前已存在的解決方案:

  1. 基於 XA 協議的 2PC(兩階段提交) 方案 shell 兩階段提交,分別是:表決階段和執行階段。兩階段提交方案應用很廣泛,幾乎所有OLTP資料庫都支援XA協議,但是兩階段提交方案鎖定資源時間長,對效能影響很大,基本上不適合解決微服務事務問題
  2. TCC 方案 shell TCC(Try-Confirm-Cancel)方案,它是兩階段提交的一種改進。 Try:完成業務的準備工作,Confirm:完成業務的提交,Cancel:完成事務的回滾。 事務協調器會根據Try的執行返回結果,然後決定呼叫Confirm或者Cancel介面。 TCC方案可以定義自己的資料鎖粒度,降低鎖衝突,提高併發吞吐量成為可能。但是它的不足之處在於: 1. 對應用的侵入性強。業務邏輯的每個分支都要實現try、confirm和cancel三個操作,業務侵入性強,改造成本高; 2. 實現難度較大。需要根據網路狀態、系統故障等不同的失敗原因,實現不同的回滾策略。為了滿足一致性要求,confirm和cancel介面必須實現冪等。
  3. 基於訊息的最終一致性方案 shell 訊息一致性方案是通過訊息中介軟體儲存上下服務資料操作的一致性。基本思路:將本地操作和傳送訊息放在一個事務中,保證本地操作和訊息傳送操作,要麼兩者都成功或者失敗。下游收到訊息後執行相應操作。 訊息方案從本質上來說,是將分散式事務轉換為兩個事務,然後依靠下游業務的重試機制達到最終一致性,這個改進在於下游的事務操作失敗後,還可以通過訊息中介軟體進行事務補償,從而達到資料的最終一致性。 缺點:基於訊息的最終一致性方案對應用的侵入性也很高,應用需要進行大量的業務改造,成本高。
  4. GTS —— 阿里分散式事務解決方案

    特點:
    1. 效能超強
    2. 應用侵入性極低
    3. 完整解決方案
    4. 容錯能力強
    
    GTS包括客戶端Client、Server事務協調器和資源管理器(RM):
    GTS Client主要用來確定事務邊界,完成事務的發起和結束
    GTS RM完成事務分支的建立、提交和回滾等操作(它存在於每個微服務中,類似於agent)
    GTS Server主要負責分散式事務的整體推進和事務生命週期管理
    

《如何打造支撐百萬使用者的分散式程式碼託管平臺?》一文,Gitlab 不滿足 SaaS 設計12 原則的第四條:後端服務-把後端服務當做附加資源。大家可以認真理解下這 12 原則,對大家以後的 SaaS 微服務設計非常有幫助。

1. 基準程式碼——一份基準程式碼,多份部署
    基準程式碼與應用之間總是保持一一對應的關係:
    一方面,如果一個應用有多個基準程式碼,則是分散式系統。另一方面,多個應用共享一份基準程式碼,則需要分為獨立的類庫
2. 依賴——顯式宣告依賴關係
    該規則不會隱式依賴系統級的類庫。它一定是通過依賴清單,確切地宣告所有依賴項, 這個做法會統一應用到開發、測試和生產環境中。
    例如:包管理dep初始化程式碼庫的依賴包時,它會生成Gopkg.toml, 這裡面存放著所有依賴包和包的當前版本號,顯示宣告所有依賴,同時也方便了庫的下載和版本號導致的編譯錯誤或者不穩定。
3. 配置——在環境中儲存配置
    這個是非常常見的做法,同一份程式碼,通過取環境變數,來指定當前的服務環境(開發、測試和生產環境),以及服務配置中心的db、cache、dns或者其他引數的value,這個是非常重要的,做到了去程式碼依賴。
4. 後端服務——把後端服務當做附加資源
    12原則應用不會區分對待本地和第三方應用,例如:本地mysql服務和第三方AWS上的RDS服務,我們只需要通過獲取配置中心的db服務配置,就可以進行db儲存操作。(而gitlab違反了這一設計的主要原因在於:1. 資料儲存於伺服器本地的檔案系統上;2.gitlab所依賴的三個重要元件:libgit2, git, grit也都是直接操作在檔案系統上。由此當gitlab的資料儲存出現容量和負載瓶頸時,難以擴容!)
5. 構建、釋出和執行——嚴格分離構建和執行
6. 程式——以一個或者多個無狀態程式執行應用
    12原則應用的程式必須是無狀態且無共享。任何需要持久化的資料都要儲存在後端服務內,比如資料庫。
    無狀態程式或者服務,則在負載彈性伸縮方面變得簡單。同時服務編排也變得簡單可行。例如:serverless的k8s, mesos等服務編排工具
7. 埠繫結——通過埠繫結來提供服務
    12原則應用完全自我載入而不依賴於任務網路伺服器就可以建立一個面向網路的服務。web應用通過埠繫結來提供服務, 並監聽傳送到該埠的所有請求。
8. 併發——通過程式模型進行擴充套件
    它主要是借鑑unix守護程式模型, 開發人員可以根據不同工作進行程式分類。例如:典型的Nginx(master nginx和worker nginx),或者中心化叢集(master node , slave node)。這樣master程式只做訊息、元素同步和代理轉發工作, 實際的業務處理通過worker計算節點做,這樣通過業務請求分發模式,使得業務計算量擴容簡單方便,同時程式的守護通過supervisor守護。
9. 易處理——快速啟動和優雅終止可最大化健壯性
    這個易處理原則,意思是程式可以瞬間開啟或者停止。這樣服務可以快速擴容或者縮容,迅速部署穩健的服務。
    1. 典型的切流量,如果服務冷啟動過慢,則對使用者而言,服務是可感知有損的
    2. 某個區域服務節點當機時,閘道器服務必須立即停止服務,不能接入新的流量進來。新的流量無法被正確處理。
10. 開發環境與線上環境等價——儘可能地保持開發、預釋出、線上環境相同
    一般來說開發環境和線上環境的程式碼庫會存在一些差異,主要表現:
    1. 時間差異:開發環境可能正在開發新功能,線上環境的程式碼比開發環境老;
    2. 人員差異:開發所需要的資源和線上的資源不一樣,生產環境的資料儲存、配置中心等和開發環境不一樣;部署策略可能也不一樣
    3. 工具差異:開發環境可能部署工具、服務監控、metrics指標等都和生產環境不一樣。開發環境的資源比較集中、而生產環境的資源是開發不可控的, 以及日誌處理等
11. 日誌——把日誌當做事件流
    該原則是指服務本身不關心日誌的儲存容量、位置、日誌分析,它只是呼叫一個日誌元件或者方法,提供日誌內容。
12. 管理程式——後臺任務管理當做一次性程式執行
    該原則是指,程式的無狀態,以及程式掛掉後的服務高可用的保證。如果採用docker,則可以通過各種服務編排工具實現;否則,可以通過supervisor來實現程式down時,自動拉起。
更多原創文章乾貨分享,請關注公眾號
  • 架構學習筆記系列三
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章