1. 程式人生 > >支付寶架構師眼裡的高可用與容災架構演進

支付寶架構師眼裡的高可用與容災架構演進

持續可用和快速容災切換的能力,是技術人員追求的極致目標。在架構設計中,容災設計強調的是系統對外界環境影響具備快速響應能力,節點級別的快速恢復能力,保障系統的持續可用。

去年12月18日,全球架構師峰會上,阿里巴巴高階系統工程師曾歡(善衡)結合網際網路金融業務及系統特性,分享了在支付寶系統架構演進中,每個階段的高可用和容災能力建設的解決思路。

高可用和容災架構的意義

企業服務、雲端計算、移動網際網路領域中,高可用的分散式技術為支撐平臺正常運作提供著關鍵性的技術支撐。從使用者角度,特別是作為主要收入來源的企業使用者的角度出發,保證業務處理的正確性和服務不中斷(高可用性)是支撐使用者信心的重要來源。高效能,高可用的分散式架構就成了訪問量高峰期時,網站得以成功運維的關鍵。

在當今資訊時代,資料和資訊逐漸成為各行各業的業務基礎和命脈。當企業因為資訊化帶來快捷的服務決策和方便管理時,也必須面對著資料丟失的危險。

容災系統,作為為計算機資訊系統提供的一個能應付各種災難的環境,尤其是計算機犯罪、計算機病毒、掉電、網路/通訊失敗、硬體/軟體錯誤和人為操作錯誤等人為災難時,容災系統將保證使用者資料的安全性(資料容災),甚至,一個更加完善的容災系統,還能提供不間斷的應用服務(應用容災)。可以說,容災系統是資料儲存備份的最高層次。

每年的“雙11”、“雙12”都是全球購物者的狂歡節,今年的雙11有232個國家參與進來,成為名副其實的全球瘋狂購物節。11月11日,全天的交易額達到912.17億元,其中在移動端交易額佔比68%今年每秒的交易峰值達到14萬筆,螞蟻金服旗下的支付寶交易峰值達到8.59萬筆/秒,這一系列的數字,考驗的是支付寶背後強大的IT支援能力。而持續可用和快速容災切換的能力,是支付寶技術人員追求的極致目標。

在架構設計中,作為系統高可用性技術的重要組成部分,容災設計強調的是系統對外界環境影響具備快速響應能力,尤其是當發生災難性事件並對IDC節點產生影響時,能夠具備節點級別的快速恢復能力,保障系統的持續可用。2015年12月18日,年度高階技術盛會:“全球架構師峰會——ArchSummit”在北京國際會議中心隆重召開,會上,阿里巴巴高階系統工程師:善衡(曾歡)結合網際網路金融業務及系統特性,分享了在支付寶系統架構演進中,每個階段的高可用和容災能力建設的解決思路。本文由其演講內容整理而成。

支付寶的系統架構,其發展歷程可以分為清晰的3個階段,每一個階段都有自己獨特的特點和架構上相應的痛點。在每一個階段的發展過程中,支付寶的技術人員針對不同的問題進行諸多的思考,在解決這些問題的過程中也做了諸多的嘗試。

純真:童年時期2004年~2011年

在此階段,支付寶的系統架構相對比較簡化,如圖1所示,通過商用LB讓使用者的流量進到入口網關係統,支付寶的系統服務暴露也通過商用裝置掛在VIP下,每個提供服務的應用機器通過VIP來進行負載均衡。早期支付寶的核心繫統庫都在一個數據庫上(後期拆為多個數據庫),即每個核心系統都只用單獨的資料庫。在這樣一個“物理上多機房,邏輯上單機房”的架構背後,每天的業務量僅僅為數十萬級,應用系統也只有數十個,容災能力相對較低:例如單應用出現問題時無法及時有效地切換、主機和備用機進行切換時,一定程度上會導致業務中斷,甚至有時會有不得不進行停機維護的情況,使得整個系統面對資料故障時顯得十分被動。

隨著業務量的不斷增長,該架構發展到2011年,出現了一些比較典型的問題。如下圖所示:由於系統內部使用的都是LB裝置,商用LB的瓶頸就尤其明顯,由於業務的發展累計,VIP及其上面釋出的服務越堆越多,裝置如果出現抖動或者宕機會對業務造成嚴重影響,這即是架構上的單點。第二個問題就是資料庫的單點瓶頸。隨著業務量的不斷增加,單一的核心資料庫一旦出現異常,比如硬體故障、負載異常等等,進而會導致整個核心鏈路上的業務都不可用。

如何消除系統架構當中存在的單點問題,優雅解決未來1-3年之間業務量增長(數百萬級/天)和機器數量增長(數百個系統),是首先要解決的問題,於是帶來了下一代架構革新。

懵懂:少年時期2011年~2012年

鑑於第一階段支付寶碰到的這些痛點,在第二個階段,它將邏輯上的單個機房拆分成為多個機房,通過把硬負載轉換成為軟負載,以實現分散式的服務呼叫,如下圖所示。下圖為基於常見的消費者和生產者模型來構建的業務模型,其中配置中心負責服務註冊以及對應服務提供方可用狀態變化的通知,從而將資訊實時推送到消費方的訂閱關係上。值得注意的是,支付寶對原有架構做了一個較大的改進:它將普通的一體化配置中心分拆成兩個模組,一個Session模組,用於管理消費者和生產者的長連線保持;一個Data模組,用於註冊服務時儲存相關。通過這兩個模組的深度解耦,進一步提高整個配置中心的效能。

除此之外,支付寶還做了資料的水平擴充套件。其實早在2011年之前,支付寶就已經開始從事此項工作,根據使用者的UID,將一個交易庫水平拆分為多個庫,如下圖所示。在此期間,需要解決的問題就是“對應用透明”,如何通過“應用無感知”的方式進行使用者資料庫的拆分,是水平擴充套件實施時首先要考慮的;其次,如何通過一個數據中介軟體來管理資料分片的規則,也是資料水平擴充套件過程中的關鍵問題。

通過上述兩個比較典型的優化,支付寶的整個系統架構如圖5所示。從應用層面上來說每個機房都是一個節點;從資料層面上,每個機房有特定的幾個資料分片在裡面。在部署模式上,當支付寶擴張到3個或4個機房的時候,需要全域性考慮資料分片部署,每個機房都有可能不可用,這些備庫們應當分散到不同的多個機房裡面,從而達到多機房備災的目的。

這種多機房多活的第二代架構體系,其優勢在於:

1.進行了資料的水平拆分,從而理論上可以無限擴充套件資料/資源;

2.應用多機房獨立部署,不再存在單個機房影響整體的情況;

3.服務呼叫機房內隔離,通過軟負載的方式去做機房內的服務本地化,不再去依賴另一個機房內相同的服務;

4.相較上一個階段具有更高、更可靠的可用性。

雖然在此過程中自然解決了上述的單點問題,但仍存在一個問題沒有解決。即資料庫日常維護時,或因為硬體的故障導致資料庫宕機時,支付寶需要進行主備切換,在此過程中業務是有損的狀態。一般情況下當IDC出現問題的時候,工程師們會通過前端的流量管控系統先把使用者的流量從出現異常的機房切換到正常的機房中,然後進行資料庫的主備切換,即將備用負載替換主用負載。

在這個過程中,有兩個比較大的痛點:

1.主備切換時資料“一致性”的問題,即主備切換時,如何在把影響時間降至最低的情況下,保證資料不被丟失,完完整整地拷貝至備用資料庫。

2.主備切換時資料存取不可用導致的業務暫停問題。

一旦資料庫發生故障,我們需要進行主備切換時,因為切換過程中的資料不可寫,部分使用者操作後的狀態不對,對使用者來說是會擔心的。為了解決這個問題,我們制定了一個Failover方案。該方案主要通過業務層進行改造,例如針對流水型的業務資料,我們是這麼來做的:正常進行資料流量存取的時候,只有主庫提供路線服務,主庫和備庫之間進行正常的資料同步,但是Failover庫不進行資料同步,正常狀態下對業務系統不可見。即正常情況下,沒有資料流經過Failover庫,而且Failover庫是空的,沒有任何歷史資料,如下圖所示:

一旦故障發生,主庫發生宕機,支付寶人員將通過容災切換將所有資料的讀寫放置在FailOver資料層中進行。因為是實時流水型的資料,所以不會對歷史資料產生任何依賴和影響。切換完成後,整個核心鏈路上的業務就已經全面恢復起來了。通過這種方式,使得支付寶可以將資料庫在短短5分鐘內進行切換,一旦故障解除,隨時可以將資料讀寫重新切換到主儲存庫上來。

FailOver方案上線後,支付寶基本上所有的核心業務都基於此進行了方案改造,並針對不同的業務(不僅限於應用層)都會有不同的FailOver方案。現在,支付寶在原有的方案基礎上再多準備一個Failover資料庫(如圖8中藍色圖形所示),與之前提到的容災設計一樣,如果需要進一步保證Failover庫的可用性,還可以增加Failover庫的備庫。此外Failover庫需要與主庫分開,可以與主庫、備庫都不放在同一個機房。

成熟:青年時期2012年~2015年

通過“多機房多活”的架構改造以及FailOver方案的實施,滿以為未來三年都無需為IDC資源去發愁的支付寶研發團隊,在順利支撐完2012年的“雙11”,為下一年做規劃時卻發現夢想破滅了。因為他們遇到了嚴峻的新問題:

1.DB連線數不夠。由於一個機房中的應用系統就是一個節點,沒有分片的概念,僅僅只有資料的分片。使用者進入任意應用節點時,系統需要根據使用者的UID分片查使用者應該去往哪個資料庫,這時候每個應用節點都會與所有資料庫節點保持連線。而傳統關係型資料庫的連線數是十分寶貴的,當支付寶面對不斷增長的使用者擴容需求時,因為DB連線數資源無法繼續擴充,導致應用也不能繼續擴容了,不僅無法滿足日常增長需求,更別提“雙11”這樣短時間爆發式增長的使用者需求。

2.城市IDC資源限制問題。2012年夏天,杭州經歷了長時間高溫天氣,由於機房執行的耗電較高,市政為了緩解電力供應壓力,下達了一紙通文,隨時可能關閉掉支付寶的某些機房供電。

3.機房間高流量問題。由於一個業務請求與後端資料讀取之間的比例為1:N(其中N可能是幾十甚至上百),在“雙11”高流量的衝擊下,跨機房的流量會變得非常的大,因此對於網路頻寬和網路質量也有著非常高的要求。

4.跨IDC網路延時問題。由於業務請求和後端資料讀取1:N配比問題,導致同城機房之間距離稍微遠一些,就會產生1、2毫秒的同城機房延時,被擴大後就會成為困擾使用者的網路延時問題。

新的問題進而帶來對新一代架構的要求:

1.徹底解決DB連線數的問題。

2.徹底解決IDC資源限制的問題。需要支付寶走出杭州,不能單單在杭州進行機房的擴張和建設。

3.保證業務的連續性。去減少故障發生的時候對於使用者的打擾、對於業務的中斷。

4.藍綠髮布。在日常釋出時,會通過線下的釋出測試,預釋出,最終到線上的釋出過程。線上釋出通常採用的是金絲雀模式,應用分成多組進行釋出,每一組的使用者不固定,可能會影響到大部分乃至全站的使用者。因此支付寶團隊希望日常釋出時,能夠最小限度影響使用者(可能是1%甚至1‰),新程式碼上線之後最小力度來驗證新程式碼符合預期。因此需要一種新的釋出方式來支援。

5.高可用-異地多活。對於支付寶來說,傳統的“兩地三中心”要求:機房分屬兩個不同地區,同城當中兩個機房是“雙活”,即活躍的主機房,異地機房通過複製資料來做“冷備”,即備用機房。若同城兩個機房都出現問題,一旦需要切換異地機房,由於不知道異地冷備機房執行起來是什麼情況,因此很難決策。支付寶希望異地的機房也能實時進行流量的讀寫,以便資料流量可以來回切換,而不用擔心在切換後無法知道資料將是什麼狀態。

6.    單元化。基於上述幾個問題的思考,支付寶走到了單元化的一步。如圖9所示,傳統的服務化架構下每一次呼叫服務時,系統都會隨機選擇一臺機器或一個節點完成整次的呼叫。而單元化之後支付寶可以把任何一個節點固定到一個單獨的單元內,即固定的節點對應一條固定的鏈路,再基於資料分片的方法完成將節點“單元化”的設定。

單元化的核心思想包括核心剝離以及長尾獨立。核心剝離指的是將核心業務進行剝離;將業務資料按照UserID進行拆分,從而實現多機房部署;在此基礎上將每一個機房的呼叫進行封閉式設定;每一個單元中的業務資料無需和其它單元進行同步。長尾獨立則針對非核心的應用,這些業務資料並不按照UID進行拆分,核心業務並不依賴於長尾應用。

支付寶單元化架構實現的主要思想有兩點,如下圖所示:

資料水平拆分,即將所有線上核心業務分離開來。由於核心業務集合都能按照使用者ID去做水平切片,支付寶團隊將資料切片後按照機房進行分佈,然後通過循序漸進的方式逐步將每個單元之間的呼叫完整地封閉掉。每一個單元的資料都是經過分片的資料,不需和其它單元進行同步。

上層單元化改造,即將歷史的、不能拆分的業務獨立出來。2013年,支付寶實現了兩個單元:單元A放置核心業務,例如核心鏈路的支付、交易等;單元B放置無法拆分的歷史業務,例如某些不重要的業務等。

支付寶單元化架構於2013年完成,幫助支付寶順利支撐過了2013年的“雙11”。而2014年~2015年,支付寶一直在嘗試解決異地延時的問題:即如果不去對全域性資料進行分割或是本地化的話,當把業務單元搬到異地時,由於每一次業務的發生基本上都會依賴全域性資料,且會對應多次資料訪問,而每一次資料訪問都會產生異地所帶來的延時,積少成多,時間延遲就會達到秒級,使用者體驗大幅度下降。基於這個問題的考慮,支付寶研發團隊做了一個很大的決定:他們引入了單元C,通過將無法拆分的全量資料進行全域性複製(異地機房之間的複製),以便於支撐核心業務本地呼叫,進而實現讀寫分離,將跨城市的呼叫減少到最小力度。如下圖所示。

由於資料的寫入操作會在每一個數據單元上進行,而單元C的資料讀取是要求全量的,所以進行這一項改造的時候需要底層的支援,從而解決架構改造時資料一致性和時效性的問題。為了解決這個問題,支付寶團隊提出了兩種解決方案:

1.基於DB同步的資料複製。針對某些對於延時並非十分敏感的業務,單就基於主備同步來做資料的同步。

2.基於訊息系統的資料複製。由於異地資料同步比較耗時,對於延時非常敏感的業務來說,支付寶基於可靠的訊息系統做一個數據複製(內部稱為資料匯流排),通過它將上層基於應用去做資料的複製,大概時間位於毫秒級。底層DB主備同步同時進行。

通過本地化呼叫,支付寶有效地解決了DB連線數問題、機房間流量限制問題、跨IDC的延時問題;通過異地的單元部署以及不斷的容災演練和資料切換,支付寶有效地解決了城市IDC資源限制和異地IDC容災問題。另外還有一個訴求——“藍綠髮布”,支付寶是這麼實現的。

如下圖所示,藍綠髮布即每個單元裡面分為一個Blue組和一個Green組,日常模式下兩個組各承擔50%的使用者流量;釋出前將Green組中的50%流量移到Blue組中,然後對Green進行兩批無序釋出;新程式碼釋出上去後,將Blue組中的流量先切換1%~2%到Green組中進行驗證,以最大程度減少對使用者的打擾,驗證完畢後,再逐步將100%的流量全部切換至新的Green組,重複前面的步驟釋出Blue組,驗證完畢後切回每個組各50%流量的日常模式。

至此,支付寶單元化全域性架構如下圖所示。每一個機房單元中有單元A和單元C,單元A中按邏輯分為了兩個組,單元C之間進行全域性的資料複製;每個單元中部署了一套分散式的容災管控系統,使得支付寶能在單個機房故障的時候去做更加快速的應對。

總結

通過單元化的系統配置,使得支付寶整個系統架構具有很強的高可用性和容災能力。具體來說有三點:

1.更靈活的流量管控,可以實現以更小的力度和更快的速度來進行資料切換。

2.自定義化的資料流量分配。由於每一個數據單元需要多少資源、需要支撐多少交易量可以前期確定,因此支付寶可以按照實際的需求量進行單元維度的擴充套件。

3.快速恢復的容災能力。通過單元化之後,不僅使得資料單元內Blue組和Green組之間可以切換流量,再向上一個級別,單元和單元之間、機房和機房之間、同城內資料中心之間甚至城市和城市之間也可以自如地進行故障發生時的應急切換。在這裡順便給大家推薦一個架構交流群:617434785,裡面會分享一些資深架構師錄製的視訊錄影:有Spring,MyBatis,Netty原始碼分析,高併發、高效能、分散式、微服務架構的原理,JVM效能優化這些成為架構師必備的知識體系。