持續可用和快速容災切換的能力,是技術人員追求的極致目標。在架構設計中,容災設計強調的是系統對外界環境影響具備快速響應能力,節點級別的快速恢復能力,保障系統的持續可用。
去年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性能優化這些成為架構師必備的知識體系。