許文奇,螞蟻金服高階技術專家,
SOFAStack 商業化產品技術 Leader,多年分散式架構及中介軟體研發經驗,負責過螞蟻金服分散式架構在多家金融機構的諮詢和落地。
本文根據他在 2019 螞蟻金服 ATEC(Ant Technology Exploration Conference)科技大會上海站的分享整理。
本次分享主要會從單體架構和微服務架構的對比開始,後面重點談一下實施金融級分散式架構的常見三個問題。
常用架構:單體式架構
目前很多金融機構的架構是典型的單體式架構,一般由反向代理伺服器,資料庫和應用組成,所有業務模組都打包在一個應用裡面執行,一般為了高可用考慮,應用至少會部署兩個節點。單體式架構在業務簡單的時候有很多它自身的優點:
-
開發,測試簡單
-
部署簡單
-
擴容簡單,只要給應用加機器就行
但同樣,單體式架構也有很多缺點,尤其是業務規模變得複雜以後,缺點會非常突出:
-
編譯慢,啟動慢,程式碼衝突等各種問題,嚴重影響開發效率
-
效能擴充套件有侷限性,一定規模後,單純堆機器已經很難擴充套件效能了。
螞蟻金服的架構:分散式架構
微服務架構是目前大家最關註的一種分散式架構。微服務架構除了在效能可擴充套件性上對比單體式架構有巨大優勢,還有一個重要優勢體現在複雜業務下的生產效率優勢。
只有在業務複雜度較低的時候,單體式架構的生產效率才能超過微服務架構,但隨著業務複雜度上升,尤其過了臨界點,單體架構下的生產效率是非常恐怖的急速下墜,而微服務架構生產效率有所下降,但下降趨勢非常緩慢,且不會偏離原有生產效率太多,能很好的應對業務複雜性的增長。
所以實施微服務架構最重要的一個意義是在業務複雜度較高的情況下提升生產效率,更快速的進行業務創新。
實施金融級分散式架構最常見的三個挑戰
基於微服務架構的巨大優勢,很多金融機構、企業開始逐漸轉型微服務架構,轉型總是伴隨著挑戰,這裡選了三個最常見的,最多使用者關心的問題,聊聊螞蟻金服的一些實踐心得:
-
如何進行微服務架構拆分及治理?
-
新的分散式架構如何相容老系統?
-
如何一步一步構建金融級容災架構?
1、微服務架構拆分及治理
微服務拆分樣式可以從微服務架構的擴充套件立方開始講起,分為X軸,Y軸,Z軸三類拆分。
X軸代表橫向擴充套件樣式。主要透過部署多份應用,負載均衡的方式來擴充套件效能,這個單體架構也可以做。當然,在微服務架構下,橫向擴充套件樣式的實現方式有別於單體架構。
微服務架構做服務負載均衡不需要透過F5或者LVS叢集這樣的硬體裝置,只需要透過註冊中心就可以實現,這樣帶來的好處是降低了成本,不需要購買大量的硬體裝置了;提高了效能,業務幹路上少了一個單點風險;降低了維護成本。
當然支援橫向擴充套件樣式還需要應用是無狀態的,這個是微服務架構的基本要求,任何涉及狀態的資料都應該儲存在資料庫,快取或者其他一些儲存介質中。更高的要求的話,應用應該要滿足著名的12要素的要求。
Y軸代表功能分解樣式。我們提倡業務系統在開發的時候就應該按照模組化進行開發,滿足高內聚,低耦合的架構要求。為了更好支援模組化開發,以SOFAStack中介軟體的SOFABoot框架為例,框架支援模組隔離能力,不同的模組使用不同的Spring背景關係,這樣不同的模組之間就不能直接取用了,如果需要呼叫別的模組的介面,那麼需要走SOFABoot框架規定的特別宣告才可以辦到。這樣極大的規範了模組化開發,使得這些系統將來在進行拆分的時候,成本非常的低。
關於功能分解,服務拆分,雖然沒有一個標準答案告訴我們就該怎麼做,但其實也有一些基本指導原則和實踐:
-
按照業務領域進行拆解,而不是組織。所有拆分必須按照業務領域模型進行合理劃分,因為物體組織不一定能和業務領域完全對應,且組織一般粒度較大,不能作為拆分細粒度微服務的參考。
-
從資料核心模型拆分開始先拆,而後再往上進行服務拆分。這個主要是進行拆分的一個重要次序問題。一般梳理資料核心模型比較容易,比如很容易梳理出哪些表,哪些資料屬於交易,哪些表,哪些資料屬於賬務,然後按照業務垂直進行拆分。有些業務歸屬不那麼明確的可以按照資料親和性進行拆分。然後資料核心模型拆分好以後,再往上按照功能模組,所對應的場景,進行服務拆分。
-
單一職責。這個是微服務架構的一條金科玉律,要求微服務架構必須遵守。一個很主要的原因是為了避免微服務架構重新掉進單體架構的老問題裡面。原來單體架構最大的問題就是任何的改動,都要導致整個應用重新的編譯打包部署,還包括全量回歸測試。試想一個微服務裡面有太多的功能、職責,如果任意一個業務模組有需求,需要改動,必然導致該微服務的應用重新編譯,打包部署和全量回歸測試,頻繁變動成本很高,研發效率也會降低。
-
註意拆分粒度,避免一開始拆得過細,循序漸進。關於拆分粒度,這個也是一個沒有標準答案的問題。總的一個原則就是適用最好。任何一家公司的業務都是獨一無二的,不存在一模一樣業務的兩家公司,所以別人的拆分,可以借鑒,但往往很難照抄。所以推薦拆分的時候,一開始不要拆得過細,按照業務發展的規律,循序漸進。舉個例子,比如說紅包業務,原來可能只是營銷系統的一個模組,但如果公司的業務在紅包這塊發展得足夠複雜,是可以考慮拆為單獨的微服務,這一切取決於業務發展。
-
註意服務分級和分層,避免迴圈依賴。這個要求服務拆分的時候,充分註意到哪些是核心服務,哪些是非核心服務,不能出現核心服務強依賴非核心服務的情況,更不能出現迴圈依賴的情況。
-
考慮團隊結構。最後微服務拆出來,肯定是要有對應團隊去維護的,所以整個拆分的粒度,拆分的邏輯也要考慮團隊結構的情況。
Z 軸代表資料分割槽樣式。一般在資料庫遇到效能瓶頸的時候,需要進行資料拆分,一般分為垂直拆分和水平拆分。垂直拆分一般就是按照業務劃分來進行,比如以前賬務和交易放在一個資料庫,現在資料庫有瓶頸了,那麼就可以拆成賬務和交易兩個資料庫,緩解資料庫的效能瓶頸。當然,如果按照垂直拆分完畢以後,還是不能滿足效能要求,這個時候就需要進行水平拆分了。
關於水平拆分,也有一些重要的實踐原則。在做資料庫水平拆分的時候,最好一次性考慮未來十年,甚至二十年的業務的要求,要避免今天做了一個拆5張表的決定,過了兩年,發現不行,還要繼續拆成10張表,甚至20張表的情況。
重新分片是個非常複雜的工作,尤其是線上還不允許停機的情況。另外關於確定如何拆多少庫,多少表,也有一些實踐。一般拆的資料庫數量等於未來業務的峰值(TPS)除以單資料庫的容量(TPS)。這裡並不代表要一步到位,拆那麼多實際物理庫,一開始可藉助SOFAStack分庫分表中介軟體虛擬成邏輯庫,只需要少量物理庫,等到訪問量上來後,再擴容物理庫。拆的表的數量等於單表時間業務量乘以儲存時長除以單標容量上限。記住表的數量一定要一步拆到位,避免過一兩年還要折騰。
做了資料拆分後,就會遇到分散式事務的問題,需要解決分散式事務的問題,這個也是金融行業區分與別的行業的最大不同。SOFAStack分散式事務中介軟體目前支援TCC和FMT兩種樣式(這裡主要討論實踐,對於TCC和FMT兩種樣式的原理,這裡不再贅述,有興趣的可以參考之前的文章)。TCC樣式雖然編碼複雜,業務有侵入,難度較高,但勝在效能好,所以像核心系統裡面的分散式事務都是用該方案。當然,因為複雜,所以實現中有些地方需要註意。
-
業務模型要分兩步設計。因為TCC是個二階段協議,一階段try的時候需要鎖定二階段提交的資源,所以業務模型要按照這樣的思路來進行設計,當然這裡還有一些技巧,需要保證鎖的粒度足夠小,否則效能就比傳統XA樣式沒有太大優勢了。拿賬戶餘額舉例子,一般可以在資料庫表裡增加一個凍結金額欄位,需要轉錢走的時候,在try階段會增加凍結金額,表示錢已經凍住,不能挪做別的用途,保證第二階段有足夠的資金進行轉賬。因為對賬戶餘額的鎖定是一個業務上的邏輯鎖,而且邏輯鎖粒度已經最小,只需要鎖定需要轉賬的金額,全程幾乎無資料庫鎖,所以效能比較高。
-
業務資料併發控制。這個很好理解,對所有涉及金額的操作,肯定是要加鎖的,控制併發的,否則肯定會出錯的。
-
冪等控制。因為分散式環境下,非常容易出現多次呼叫的情況,為了保證業務不出錯,所有try,confirm,cancel方法都需要保證冪等。
-
允許空回滾:這個其實出現機率不是特別高,但為了保證分散式事務的一致性,必須要做這樣的控制。舉個例子來說明為什麼會出現這樣的情況。事務發起方呼叫參與者的try方法,因為網路擁塞,try請求可能沒有到達參與者。然後try方法超時,分散式事務框架判定一階段失敗,所以開始呼叫參與者的cancel方法。這個時候網路好了,而且,cancel方法的呼叫先到參與者,這個時候,參與者會進行一次空回滾(因為沒有執行過try方法,沒有鎖定任何資源),所以必須要保證這種情況下空回滾沒有問題。
-
防懸掛控制:空回滾之後,cancel方法執行成功,分散式事務框架判定這次分散式事務結束。這個時候如果之前被擁塞的try請求到達參與者,參與者執行了try方法,但這個時候分散式事務已經判定這次事務結束了,所以不會繼續推進二階段事務,這就出現二階段cancel比一階段Try先執行的情況,就造成了事務的懸掛,所以這裡要也需要業務程式碼做個控制,防止事務的懸掛。
FMT樣式的特點就是使用簡單,基本上像使用單機事務一樣,當然效能自然沒有TCC高,所以一般使用在外圍一點的系統,對效能要求不那麼高的系統上去保證分散式事務的一致性。
最後關於服務治理,這塊有很多方法可以推薦,比如說API檔案化,API檔案可以藉助開源的swagger來生成。還有對核心的服務一定要做限流保護,避免雪崩效應的發生。另外可以藉助全鏈路壓測工具識別整個架構的效能短板,做好相應的保護。
當然最重要的還是組織的問題,要保證微服務架構的有效運轉,一定要在組織層面有相應的保障。
有些金融機構在落地微服務的時候,整個組織架構還是完全的老的一套組織架構體系。按照康威定律,組織溝通方式會透過系統設計表達出來,如果組織還是原來維護單體架構的一套組織體系,那麼必然在維護髮展微服務架構的時候有很多的彆扭和不適,久而久之可能整個微服務架構又會慢慢腐壞,退化掉。
再比如很多企業提出要走中臺戰略,如果都沒有一個物體的組織去負責這個中臺,去背KPI去維護髮展這個中臺,把相應的通用能力沉澱到中臺,那麼這個中臺戰略其實是不能得到很好的貫徹及執行的,最終也達不到中臺的效果。
組織的問題是實施微服務架構一個亟需解決的問題,很多企業可以考慮慢慢過渡,循序漸進的方式去調整組織架構,去適應未來的發展。
2、新的分散式架構相容老系統
金融行業其實整體的資訊化水平是領先其他行業的,這個也造成了分散式架構轉型中需要處理好大量老系統,很多老系統用的是C語言,COBOL語言開發,甚至也有一些Python等其他語言,如何保證新分散式架構對這塊的相容性,保證整體架構升級慢慢平滑過渡,這是一個經常遇到的問題。
我們主要推薦SOFAMesh/Gateway的方案去解決。
SOFAMosn 就是一個Sidecar,它包括了中介軟體SDK的能力,包括服務註冊,熔斷限流,動態配置等。SOFAMosn 可以攔截應用的呼叫,並對相應的協議進行解析後進行代理轉發,這樣對於一些老系統,就可以使用Mesh的方案去通訊,從而實現異構語言系統之間的相互呼叫。
對於一些不方便部署Sidecar的老系統應用,還有Gateway的方案,SOFAGateway部署方案有點類似ESB,是個獨立的叢集,當然不會像ESB那樣有那麼複雜的路由能力。所有協議的相容,轉換都在Gateway完成,從而實現異構語言系統之間的通訊,當然Gateway還可以附加一些額外的能力,比如對呼叫進行QPS控制,做一些安全校驗等。
3、構建金融級容災架構
我們知道,金融行業監管對系統的容災是有一定要求的,所以容災架構成了金融企業的標配。從架構的複雜性和解決的問題看,我們推薦按照同城雙活架構,兩地三中心架構,異地多活架構和三地五中心架構的次序來慢慢推進。
對於一般金融企業,做到同城雙活或兩地三中心一般足夠了,有條件的企業可以考慮異地多活方案。
在做同城雙活方案的時候,還是有個點需要特別註意,因為同城兩個機房一般有1~3ms的延時,而一個使用者請求一般會放大為十幾個甚至幾十個SQL的資料庫訪問,那麼這些增加的延時有可能會造成一些效能問題甚至使用者根本無法使用。所以推薦在實施同城雙活架構的時候,一般最好能模擬這塊的延時,提早發現應用的一些問題,儘早最佳化,避免架構上線的時候才發現,造成一些線上問題。
要實現異地多活,一般就得考慮單元化架構了,因為異地之間200公里的延時一般至少有7~10ms,上千公里的話有30ms以上的延時,同城雙活的方案已經不能行得通了。單元化的思想主要是把業務劃分為一個個獨立的單元,讓業務呼叫儘量在單元裡面封閉,減少跨單元呼叫,這樣才能保證將一些單元部署在異地的時候不會影響線上正常執行。
當然單元化架構對業務有一定侵入,會增加開發運維的複雜性,有必要上異地多活的架構的企業可以考慮是否應用。
總結
當前,越來越多的企業已經認識到分散式架構在實現業務靈活擴充套件以及敏捷開發等方面的巨大價值,實施微服務架構的時候選擇完善、經過驗證的架構方案,中介軟體產品的選擇又是至關重要。
SOFAStack 金融級分散式架構是螞蟻金服分散式架構實踐的結晶,而且還在不斷革新中,持續助力金融機構、企業分散式架構轉型,可以在https://tech.antfin.com/sofa,瞭解更多。