高可用解決方案:同城雙活?異地雙活?異地多活?怎麼實現?

後臺服務能夠劃分爲兩類,有狀態和無狀態。高可用對於無狀態的應用來講是比較簡單的,無狀態的應用,只須要經過F5或者任何代理的方式就能夠很好的解決。後文描述的主要是針對有狀態的服務進行分析。服務端進行狀態維護主要是經過磁盤或內存進行保存,好比MySQL數據庫,redis等內存數據庫。除了這兩種類型的維護方式,還有jvm的內存的狀態維持,但jvm的狀態生命週期一般很短。前端

高可用的一些解決方案

高可用,從發展來看,大體通過了這幾個過程:mysql

  • 冷備
  • 雙機熱備
  • 同城雙活
  • 異地雙活
  • 異地多活

在聊異地多活的時候,仍是先看一些其餘的方案,這有利於咱們理解不少設計的原因。linux

冷備redis

冷備,經過中止數據庫對外服務的能力,經過文件拷貝的方式將數據快速進行備份歸檔的操做方式。簡而言之,冷備,就是複製粘貼,在linux上經過cp命令就能夠很快完成。能夠經過人爲操做,或者定時腳本進行。有以下好處:sql

  • 簡單
  • 快速備份(相對於其餘備份方式)
  • 快速恢復。只須要將備份文件拷貝回工做目錄即完成恢復過程(亦或者修改數據庫的配置,直接將備份的目錄修改成數據庫工做目錄)。更甚,經過兩次mv命令就可瞬間完成恢復。
  • 能夠按照時間點恢復。好比,幾天前發生的拼多多優惠券漏洞被人刷掉不少錢,能夠根據前一個時間點進行還原,「挽回損失」。

以上的好處,對於之前的軟件來講,是很好的方式。可是對於現現在的不少場景,已經很差用了,由於:數據庫

  • 服務須要停機。n個9確定沒法作到了。而後,之前咱們的停機冷備是在凌晨沒有人使用的時候進行,可是如今不少的互聯網應用已是面向全球了,因此,任什麼時候候都是有人在使用的。
  • 數據丟失。若是不採起措施,那麼在完成了數據恢復後,備份時間點到還原時間內的數據會丟失。傳統的作法,是冷備還原之後,經過數據庫日誌手動恢復數據。好比經過redo日誌,更甚者,我還曾經經過業務日誌去手動回放請求恢復數據。恢復是極大的體力活,錯誤率高,恢復時間長。
  • 冷備是全量備份。全量備份會形成磁盤空間浪費,以及容量不足的問題,只能經過將備份拷貝到其餘移動設備上解決。因此,整個備份過程的時間其實更長了。想象一下天天拷貝幾個T的數據到移動硬盤上,須要多少移動硬盤和時間。而且,全量備份是沒法定製化的,好比只備份某一些表,是沒法作到的。

如何權衡冷備的利弊,是每一個業務須要考慮的。緩存

雙機熱備安全

熱備,和冷備比起來,主要的差異是不用停機,一邊備份一邊提供服務。但還原的時候仍是須要停機的。因爲咱們討論的是和存儲相關的,因此不將共享磁盤的方式看做雙機熱備。服務器

Active/Standby模式

至關於1主1從,主節點對外提供服務,從節點做爲backup。經過一些手段將數據從主節點同步到從節點,當故障發生時,將從節點設置爲工做節點。數據同步的方式能夠是偏軟件層面,也能夠是偏硬件層面的。網絡

偏軟件層面的,好比mysql的master/slave方式,經過同步binlog的方式;sqlserver的訂閱複製方式。

偏硬件層面,經過扇區和磁盤的攔截等鏡像技術,將數據拷貝到另外的磁盤。偏硬件的方式,也被叫作數據級災備;偏軟件的,被叫作應用級災備。後文談得更多的是應用級災備。

雙機互備

本質上仍是Active/Standby,只是互爲主從而已。雙機互備並不能工做於同一個業務,只是在服務器角度來看,更好的壓榨了可用的資源。好比,兩個業務分別有庫A和B,經過兩個機器P和Q進行部署。那麼對於A業務,P主Q從,對於B業務,Q主P從。總體上看起來是兩個機器互爲主備。這種架構下,讀寫分離是很好的,單寫多讀,減小衝突又提升了效率。

其餘的高可用方案還能夠參考各種數據庫的多種部署模式,好比mysql的主從、雙主多從、MHA;redis的主從,哨兵,cluster等等。

同城雙活

前面講到的幾種方案,基本都是在一個局域網內進行的。業務發展到後面,有了同城多活的方案。和前面比起來,不信任的粒度從機器轉爲了機房。這種方案能夠解決某個IDC機房總體掛掉的狀況(停電,斷網等)。

同城雙活其實和前文提到的雙機熱備沒有本質的區別,只是「距離」更遠了,基本上仍是同樣(同城專線網速仍是很快的)。雙機熱備提供了災備能力,雙機互備避免了過多的資源浪費。

在程序代碼的輔助下,有的業務還能夠作到真正的雙活,即同一個業務,雙主,同時提供讀寫,只要處理好衝突的問題便可。須要注意的是,並非全部的業務都能作到。

業界更多采用的是兩地三中心的作法。遠端的備份機房能更大的提供災備能力,能更好的抵抗地震,恐襲等狀況。雙活的機器必須部署到同城,距離更遠的城市做爲災備機房。災備機房是不對外提供服務的,只做爲備份使用,發生故障了才切流量到災備機房;或者是隻做爲數據備份。緣由主要在於:距離太遠,網絡延遲太大。如上圖,用戶流量經過負載均衡,將服務A的流量發送到IDC1,服務器集A;將服務B的流量發送到IDC2,服務器B;同時,服務器集a和b分別從A和B進行同城專線的數據同步,而且經過長距離的異地專線往IDC3進行同步。當任何一個IDC當機時,將全部流量切到同城的另外一個IDC機房,完成了failover。當城市1發生大面積故障時,好比發生地震致使IDC1和2同時中止工做,則數據在IDC3得以保全。同時,若是負載均衡仍然有效,也能夠將流量所有轉發到IDC3中。不過,此時IDC3機房的距離很是遠,網絡延遲變得很嚴重,一般用戶的體驗的會受到嚴重影響的。上圖是一種基於Master-Slave模式的兩地三中心示意圖。城市1中的兩個機房做爲1主1從,異地機房做爲從。也能夠採用同城雙主+keepalived+vip的方式,或者MHA的方式進行failover。但城市2不能(最好不要)被選擇爲Master。

異地雙活

同城雙活能夠應對大部分的災備狀況,可是碰到大面積停電,或者天然災害的時候,服務依然會中斷。對上面的兩地三中心進行改造,在異地也部署前端入口節點和應用,在城市1中止服務後將流量切到城市2,能夠在下降用戶體驗的狀況下,進行降級。但用戶的體驗降低程度很是大。

因此大多數的互聯網公司採用了異地雙活的方案。上圖是一個簡單的異地雙活的示意圖。流量通過LB後分發到兩個城市的服務器集羣中,服務器集羣只鏈接本地的數據庫集羣,只有當本地的全部數據庫集羣均不能訪問,才failover到異地的數據庫集羣中。

在這種方式下,因爲異地網絡問題,雙向同步須要花費更多的時間。更長的同步時間將會致使更加嚴重的吞吐量降低,或者出現數據衝突的狀況。吞吐量和衝突是兩個對立的問題,你須要在其中進行權衡。例如,爲了解決衝突,引入分佈式鎖/分佈式事務;爲了解決達到更高的吞吐量,利用中間狀態、錯誤重試等手段,達到最終一致性;下降衝突,將數據進行恰當的sharding,儘量在一個節點中完成整個事務。

對於一些沒法接受最終一致性的業務,餓了麼採用的是下圖的方式:對於個別一致性要求很高的應用,咱們提供了一種強一致的方案(Global Zone),Globa Zone是一種跨機房的讀寫分離機制,全部的寫操做被定向到一個 Master 機房進行,以保證一致性,讀操做能夠在每一個機房的 Slave庫執行,也能夠 bind 到 Master 機房進行,這一切都基於咱們的數據庫訪問層(DAL)完成,業務基本無感知。

也就是說,在這個區域是不能進行雙活的。採用主從而不是雙寫,天然解決了衝突的問題。

實際上,異地雙活和異地多活已經很像了,雙活的結構更爲簡單,因此在程序架構上不用作過多的考慮,只須要作傳統的限流,failover等操做便可。但其實雙活只是一個臨時的步驟,最終的目的是切換到多活。由於雙活除了有數據衝突上的問題意外,還沒法進行橫向擴展。

異地多活根據異地雙活的思路,咱們能夠畫出異地多活的一種示意圖。每一個節點的出度和入度都是4,在這種狀況下,任何節點下線都不會對業務有影響。可是,考慮到距離的問題,一次寫操做將帶來更大的時間開銷。時間開銷除了影響用戶體驗之外,還帶來了更多的數據衝突。在嚴重的數據衝突下,使用分佈式鎖的代價也更大。這將致使系統的複雜度上升,吞吐量降低。因此上圖的方案是沒法使用的。

回憶一下咱們在解決網狀網絡拓撲的時候是怎麼優化的?引入中間節點,將網狀改成星狀:改造爲上圖後,每一個城市下線都不會對數據形成影響。對於原有請求城市的流量,會被從新LoadBalance到新的節點(最好是LB到最近的城市)。爲了解決數據安全的問題,咱們只須要針對中心節點進行處理便可。可是這樣,對於中心城市的要求,比其餘城市會更高。好比恢復速度,備份完整性等,這裏暫時不展開。咱們先假定中心是徹底安全的。

若是咱們已經將異地多活的業務部署爲上圖的結構,很大程度解決了數據處處同步的問題,不過依然會存在大量的衝突,衝突的狀況能夠簡單認爲和雙活差很少。那麼還有沒有更好的方式呢?

回顧一下前文提到的餓了麼的GlobalZone方案,整體思路就是「去分佈式」,也就是說將寫的業務放到一個節點的(同城)機器上。阿里是這麼思考的:實際上我猜想不少業務也是按照上圖去實現的,好比滴滴打車業務這種,全部的業務都是按城市劃分開的。用戶、車主、目的地,他們的經緯度一般都是在同一個城市的。單個數據中心並不須要和其餘數據中心進行數據交互,只有在統計出報表的時候才須要,但報表是不太注重實時性的。那麼,在這種狀況下,全國的業務其實能夠被很好的sharding的。

可是對於電商這種複雜的場景和業務,按照前文說的方式進行sharding已經沒法知足需求了。由於業務線很是複雜,數據依賴也很是複雜,每一個數據中心相互進行數據同步的狀況無可避免。淘寶的解決方式和咱們切分微服務的方式有點相似:注意看圖中的數據同步箭頭。以交易單元爲例,屬於交易單元的業務數據,將與中心單元進行雙向同步;不屬於交易單元的業務數據,單向從中心單元同步。中心單元承擔了最複雜的業務場景,業務單元承擔了相對單一的場景。對於業務單元,能夠進行彈性伸縮和容災;對於中心單元,擴展能力較差,穩定性要求更高。能夠碰見,大部分的故障都會出如今中心單元。

按照業務進行單元切分,已經須要對代碼和架構進行完全的改造了(可能這也是爲何阿里要先從雙活再切到多活,歷時3年)。好比,業務拆分,依賴拆分,網狀改星狀,分佈式事務,緩存失效等。除了對於編碼的要求很高之外,對測試和運維也有很是大的挑戰。如此複雜的狀況,如何進行自動化覆蓋,如何進行演練,如何改造流水線。這種級別的災備,不是通常公司敢作的,投入產出也不成正比。不過仍是能夠把這種場景看成咱們的「假想敵」,去思考咱們本身的業務,將來會怎麼發展,須要作到什麼級別的災備。相對而言,餓了麼的多活方案可能更適合大多數的企業。

本文只是經過畫圖的方式進行了簡單的描述,其實異地多活是須要不少很強大的基礎能力的。好比,數據傳輸,數據校驗,數據操做層(簡化客戶端控制寫和同步的過程)等。

來源 | https://blog.dogchao.cn/?p=299
image
相關文章
相關標籤/搜索