持續(xù)可用和快速容災(zāi)切換的能力,是技術(shù)人員追求的極致目標。在架構(gòu)設(shè)計中,容災(zāi)設(shè)計強調(diào)的是系統(tǒng)對外界環(huán)境影響具備快速響應(yīng)能力,節(jié)點級別的快速恢復(fù)能力,保障系統(tǒng)的持續(xù)可用。
去年12月18日,全球架構(gòu)師峰會上,阿里巴巴高級系統(tǒng)工程師曾歡(善衡)結(jié)合互聯(lián)網(wǎng)金融業(yè)務(wù)及系統(tǒng)特性,分享了在支付寶系統(tǒng)架構(gòu)演進中,每個階段的高可用和容災(zāi)能力建設(shè)的解決思路。
企業(yè)服務(wù)、云計算、移動互聯(lián)網(wǎng)領(lǐng)域中,高可用的分布式技術(shù)為支撐平臺正常運作提供著關(guān)鍵性的技術(shù)支撐。從用戶角度,特別是作為主要收入來源的企業(yè)用戶的角度出發(fā),保證業(yè)務(wù)處理的正確性和服務(wù)不中斷(高可用性)是支撐用戶信心的重要來源。高性能,高可用的分布式架構(gòu)就成了訪問量高峰期時,網(wǎng)站得以成功運維的關(guān)鍵。
在當今信息時代,數(shù)據(jù)和信息逐漸成為各行各業(yè)的業(yè)務(wù)基礎(chǔ)和命脈。當企業(yè)因為信息化帶來快捷的服務(wù)決策和方便管理時,也必須面對著數(shù)據(jù)丟失的危險。
容災(zāi)系統(tǒng),作為為計算機信息系統(tǒng)提供的一個能應(yīng)付各種災(zāi)難的環(huán)境,尤其是計算機犯罪、計算機病毒、掉電、網(wǎng)絡(luò)/通信失敗、硬件/軟件錯誤和人為操作錯誤等人為災(zāi)難時,容災(zāi)系統(tǒng)將保證用戶數(shù)據(jù)的安全性(數(shù)據(jù)容災(zāi)),甚至,一個更加完善的容災(zāi)系統(tǒng),還能提供不間斷的應(yīng)用服務(wù)(應(yīng)用容災(zāi))??梢哉f,容災(zāi)系統(tǒng)是數(shù)據(jù)存儲備份的最高層次。
每年的“雙11”、“雙12”都是全球購物者的狂歡節(jié),今年的雙11有232個國家參與進來,成為名副其實的全球瘋狂購物節(jié)。11月11日,全天的交易額達到912.17億元,其中在移動端交易額占比68%今年每秒的交易峰值達到14萬筆,螞蟻金服旗下的支付寶交易峰值達到8.59萬筆/秒,這一系列的數(shù)字,考驗的是支付寶背后強大的IT支持能力。而持續(xù)可用和快速容災(zāi)切換的能力,是支付寶技術(shù)人員追求的極致目標。
在架構(gòu)設(shè)計中,作為系統(tǒng)高可用性技術(shù)的重要組成部分,容災(zāi)設(shè)計強調(diào)的是系統(tǒng)對外界環(huán)境影響具備快速響應(yīng)能力,尤其是當發(fā)生災(zāi)難性事件并對IDC節(jié)點產(chǎn)生影響時,能夠具備節(jié)點級別的快速恢復(fù)能力,保障系統(tǒng)的持續(xù)可用。2015年12月18日,年度高端技術(shù)盛會:“全球架構(gòu)師峰會——ArchSummit”在北京國際會議中心隆重召開,會上,阿里巴巴高級系統(tǒng)工程師:善衡(曾歡)結(jié)合互聯(lián)網(wǎng)金融業(yè)務(wù)及系統(tǒng)特性,分享了在支付寶系統(tǒng)架構(gòu)演進中,每個階段的高可用和容災(zāi)能力建設(shè)的解決思路。本文由其演講內(nèi)容整理而成。
支付寶的系統(tǒng)架構(gòu),其發(fā)展歷程可以分為清晰的3個階段,每一個階段都有自己獨特的特點和架構(gòu)上相應(yīng)的痛點。在每一個階段的發(fā)展過程中,支付寶的技術(shù)人員針對不同的問題進行諸多的思考,在解決這些問題的過程中也做了諸多的嘗試。
在此階段,支付寶的系統(tǒng)架構(gòu)相對比較簡化,如圖1所示,通過商用LB讓用戶的流量進到入口網(wǎng)關(guān)系統(tǒng),支付寶的系統(tǒng)服務(wù)暴露也通過商用設(shè)備掛在VIP下,每個提供服務(wù)的應(yīng)用機器通過VIP來進行負載均衡。早期支付寶的核心系統(tǒng)庫都在一個數(shù)據(jù)庫上(后期拆為多個數(shù)據(jù)庫),即每個核心系統(tǒng)都只用單獨的數(shù)據(jù)庫。在這樣一個“物理上多機房,邏輯上單機房”的架構(gòu)背后,每天的業(yè)務(wù)量僅僅為數(shù)十萬級,應(yīng)用系統(tǒng)也只有數(shù)十個,容災(zāi)能力相對較低:例如單應(yīng)用出現(xiàn)問題時無法及時有效地切換、主機和備用機進行切換時,一定程度上會導(dǎo)致業(yè)務(wù)中斷,甚至有時會有不得不進行停機維護的情況,使得整個系統(tǒng)面對數(shù)據(jù)故障時顯得十分被動。
隨著業(yè)務(wù)量的不斷增長,該架構(gòu)發(fā)展到2011年,出現(xiàn)了一些比較典型的問題。如下圖所示:由于系統(tǒng)內(nèi)部使用的都是LB設(shè)備,商用LB的瓶頸就尤其明顯,由于業(yè)務(wù)的發(fā)展累計,VIP及其上面發(fā)布的服務(wù)越堆越多,設(shè)備如果出現(xiàn)抖動或者宕機會對業(yè)務(wù)造成嚴重影響,這即是架構(gòu)上的單點。第二個問題就是數(shù)據(jù)庫的單點瓶頸。隨著業(yè)務(wù)量的不斷增加,單一的核心數(shù)據(jù)庫一旦出現(xiàn)異常,比如硬件故障、負載異常等等,進而會導(dǎo)致整個核心鏈路上的業(yè)務(wù)都不可用。
如何消除系統(tǒng)架構(gòu)當中存在的單點問題,優(yōu)雅解決未來1-3年之間業(yè)務(wù)量增長(數(shù)百萬級/天)和機器數(shù)量增長(數(shù)百個系統(tǒng)),是首先要解決的問題,于是帶來了下一代架構(gòu)革新。
鑒于第一階段支付寶碰到的這些痛點,在第二個階段,它將邏輯上的單個機房拆分成為多個機房,通過把硬負載轉(zhuǎn)換成為軟負載,以實現(xiàn)分布式的服務(wù)調(diào)用,如下圖所示。下圖為基于常見的消費者和生產(chǎn)者模型來構(gòu)建的業(yè)務(wù)模型,其中配置中心負責(zé)服務(wù)注冊以及對應(yīng)服務(wù)提供方可用狀態(tài)變化的通知,從而將信息實時推送到消費方的訂閱關(guān)系上。值得注意的是,支付寶對原有架構(gòu)做了一個較大的改進:它將普通的一體化配置中心分拆成兩個模塊,一個Session模塊,用于管理消費者和生產(chǎn)者的長連接保持;一個Data模塊,用于注冊服務(wù)時存儲相關(guān)。通過這兩個模塊的深度解耦,進一步提高整個配置中心的性能。
除此之外,支付寶還做了數(shù)據(jù)的水平擴展。其實早在2011年之前,支付寶就已經(jīng)開始從事此項工作,根據(jù)用戶的UID,將一個交易庫水平拆分為多個庫,如下圖所示。在此期間,需要解決的問題就是“對應(yīng)用透明”,如何通過“應(yīng)用無感知”的方式進行用戶數(shù)據(jù)庫的拆分,是水平擴展實施時首先要考慮的;其次,如何通過一個數(shù)據(jù)中間件來管理數(shù)據(jù)分片的規(guī)則,也是數(shù)據(jù)水平擴展過程中的關(guān)鍵問題。
通過上述兩個比較典型的優(yōu)化,支付寶的整個系統(tǒng)架構(gòu)如圖5所示。從應(yīng)用層面上來說每個機房都是一個節(jié)點;從數(shù)據(jù)層面上,每個機房有特定的幾個數(shù)據(jù)分片在里面。在部署模式上,當支付寶擴張到3個或4個機房的時候,需要全局考慮數(shù)據(jù)分片部署,每個機房都有可能不可用,這些備庫們應(yīng)當分散到不同的多個機房里面,從而達到多機房備災(zāi)的目的。
這種多機房多活的第二代架構(gòu)體系,其優(yōu)勢在于:
進行了數(shù)據(jù)的水平拆分,從而理論上可以無限擴展數(shù)據(jù)/資源;
應(yīng)用多機房獨立部署,不再存在單個機房影響整體的情況;
服務(wù)調(diào)用機房內(nèi)隔離,通過軟負載的方式去做機房內(nèi)的服務(wù)本地化,不再去依賴另一個機房內(nèi)相同的服務(wù);
相較上一個階段具有更高、更可靠的可用性。
雖然在此過程中自然解決了上述的單點問題,但仍存在一個問題沒有解決。即數(shù)據(jù)庫日常維護時,或因為硬件的故障導(dǎo)致數(shù)據(jù)庫宕機時,支付寶需要進行主備切換,在此過程中業(yè)務(wù)是有損的狀態(tài)。一般情況下當IDC出現(xiàn)問題的時候,工程師們會通過前端的流量管控系統(tǒng)先把用戶的流量從出現(xiàn)異常的機房切換到正常的機房中,然后進行數(shù)據(jù)庫的主備切換,即將備用負載替換主用負載。
在這個過程中,有兩個比較大的痛點:
主備切換時數(shù)據(jù)“一致性”的問題,即主備切換時,如何在把影響時間降至最低的情況下,保證數(shù)據(jù)不被丟失,完完整整地拷貝至備用數(shù)據(jù)庫。
主備切換時數(shù)據(jù)存取不可用導(dǎo)致的業(yè)務(wù)暫停問題。
一旦數(shù)據(jù)庫發(fā)生故障,我們需要進行主備切換時,因為切換過程中的數(shù)據(jù)不可寫,部分用戶操作后的狀態(tài)不對,對用戶來說是會擔(dān)心的。為了解決這個問題,我們制定了一個Failover方案。該方案主要通過業(yè)務(wù)層進行改造,例如針對流水型的業(yè)務(wù)數(shù)據(jù),我們是這么來做的:正常進行數(shù)據(jù)流量存取的時候,只有主庫提供路線服務(wù),主庫和備庫之間進行正常的數(shù)據(jù)同步,但是Failover庫不進行數(shù)據(jù)同步,正常狀態(tài)下對業(yè)務(wù)系統(tǒng)不可見。即正常情況下,沒有數(shù)據(jù)流經(jīng)過Failover庫,而且Failover庫是空的,沒有任何歷史數(shù)據(jù),如下圖所示:
一旦故障發(fā)生,主庫發(fā)生宕機,支付寶人員將通過容災(zāi)切換將所有數(shù)據(jù)的讀寫放置在FailOver數(shù)據(jù)層中進行。因為是實時流水型的數(shù)據(jù),所以不會對歷史數(shù)據(jù)產(chǎn)生任何依賴和影響。切換完成后,整個核心鏈路上的業(yè)務(wù)就已經(jīng)全面恢復(fù)起來了。通過這種方式,使得支付寶可以將數(shù)據(jù)庫在短短5分鐘內(nèi)進行切換,一旦故障解除,隨時可以將數(shù)據(jù)讀寫重新切換到主存儲庫上來。
FailOver方案上線后,支付寶基本上所有的核心業(yè)務(wù)都基于此進行了方案改造,并針對不同的業(yè)務(wù)(不僅限于應(yīng)用層)都會有不同的FailOver方案。現(xiàn)在,支付寶在原有的方案基礎(chǔ)上再多準備一個Failover數(shù)據(jù)庫(如圖8中藍色圖形所示),與之前提到的容災(zāi)設(shè)計一樣,如果需要進一步保證Failover庫的可用性,還可以增加Failover庫的備庫。此外Failover庫需要與主庫分開,可以與主庫、備庫都不放在同一個機房。
通過“多機房多活”的架構(gòu)改造以及FailOver方案的實施,滿以為未來三年都無需為IDC資源去發(fā)愁的支付寶研發(fā)團隊,在順利支撐完2012年的“雙11”,為下一年做規(guī)劃時卻發(fā)現(xiàn)夢想破滅了。因為他們遇到了嚴峻的新問題:
DB連接數(shù)不夠。由于一個機房中的應(yīng)用系統(tǒng)就是一個節(jié)點,沒有分片的概念,僅僅只有數(shù)據(jù)的分片。用戶進入任意應(yīng)用節(jié)點時,系統(tǒng)需要根據(jù)用戶的UID分片查用戶應(yīng)該去往哪個數(shù)據(jù)庫,這時候每個應(yīng)用節(jié)點都會與所有數(shù)據(jù)庫節(jié)點保持連接。而傳統(tǒng)關(guān)系型數(shù)據(jù)庫的連接數(shù)是十分寶貴的,當支付寶面對不斷增長的用戶擴容需求時,因為DB連接數(shù)資源無法繼續(xù)擴充,導(dǎo)致應(yīng)用也不能繼續(xù)擴容了,不僅無法滿足日常增長需求,更別提“雙11”這樣短時間爆發(fā)式增長的用戶需求。
城市IDC資源限制問題。2012年夏天,杭州經(jīng)歷了長時間高溫天氣,由于機房運行的耗電較高,市政為了緩解電力供應(yīng)壓力,下達了一紙通文,隨時可能關(guān)閉掉支付寶的某些機房供電。
機房間高流量問題。由于一個業(yè)務(wù)請求與后端數(shù)據(jù)讀取之間的比例為1:N(其中N可能是幾十甚至上百),在“雙11”高流量的沖擊下,跨機房的流量會變得非常的大,因此對于網(wǎng)絡(luò)帶寬和網(wǎng)絡(luò)質(zhì)量也有著非常高的要求。
跨IDC網(wǎng)絡(luò)延時問題。由于業(yè)務(wù)請求和后端數(shù)據(jù)讀取1:N配比問題,導(dǎo)致同城機房之間距離稍微遠一些,就會產(chǎn)生1、2毫秒的同城機房延時,被擴大后就會成為困擾用戶的網(wǎng)絡(luò)延時問題。
新的問題進而帶來對新一代架構(gòu)的要求:
徹底解決DB連接數(shù)的問題。
徹底解決IDC資源限制的問題。需要支付寶走出杭州,不能單單在杭州進行機房的擴張和建設(shè)。
保證業(yè)務(wù)的連續(xù)性。去減少故障發(fā)生的時候?qū)τ谟脩舻拇驍_、對于業(yè)務(wù)的中斷。
藍綠發(fā)布。在日常發(fā)布時,會通過線下的發(fā)布測試,預(yù)發(fā)布,最終到線上的發(fā)布過程。線上發(fā)布通常采用的是金絲雀模式,應(yīng)用分成多組進行發(fā)布,每一組的用戶不固定,可能會影響到大部分乃至全站的用戶。因此支付寶團隊希望日常發(fā)布時,能夠最小限度影響用戶(可能是1%甚至1‰),新代碼上線之后最小力度來驗證新代碼符合預(yù)期。因此需要一種新的發(fā)布方式來支持。
高可用-異地多活。對于支付寶來說,傳統(tǒng)的“兩地三中心”要求:機房分屬兩個不同地區(qū),同城當中兩個機房是“雙活”,即活躍的主機房,異地機房通過復(fù)制數(shù)據(jù)來做“冷備”,即備用機房。若同城兩個機房都出現(xiàn)問題,一旦需要切換異地機房,由于不知道異地冷備機房運行起來是什么情況,因此很難決策。支付寶希望異地的機房也能實時進行流量的讀寫,以便數(shù)據(jù)流量可以來回切換,而不用擔(dān)心在切換后無法知道數(shù)據(jù)將是什么狀態(tài)。
單元化?;谏鲜鰩讉€問題的思考,支付寶走到了單元化的一步。如圖9所示,傳統(tǒng)的服務(wù)化架構(gòu)下每一次調(diào)用服務(wù)時,系統(tǒng)都會隨機選擇一臺機器或一個節(jié)點完成整次的調(diào)用。而單元化之后支付寶可以把任何一個節(jié)點固定到一個單獨的單元內(nèi),即固定的節(jié)點對應(yīng)一條固定的鏈路,再基于數(shù)據(jù)分片的方法完成將節(jié)點“單元化”的設(shè)置。
單元化的核心思想包括核心剝離以及長尾獨立。核心剝離指的是將核心業(yè)務(wù)進行剝離;將業(yè)務(wù)數(shù)據(jù)按照UserID進行拆分,從而實現(xiàn)多機房部署;在此基礎(chǔ)上將每一個機房的調(diào)用進行封閉式設(shè)置;每一個單元中的業(yè)務(wù)數(shù)據(jù)無需和其它單元進行同步。長尾獨立則針對非核心的應(yīng)用,這些業(yè)務(wù)數(shù)據(jù)并不按照UID進行拆分,核心業(yè)務(wù)并不依賴于長尾應(yīng)用。
支付寶單元化架構(gòu)實現(xiàn)的主要思想有兩點,如下圖所示:
數(shù)據(jù)水平拆分,即將所有線上核心業(yè)務(wù)分離開來。由于核心業(yè)務(wù)集合都能按照用戶ID去做水平切片,支付寶團隊將數(shù)據(jù)切片后按照機房進行分布,然后通過循序漸進的方式逐步將每個單元之間的調(diào)用完整地封閉掉。每一個單元的數(shù)據(jù)都是經(jīng)過分片的數(shù)據(jù),不需和其它單元進行同步。
上層單元化改造,即將歷史的、不能拆分的業(yè)務(wù)獨立出來。2013年,支付寶實現(xiàn)了兩個單元:單元A放置核心業(yè)務(wù),例如核心鏈路的支付、交易等;單元B放置無法拆分的歷史業(yè)務(wù),例如某些不重要的業(yè)務(wù)等。
支付寶單元化架構(gòu)于2013年完成,幫助支付寶順利支撐過了2013年的“雙11”。而2014年~2015年,支付寶一直在嘗試解決異地延時的問題:即如果不去對全局數(shù)據(jù)進行分割或是本地化的話,當把業(yè)務(wù)單元搬到異地時,由于每一次業(yè)務(wù)的發(fā)生基本上都會依賴全局數(shù)據(jù),且會對應(yīng)多次數(shù)據(jù)訪問,而每一次數(shù)據(jù)訪問都會產(chǎn)生異地所帶來的延時,積少成多,時間延遲就會達到秒級,用戶體驗大幅度下降。基于這個問題的考慮,支付寶研發(fā)團隊做了一個很大的決定:他們引入了單元C,通過將無法拆分的全量數(shù)據(jù)進行全局復(fù)制(異地機房之間的復(fù)制),以便于支撐核心業(yè)務(wù)本地調(diào)用,進而實現(xiàn)讀寫分離,將跨城市的調(diào)用減少到最小力度。如下圖所示。
由于數(shù)據(jù)的寫入操作會在每一個數(shù)據(jù)單元上進行,而單元C的數(shù)據(jù)讀取是要求全量的,所以進行這一項改造的時候需要底層的支持,從而解決架構(gòu)改造時數(shù)據(jù)一致性和時效性的問題。為了解決這個問題,支付寶團隊提出了兩種解決方案:
基于DB同步的數(shù)據(jù)復(fù)制。針對某些對于延時并非十分敏感的業(yè)務(wù),單就基于主備同步來做數(shù)據(jù)的同步。
基于消息系統(tǒng)的數(shù)據(jù)復(fù)制。由于異地數(shù)據(jù)同步比較耗時,對于延時非常敏感的業(yè)務(wù)來說,支付寶基于可靠的消息系統(tǒng)做一個數(shù)據(jù)復(fù)制(內(nèi)部稱為數(shù)據(jù)總線),通過它將上層基于應(yīng)用去做數(shù)據(jù)的復(fù)制,大概時間位于毫秒級。底層DB主備同步同時進行。
通過本地化調(diào)用,支付寶有效地解決了DB連接數(shù)問題、機房間流量限制問題、跨IDC的延時問題;通過異地的單元部署以及不斷的容災(zāi)演練和數(shù)據(jù)切換,支付寶有效地解決了城市IDC資源限制和異地IDC容災(zāi)問題。另外還有一個訴求——“藍綠發(fā)布”,支付寶是這么實現(xiàn)的。
如下圖所示,藍綠發(fā)布即每個單元里面分為一個Blue組和一個Green組,日常模式下兩個組各承擔(dān)50%的用戶流量;發(fā)布前將Green組中的50%流量移到Blue組中,然后對Green進行兩批無序發(fā)布;新代碼發(fā)布上去后,將Blue組中的流量先切換1%~2%到Green組中進行驗證,以最大程度減少對用戶的打擾,驗證完畢后,再逐步將100%的流量全部切換至新的Green組,重復(fù)前面的步驟發(fā)布Blue組,驗證完畢后切回每個組各50%流量的日常模式。
至此,支付寶單元化全局架構(gòu)如下圖所示。每一個機房單元中有單元A和單元C,單元A中按邏輯分為了兩個組,單元C之間進行全局的數(shù)據(jù)復(fù)制;每個單元中部署了一套分布式的容災(zāi)管控系統(tǒng),使得支付寶能在單個機房故障的時候去做更加快速的應(yīng)對。
通過單元化的系統(tǒng)配置,使得支付寶整個系統(tǒng)架構(gòu)具有很強的高可用性和容災(zāi)能力。具體來說有三點:
更靈活的流量管控,可以實現(xiàn)以更小的力度和更快的速度來進行數(shù)據(jù)切換。
自定義化的數(shù)據(jù)流量分配。由于每一個數(shù)據(jù)單元需要多少資源、需要支撐多少交易量可以前期確定,因此支付寶可以按照實際的需求量進行單元維度的擴展。
快速恢復(fù)的容災(zāi)能力。通過單元化之后,不僅使得數(shù)據(jù)單元內(nèi)Blue組和Green組之間可以切換流量,再向上一個級別,單元和單元之間、機房和機房之間、同城內(nèi)數(shù)據(jù)中心之間甚至城市和城市之間也可以自如地進行故障發(fā)生時的應(yīng)急切換。不僅使得支付寶實現(xiàn)了“異地多活”的架構(gòu)能力,更使其順利經(jīng)過了2015年“雙11”的洗禮。