參考:
https://www.jianshu.com/p/aff048130bed
https://www.jianshu.com/p/c25676f54308
https://www.infoq.cn/article/interview-alibaba-bixuan
異地多活架構
異地指地理位置上的不同,多活指不同地理位置上的系統都能夠提供業務服務。
判斷標准:
-
正常情況下,用戶無論訪問哪一個地點的業務系統,都能夠得到正確的業務服務。
-
某地異常時,用戶訪問其他地方正常的業務系統,能夠得到正確的業務服務。
異地多活的代價:
-
系統復雜度會有質的變化。
-
成本大大增加。
架構模式
1. 同城異區
部署在同一個城市不同區的機房,用專用網絡連接。
同城異區兩個機房距離一般就是幾十千米,網絡傳輸速度幾乎和同一個機房相同,降低了系統復雜度、成本。
這個模式無法解決極端的災難情況,例如某個城市的地震、水災,此方式是用來解決一些常規故障的,例如機房的火災、停電、空調故障。
2. 跨城異地
部署在不同城市的多個機房,距離要遠一些,例如北京和廣州。
此模式就是用來處理極端災難情況的,例如城市的地震、相鄰城市的大停電。
跨城異地主要問題就是網絡傳輸延遲,例如北京到廣州,正常情況下的RTT(Round-Trip Time 往返時延)是50毫秒,當遇到網絡波動等情況,會升到500毫秒甚至1秒,而且會有丟包問題。
物理距離必然導致數據不一致,這就得從“數據”特性來解決,如果是強一致性要求的數據(如存款余額),就無法做異地多活。
舉例,存款余額支持跨城異地多活,部署在北京和廣州,當光纜被挖斷后,會發生:
-
用戶A余額有10000,北京和廣州是一致的。
-
A在廣州機房給B轉5000,廣州余額為5000,由於網絡不通,北京此時的余額為10000。
-
A在北京發現余額還是10000,給C轉10000,由於網絡不通,廣州的余額為5000。
-
A在廣州又可以給D轉5000。
這就出事兒了,所以這類數據不會做跨城異地多活,只能用同城異區架構,因為同城的網絡環境要好很多,可以搭建多條互聯通道,成本也不會太高。
跨城異地模式適用於對數據一致性要求不高的場景,例如:
-
用戶登錄,數據不一致時重新登錄即可。
-
新聞網站,一天內新聞數據變化較少。
-
微博網站,即使丟失一點微博或評論數據也影響不大。
3. 跨國異地
部署在不同國家的多個機房。
此模式的延時就更長了,正常情況也得幾秒,無法滿足正常的業務訪問。
所以,跨國異地多活適用於:
-
為不同地區用戶提供服務
例如,亞馬遜美國是為美國用戶服務的,亞馬遜中國的賬號是無法登錄美國亞馬遜的。
-
只讀類業務
例如谷歌的搜索,不管用戶在哪個國家搜索,得到的結果基本相同,對用戶來說,跨國異地的幾秒延遲,對搜索結果沒什么影響。
跨城異地多活設計技巧
1. 保證核心業務的異地多活
思維誤區:要保證所有業務都能異地多活。
假設用戶子系統,負責注冊、登錄、用戶信息這3個業務,由於有海量用戶,所以對用戶進行分區,分配到不同數據中心,正常情況下某個用戶屬於某個主分區,並在其他分區也有備份,通過hash計算得出屬於哪個中心。
如果想要保證注冊業務多活,可能會有問題,例如,A中心注冊了用戶,數據還未同步到B中心時A宕了,為了支持多活,需要可以讓用戶到B中心重新注冊,但一個手機號只能注冊一個賬號,A恢復后就有沖突了。
如果要保證用戶信息業務多活,也會有問題,例如,A、B兩個中心在異常情況下都修改了用戶信息,如何處理沖突?
可以發現,注冊、登錄、用戶信息這3個業務都支持多活的話,是非常難的,有的問題甚至是無解的。解決的方法就是:優先實現核心業務的異地多活。
這個示例中,“登錄”才是核心業務,例如系統的日活是1000萬,每天的注冊可能是幾萬,修改用戶信息的可能還不到1萬,但登錄是1000萬,很明顯要保證登錄的異地多活。
2. 保證核心數據最終一致性
思維誤區:要保證所有數據實時同步。
由於物理上的限制,所有數據都實時同步,是一個無法達到的目標。
必須要盡量減少數據同步,只同步核心業務相關的數據。
例如上面的例子,登錄產生的token或session信息,數據量很大,實際上不需要同步到其他中心,即使丟失了重新登錄就可以了,會影響用戶體驗,但是可以接受的。
3. 采用多種手段同步數據
思維誤區:只使用存儲系統的同步功能。
存儲系統本身就有強大的同步功能,例如 mysql redis 都可以很好的實現同步,但某些場景下是無法滿足需要的,所以要使用多種手段配合,例如:
-
消息隊列
創建賬號后,將賬號數據通過消息隊列同步到其他業務中心。
-
二次讀取
例如用戶在A中心注冊了,然后訪問了B中心,此時B還沒有拿到賬號數據,為了解決這個問題,B中心在讀取本地數據失敗時,可以根據路由規則,再去A中心訪問一次。
-
回源讀取
例如session數據沒有同步,用戶在A中心登錄,B中心可以拿着 session id 到A中心請求session數據。
4. 只保證絕大部分用戶的異地多活
思維誤區:要保證業務 100% 可用。
物理規律決定了異地多活無法保證100%的業務可用。
以轉賬業務為例,在北京和上海兩個中心實現了實時轉賬的異地多活,在異常情況下會出現問題,例如用戶有一萬存款,在北京給人轉了一萬,又到上海給人轉了一萬。
所以,無法做到實時轉賬的異地多活,需要通過特殊業務受到實現。
例如,除了“實時轉賬”外,還提供“轉賬申請”業務,用戶在上海提交了轉賬請求,並不立即轉賬,而是后台異步處理,如果發現北京中心不可用,就等待重試,北京恢復后,如果發現余額不足就轉賬失敗。
這個方式犧牲了一些用戶體驗,本來一次完成的操作變為了2次,一次提交轉賬申請,另一次是確認轉賬結果。
對於用戶體驗,可以采取一些補償措施,例如:
-
公告
例如由於xxx原因導致您的不便,技術哥哥正在緊急處理等等。
-
事后補償
例如送代金券、小禮品等。
-
補充體驗
例如上面的轉賬例子,可以在轉賬結果出來后給用戶發個短信,減少用戶不時的登錄查看。
小結
三地五中心(1)
昨天科技圈最火的新聞應該是“AWS中國區光纜被挖,導致三星、小米等眾多企業服務不可用”。
又是光纜被挖,咦!?為什么是又,讓我們來一起回到過去:
- 2019.6.02:亞馬遜光纜被挖斷,國內部分地區網絡出現異常
- 2019.3.23:施工隊挖斷騰訊光纖,致騰訊旗下100多款游戲受影響,損失大了
- 2015.5.27:由於杭州市蕭山區某地光纖被挖斷,造成目前少部分用戶無法使用支付寶
我這里只是列出來了幾家大公司所涉及到的光纜被挖事故,其余還包括什么廣電光纜被挖,社保局光纜被挖就不列了,感興趣的自己去百度。
好,我們發現“公司再大,也怕施工隊”,那么這種事故能怪施工隊嗎?個人覺得不能把責任都推給施工隊,當然我們這里不討論這些,我們做為大公司,我們以后怎么預防這種現象呢?
這個我們可以來看下支付寶的解決辦法,畢竟它老人家在2015年就經歷過這種慘況了。
2018年9月20日,杭州雲棲大會ATEC主論壇現場上演了一場特別的技術秀。螞蟻金服副CTO胡喜現場模擬挖斷支付寶近一半服務器的光纜。結果只過了26秒,模擬環境中的支付寶就完全恢復了正常。
這種解決辦法就是“三地五中心”,這是一種機房架構,即在三座城市部署五個機房,一旦其中一個或兩個機房發生故障,依靠技術可以將故障城市的流量全部切換到運行正常的機房。
那么在“三地五中心”之前還存在很多其他架構,我們一一來看一下他們的特點。
災難演進
最初,我們把應用(一個非常簡單的只讀應用,比如一個顯示Hello World的網頁,不考慮數據存儲)只放在一個機器上,那么當這個服務器down機了,我們的應用便不可用了。
所以,我們考慮把我們的應用放在多個機器上,在公司單獨開辟一個機房來放置這些機器,這樣單獨某一個台機器down機了並不影響我們的應用。
但是,如果你們公司某一天停電了呢?這個時候我們就考慮在這座城市的另外一個地方在放置一個機房,這是應用就被部署在了同城的兩個機房(這個叫同城雙活)
但是,如果你們城市某一天經歷了海嘯、台風、地震等自然災害,兩個機房都不能使用了,這個時候我們就會考慮在另外一個城市再搭建一個機房來部署我們的應用,這樣我們應用的可用性就更高了(這個叫異地多活)。
好,到此為止不管出現什么樣的狀況,我們的應用基本上都可用(除非地球毀滅...)
那么我們上面考慮的應用是一個非常簡單的只讀應用,所以各個地方的應用是可以同時對外提供服務的,那么如果我們的應用涉及到數據存儲,這個時候各個地方的應用就不能同時對外提供寫入數據的服務了,因為很有可能會出現數據沖突,那么我們暫且規定只有公司內部機房里的服務器(后文我們叫主機房)可以提供寫數據服務,而同城的另外一個機房以及異地的另外一個機房只能從主機房同步數據,這樣這兩個地方的機房的功能就叫災備,因為數據會同步,所以就算主機房停電了,另外兩個機房還是可以臨時來對外提供服務的。所以現在的架構可以如下:

當主機房停電后,用戶會去請求北京備份機房,當北京備份機房也停電后,用戶會去請求上海備份機房。
好,對於這個架構,我們剛剛說只有主機房能對外提供服務,另外兩個機房都只是作為容災的備份,那么也就是說備份機房利用率不高,因為畢竟正常請求下主機房不可能老停電,所以對於備份機房能不能提高它的利用率呢?當然可以,我們可以讓北京的備份機房也去接收部分業務請求,只是這些請求可以沒那么重要,比如一些讀請求,而上海的備份機房不去接收請求,還是單純作為容災備份機器,因為如果誰都不能保證當備份機房接收業務請求會不會出現其他不可預知的問題,那么現在三個機房的角色實際上已經有些不同了:

這個就叫兩地三中心。
那么兩地三中心這種架構是目前很多銀行或大型企業正在使用的一種架構,因為國家針對銀行的災備能力做過要求,資產超過多少多少的一定要做兩地三中心架構,以保證銀行系統的穩定。
那么這種架構有沒有它的缺點呢?我們來考慮一下它的可用性高不高?可用性的意思就是這個架構處理用戶請求時夠不夠快?
我們發現這種架構,中心之間是需要數據備份的,那么對於數據備份只有兩種方式,要么異步,要么同步。
- 最大性能模式:如果是異步,表示用戶一個寫數據請求,只要在生產數據中心存儲完數據后就會直接返回結果給用戶,同時異步去備份數據,但是,如果正准備去異步備份數據的時候生產數據中心停電了~,那么這個時候還能將災備服務器暴露出去給用戶提供服務嗎?不能了,因為很有可能災備中心的數據是過時的數據。
- 最大保護模式:如果是同步,表示用戶一個寫數據請求,不僅要等待生產數據中心存儲完數據,還需要等其他災備中心備份完數據后才能返回,而且僅僅當災備中心出現問題時,因為不能完成數據的備份,所以整個架構也不能對外提供服務,這種可用性是很低的。
- 最大可用模式:這是普遍采用的方案,正常情況下使用最大保護模式,同時生產數據中心監控災備數據中心,一旦發現某一災備中心出現了問題,那么則會改為最大性能模式,這樣就保證了生產數據中心不受其他災備中心影響。
- 三寫兩同步:這是阿里之前的架構模式,意思是同城三個中心,數據備份不是發生在數據庫層面,而是應用層,當應用向數據庫去寫數據時,會同時向三個中心去寫數據,只要有兩個中心返回成功即可,這樣就算三個中心有一個中心停電了,那么並不影響整個架構的高可用,這個思路和我們前面三種是不一樣的,性能肯定會高很多。
好,我們介紹了一下兩地三中心,總結一下它的缺點:
- 災備中心利用率不高
- 生產數據中心停止運行后,災備中心中不一定有100%一模一樣的數據
- 成本高,但又無法真正實現期望的高可用能力
那么為了解決這個問題,就出現了三地五中心,雖然名字和兩地三中心類似,但提供的功能完全不同。
三地五中心是指三個城市,5個中心,三地五中心基於的概念是單元化,還得花很大篇幅來講,下一篇繼續吧。
三地五中心(2)
上篇文章我們總結了一下同城雙活、異地多活、兩地三中心等一些部署架構,那么這篇文章我來發表一下我對三地五中心的理解。
我們上篇文章講過兩地三中心這個架構,如下圖:

這種架構具備容災能力,比如生產數據中心停電了,那么可以把所有流量都切到同城災備中心或異地災備中心,那么現在的問題是假如真到了停電的那一天,你敢把所有的流量都切到災備中心去嗎?
上篇文章說了,災備中心它主要的功能是作為生產數據中心的一個備份,所以它並沒有如同生產數據中心一樣不停的在對外提供服務,那么就有問題了,災備相當於一個新人,一個一直在模仿大哥的一個新人,現在大哥受傷了,按道理是應該小弟頂上,但是小弟還是個新人,硬頂上去是不是很有可能會出錯?也就是說:
- 第一,不能保證災備中心有能力接管線上所有的用戶流量,可能剛已接收災備中心被壓垮,或者出現其他各種各樣預估不到的錯誤;
- 第二,如果生產數據中心接收了用戶的寫請求,還沒來得及同步到災備中心,這個時候停電了,這種情況下,也不能直接把用戶流量切到災備中心。
所以基於上面的分析,並不是說災備中心一定不能頂上,只是在頂上之前可能還要做很多其他的檢查和准備,這個時間是不確定的,至少不會很快...。
那么問題來了,該怎么辦?
首先對於上面列出來的兩點中的第一點,如果我們能夠讓災備中心不再僅僅只能用來做災備,還能和生產數據中心一樣正常的對外提供服務呢?如下圖:

可以看到上面的架構圖:
- 不再區分生產數據中心和災備數據中心,只有數據中心,而且數據中心之間相互備份數據,保證每個數據中心都是全量數據。
- 用戶可以在任意一個數據中心上進行讀寫操作。
好,首先我們不管這種架構能不能實現,至少它的好處是非常明顯的:
- 每個數據中心一直在對外提供服務(不是一個新手),所以當一個數據中心停電后,直接把用戶流量切到另外一個數據中心也是問題不大的。
- 用戶可以就近訪問數據中心,這樣用戶的體驗更好,並且整個架構的流量也比較平均。
優點很明顯,如果能實現就再好不過了,那么這種架構實現起來最重要的一點就是:用戶同時向不同數據中心寫入數據,數據中心雙向同步數據時,如果出現沖突該如何解決?
那么這個問題,目前阿里和螞蟻金服的解決辦法是:將用戶按某一個規則進行分組,每組用戶寫入數據時只能寫入到指定的數據中心,相當於用戶與數據中心綁定在一起了,這樣保證了數據中心在雙向同步之前數據是不會沖突的,因為按用戶分組了,不同用戶的數據不會沖突。
當然思路非常簡單,但是實現起來肯定是非常麻煩的,但是思路肯定是可以的,阿里也用實踐證明了,我們先把上面的架構稍微完善一下:

用戶使用網站時,由運營商網絡或CDN選擇最近的機房,機房內部署一個負載均衡,由這個負載均衡最終判斷用戶屬於機房(前文中的數據中心),也就是可能出現,用戶在注冊時在北京,那么他的uid就和北京某個機房綁定了,那么當這個用戶在上海使用時,會由上海的負載均衡按照用戶分組規則將請求轉發到北京綁定的那個機房去(當然並不是所有請求,比如讀請求肯定可以直接在上海機房進行讀取,所以具體的實現都要看業務怎么實現了,以及負載均衡具體的配置,這里只是把最簡單易懂的思路說一下)。
所以,我們現在可以
- 假設北京機房1應用程序或數據庫對應的機器停電了,那么我們可以調整負載均衡是原本屬於這個機房的用戶流量轉移到機房2去,注意這里不要有疑問,將用戶進行分組是為了防止用戶同時寫兩個數據庫發生沖突,那么現在機房1里其實已經不能寫入數據了,所以將流量遷移到機房2是沒有問題的。
- 假設北京機房1整個停電了,那么可以通過運營商網絡或CDN將流量遷移到北京機房2。
- 假設北京停電了,那么一樣可以將流量遷移到上海。
這個架構中最重要的其實就是用戶分組,所以包括我們的應用程序、數據庫負載均衡、數據庫分表等等都需要按用戶進行分組,我們要保證針對同一個用戶的請求與操作都在同一個機房內,不去跨機房,這樣才是最快的,這就是單元化。
那么上面這個架構實際上就是一個高級版的“兩地三中心”,只是這種單元化架構我們可以任意去擴展(只要你足夠有錢,因為搭一套全配置的數據中心是需要很高成本的),比如你在上海在增加一個數據中心,在杭州也增加一個,那么就如下圖:

這就叫三地五中心。
專訪阿里巴巴畢玄:異地多活數據中心項目的來龍去脈
大數據時代,數據中心的異地容災變得非常重要。在去年雙十一之前,阿里巴巴上線了數據中心異地雙活項目。InfoQ 就該項目采訪了阿里巴巴的林昊(花名畢玄)。
畢玄是阿里巴巴技術保障部的研究員,負責性能容量架構。數據中心異地多活項目就是他主導的。
InfoQ:首先請介紹一下數據中心異地多活這個項目。
畢玄:這個項目在我們內部的另外一個名字叫做單元化,雙活是它的第二個階段,多活是第三個階段。所以我們把這個項目分成三年來實現。所謂異地多活,故名思義,就是在不同地點的數據中心起多個我們的交易,並且每個地點的那個交易都是用來支撐流量的。
InfoQ:當時為什么要做這件事呢?
畢玄:其實我們大概在 2009 還是 2010 年左右的時候,就開始嘗試在異地去做一個數據中心,把我們的業務放過去。更早之前,我們做過同城,就是在同一個城市建多個數據中心,應用部署在多個數據中心里面。同城的好處就是,如果同城的任何一個機房掛掉了,另外一個機房都可以接管。
做到這個以后,我們就在想,異地是不是也能做到這樣?
整個業界傳統的做法,異地是用來做一個冷備份的,等這邊另外一個城市全部掛掉了,才會切過去。我們當時也是按照這個方式去嘗試的,嘗試了一年左右,我們覺得冷備的方向對我們來講有兩個問題:第一個問題是成本太高。我們需要備份全站,而整個阿里巴巴網站,包括淘寶、天貓、聚划算等等,所有加起來,是一個非常大的量,備份成本非常高。第二個問題是,冷備並不是一直在跑流量的,所以有個問題,一旦真的出問題了,未必敢切過去。因為不知道切過去到底能不能起來,而且整個冷備恢復起來要花多長時間,也不敢保證。因此在嘗試之后,我們發現這個方向對我們而言並不好。
那為什么我們最后下定決心去做異地多活呢?
最關鍵的原因是,我們在 2013 年左右碰到了幾個問題。首先,阿里巴巴的機房不僅僅給電商用,我們有電商,有物流,有雲,有大數據,所有業務共用機房。隨着各種業務規模的不斷增長,單個城市可能很難容納下我們,所以我們面臨的問題是,一定需要去不同的城市建設我們的數據中心。其次是我們的伸縮規模的問題。整個淘寶的量,交易量不斷攀升,每年的雙十一大家都看到了,增長非常快。而我們的架構更多還是在 2009 年以前確定的一套架構,要不斷的加機器,這套架構會面臨風險。
如果能夠做到異地部署,就可以把伸縮規模縮小。雖然原來就是一套巨大的分布式應用,但是其實可以認為是一個集群,然后不斷的加機器。但是在這種情況下,隨着不斷加機器,最終在整個分布式體系中,一定會有一個點是會出現風險的,會再次到達瓶頸,那時就無法解決了。
這兩個問題讓我們下定決心去做異地多活這個項目。
為什么我們之前那么糾結呢?因為整個業界還沒有可供參考的異地多活實現,這就意味着我們必須完全靠自己摸索。而且相對來講,它的風險以及周期可能也是比較大的。
InfoQ:這個項目具體是怎樣部署的?
畢玄:以去年雙十一為例,當時我們在杭州有一個數據中心,在另外一個城市還有個數據中心,一共是兩個,分別承擔 50% 用戶的流量。就是有 50% 的用戶會進入杭州,另外 50% 會進入到另外一個城市。當用戶進入以后,比如說在淘寶上看商品,瀏覽商品,搜索、下單、放進購物車等等操作,還包括寫數據庫,就都是在所進入的那個數據中心中完成的,而不需要跨數據中心。
InfoQ:這樣的優勢是?
畢玄:異地部署,從整個業界的做法上來講,主要有幾家公司,比如 Google、Facebook,這兩家是比較典型的,Google 做到了全球多個數據中心,都是多活的。但是 Google 具體怎么做的,也沒有多少人了解。另外一家就是 Facebook,我們相對更了解一些,Facebook 在做多個數據中心時,比如說美國和歐洲兩個數據中心,確實都在支撐流量。但是歐洲的用戶有可能需要訪問美國的數據中心,當出現這種狀況時,整個用戶體驗不是很好。
國內的情況,我們知道的像銀行,還有其他一些行業,傾向於做異地災備。銀行一般都會有兩地,一個地方是熱點,另一個地方是冷備。當遇到故障時,就沒有辦法做出決定,到底要不要切到災備數據中心,他們會碰到我們以前摸索時所面對的問題,就是不確定切換過程到底要多久,災備中心到底多久才能把流量接管起來。而且接管以后,整個功能是不是都正常,也可能無法確定。
剛才也提到過,冷備的話,我們要備份全站,成本是非常高的。
如果每個地點都是活的,這些數據中心就可以實時承擔流量,任何一點出問題,都可以直接切掉,由另外一點直接接管。相對冷備而言,這是一套可以運行的模式,而且風險非常低。
InfoQ:不過這樣的話,平時要預留出很多流量才能保證?
畢玄:沒錯。因為在異地或同城建多個數據中心時,建設過程中一定都會保有一定的冗余量。因為要考慮其他數據中心出現故障時加以接管。不過隨着數據中心建設的增多,這個成本是可以控制的。如果有兩個異地的數據中心,冗余量可能是一倍,因為要接管全量。但是如果有三個數據中心,互為備份,就不需要冗余兩倍了。
InfoQ:這個項目挑戰還是比較大的。您可以介紹一下研發過程中遇到的挑戰嗎?又是怎樣克服的?
畢玄:對於我們來講,異地項目最大的挑戰是延時。跨城市一定會有延時的問題。在中國范圍內,延時可能在一百毫秒以內。
看起來單次好像沒什么,但是像淘寶是個很大的分布式系統,一次頁面的展現,背后的交互次數可能在一兩百次。如果這一兩百次全部是跨城市做的,整個響應時間會增加很多,所以延時帶來的挑戰非常大。
在解決挑戰的過程中,我們會面臨更細節的一些問題。怎樣降低延時的影響,我們能想到的最簡單、最好的辦法,就是讓操作全部在同一機房內完成,那就不存在延時的挑戰了。所以最關鍵的問題,就是怎樣讓所有操作在一個機房內完成。這就是單元化。
為什么叫單元化,而沒有叫其他名字呢?原因在於,要在異地部署我們的網站,首先要做一個決定。比如說,冷備是把整個站全部備過去,這樣可以確保可以全部接管。但是多活的情況下,要考慮成本,所以不能部署全站。
整個淘寶的業務非常豐富,其實有很多非交易類型的應用,這些功能可能大家平時用的不算很多。但對我們來講,又是不能缺失的。這部分流量可能相對很小。如果這些應用也全國到處部署,冗余量就太大了。所以我們需要在異地部署的是流量會爆發式增長的,流量很大的那部分。雖然有冗余,但是因為流量會爆發式增長,成本比較好平衡。異地部署,我們要在成本之間找到一個平衡點。所以我們決定在異地只部署跟買家交易相關的核心業務,確保一個買家在淘寶上瀏覽商品,一直到買完東西的全過程都可以完成。
其他一些功能就會缺失,所以我們在異地部署的並非全站,而是一組業務,這組業務就成為單元。比如說我們現在做的就是交易單元。
這時淘寶會面臨一個比 Google、Facebook 等公司更大的一個挑戰。像 Facebook 目前做的全球化數據中心,因為 Facebook 更多的是用戶和用戶之間發消息,屬於社交領域。但淘寶是電商領域,對數據的一致性要求非常高,延時要求也非常高。
還有個更大的挑戰,那就是淘寶的數據。如果要把用戶操作封閉在一個單元內完成,最關鍵的是數據。跟冷備相比,異地多活最大的風險在於,它的數據會同時在多個地方寫,冷備則不存在數據會寫錯的問題。如果多個地方在寫同一行數據,那就沒有辦法判斷哪條數據是正確的。在某個點,必須確保單行的數據在一個地方寫,絕對不能在多個地方寫。
為了做到這一點,必須確定數據的維度。如果數據只有一個維度,就像 Facebook 的數據,可以認為只有一個緯度,就是用戶。但是像淘寶,如果要在淘寶上買一個東西,除了用戶本身的信息以外,還會看到所有商品的數據、所有賣家的數據,面對的是買家、賣家和商品三個維度。這時就必須做出一個選擇,到底用哪個維度作為我們唯一的一個封閉的維度。
單元化時,走向異地的就是買家的核心鏈路,所以我們選擇了買家這個維度。但是這樣自然會帶來一個問題,因為我們有三個維度的數據,當操作賣家商品數據時,就無法封閉了,因為這時一定會出現需要集中到一個點去寫的現象。
從我們的角度看,目前實現整個單元化項目最大的幾個難點是:
第一個是路由的一致性。因為我們是按買家維度來切分數據的,就是數據會封閉在不同的單元里。這時就要確保,這個買家相關的數據在寫的時候,一定是要寫在那個單元里,而不能在另外一個單元,否則就會出現同一行數據在兩個地方寫的現象。所以這時一定要保證,一個用戶進到淘寶,要通過一個路由規則來決定這個用戶去哪里。這個用戶進來以后,到了前端的一組 Web 頁面,而 Web 頁面背后還要訪問很多后端服務,服務又要訪問數據庫,所以最關鍵的是要保障這個用戶從進來一直到訪問服務,到訪問數據庫,全鏈路的路由規則都是完全一致的。如果說某個用戶本來應該進 A 城市的數據中心,但是卻因為路由錯誤,進入了 B 城市,那看到的數據就是錯的了。造成的結果,可能是用戶看到的購買列表是空的,這是不能接受的。所以如何保障路由的一致性,非常關鍵。
第二個是挑戰是數據的延時問題。因為是異地部署,我們需要同步賣家的數據、商品的數據。如果同步的延時太長,就會影響用戶體驗。我們能接受的范圍是有限的,如果是 10 秒、30 秒,用戶就會感知到。比如說賣家改了一個價格,改了一個庫存,而用戶隔了很久才看到,這對買家和賣家都是傷害。所以我們能接受的延時必須要做到一秒內,即在全國的范圍內,都必須做到一秒內把數據同步完。當時所有的開源方案,或者公開的方案,包括 MySQL 自己的主備等,其實都不可能做到一秒內,所以數據延時是我們當時面臨的第二個挑戰。
第三個挑戰,在所有的異地項目中,雖然冷備成本很高,多活可以降低成本,但是為什么大家更喜歡冷備,而不喜歡多活呢?因為數據的正確性很難保證。數據在多點同時寫的時候,一定不能寫錯。因為數據故障跟業務故障還不一樣,跟應用層故障不一樣。如果應用出故障了,可能就是用戶不能訪問。但是如果數據寫錯了,對用戶來說,就徹底亂了。而且這個故障是無法恢復的,因為無法確定到底那里寫的才是對的。所以在所有的異地多活項目中,最重要的是保障某個點寫進去的數據一定是正確的。這是最大的挑戰,也是我們在設計整個方案中的第一原則。業務這一層出故障我們都可以接受,但是不能接受數據故障。
還有一個挑戰是數據的一致性。多個單元之間一定會有數據同步。一方面,每個單元都需要賣家的數據、商品的數據;另一方面,我們的單元不是全量業務,那一定會有業務需要這個單元,比如說買家在這個單元下了一筆定單,而其他業務有可能也是需要這筆數據,否則可能操作不了,所以需要同步該數據。所以怎樣確保每個單元之間的商品、賣家的數據是一致的,然后買家數據中心和單元是一致的,這是非常關鍵的。
這幾個挑戰可能是整個異地多活項目中最復雜的。另外還有一點,淘寶目前還是一個高速發展的業務,在這樣的過程中,去做一次比較純技術的改造,怎樣確保對業務的影響最小,也是一個挑戰。
InfoQ:要將延時控制在 1 秒之內,網絡和硬件方面都有哪些工作?
畢玄:如果網絡帶寬質量不好,1 秒是不可能做到的。我們在每個城市的數據中心之間,會以一個點做成自己的骨干網,所以可以保障不同城市之間的網絡質量。但是要保證到 1 秒,還必須自己再去做東西來實現數據的同步,這個很關鍵。這個東西現在也在阿里雲上有開放了。
InfoQ:異地多活其實也是實現高可用。阿里技術保障的梁耀斌(花名追源)老師會在4 月23 日~25 日的 QCon 北京 2015 大會上分享《你的網站是高可用的嗎?》,因為當時的題目和內容也是您參與擬定的。您可以先談一下其中的一些標准嗎?
畢玄:其實每家比較大的互聯網公司,每年可能都會對外公開說,我們今年的可用性做到了多少,比如 4 個 9 或者 5 個 9。但是每家公司對可用性的定義可能並不一樣。比如說,有的公司可能認為業務響應時間超過多少才叫可用性損失,而其他公司可能認為業務受損多少就是可用性損失。
我們希望大家以后有一個統一的定義,這樣就比較好比較了。我們發現,真正所有做到高可用的網站,最重要的一點是故障恢復時間的控制。因為出故障是不可避免的,整個網站一定會出現各種各樣的故障,關鍵是在故障出現以后,應對能力有多強,恢復時間可以做到多短。追源會在 QCon 上分享,我們在應對不同類型的故障時,我們是怎樣去恢復的,恢復時間能控制到多短,為什么能控制到那么短。在不同的技術能力,以及不同的技術設施的情況下,能做到的恢復時間可能是不一樣的,所以我們會定義一個在不同的技術能力和不同的技術設施的情況下,恢復時間的標准。如果恢復時間能控制得非常好,可能整個故障控制力就非常強。舉個例子,比如淘寶因為能夠做到異地多活,並且流量是可以隨時切換的,所以對於我們來講,如果一地出現故障,不管是什么原因,最容易的解決方案,就是把這一地的流量全部切走。這樣可以把故障控制在一分鍾以內,整個可用性是非常高的。
關於系統的容災能力,國家也有一個標准,最重要的一點就是故障的恢復時間。如果大家都以故障恢復時間控制到哪個級別來衡量,那所有網站就有了一套標准。
螞蟻金服三地五中心異地多活解決方案是基於完全自主研發的SOFA金融分布式架構及OceanBase關系數據庫。
在該方案中,SOFA分布式架構能夠承受高並發交易,並確保資金安全;同時,在系統擴展、容災恢復、更新發布時做到數據無損,且服務持續可用。OceanBase分布式關系數據庫具備數據強一致、高可用、高性能、在線擴展、高度兼容SQL標准和主流關系數據庫、低成本等特點;可在低成本的通用硬件上,進行在線水平擴展,並創造了4200萬次/秒處理峰值的紀錄