高可用的技術(shù):跨機房部署、同城雙活、異地多活究竟怎么玩兒?
在互聯(lián)網(wǎng)大廠,有個普遍的現(xiàn)象:某種程度上,只要是比較重要的系統(tǒng),都需要考慮系統(tǒng)的容災(zāi)問題。
通過實施容災(zāi)方案,將系統(tǒng)部署兩套或者多套,并且這套系統(tǒng)或者多套系統(tǒng)可以部署到不同的機房,如果其中一套系統(tǒng)出現(xiàn)故障導(dǎo)致不可用,則可以迅速切換到另一套系統(tǒng),提供7*24小時不間斷服務(wù)。
一、容災(zāi)介紹
同城雙活和異地多活都是典型的系統(tǒng)容災(zāi)部署方案,對于企業(yè)來說,尤其是大型互聯(lián)網(wǎng)公司,比較重要的系統(tǒng)一般都會做容災(zāi),采用同城雙活,甚至異地多活的架構(gòu)方案進行部署。
對于同城雙活和異地多活來說,都是容災(zāi)的不同方案,它們對技術(shù)、部署成本、運維成本、網(wǎng)絡(luò)帶寬、網(wǎng)絡(luò)穩(wěn)定性等的要求都不一樣。
多多少少都會增加部署的復(fù)雜度和部署成本,但是,容災(zāi)在某套系統(tǒng)出現(xiàn)故障時,能夠迅速切換到另一套系統(tǒng),保證系統(tǒng)的高可用。
二、宕機問題
企業(yè)的核心系統(tǒng)和比較重要的系統(tǒng)應(yīng)該也必須考慮容災(zāi)問題,這里的容災(zāi)主要是通過部署兩套或者多套系統(tǒng)實現(xiàn),這兩套或者多套系統(tǒng)一般是部署在不同的機房,避免只部署一套系統(tǒng)或者在同一機房部署多套系統(tǒng)出現(xiàn)宕機事故。
在實際場景中,哪怕我們部署了兩套或者多套系統(tǒng),但是這些系統(tǒng)是部署在同一個機房內(nèi),此時系統(tǒng)的可用性是受限于機房的可用性,如果機房出現(xiàn)網(wǎng)絡(luò)不通或者其他事故,就會影響到系統(tǒng)的可用性,甚至造成系統(tǒng)長時間宕機。
這種系統(tǒng)事故不是人為造成的,但是如果不考慮容災(zāi)問題,或者容災(zāi)問題考慮不充分,將兩套或者多套系統(tǒng)部署在同一個機房內(nèi)就可能出現(xiàn)這種問題。
舉個例子,如果已經(jīng)考慮到容災(zāi)的問題,只是將兩套或者多套系統(tǒng)部署在同一個機房中,如果這個機房的網(wǎng)絡(luò)或者服務(wù)器出現(xiàn)了故障,機房發(fā)生了火災(zāi),甚至機房所在的城市發(fā)生了地震、海嘯、洪水等不可抗力的災(zāi)難時,哪怕部署在同一個機房內(nèi)的多套系統(tǒng)之間實現(xiàn)的可用性再高,整個系統(tǒng)也是不可用的。
三、跨機房部署
跨機房部署,顧名思義就是將兩套或者多套系統(tǒng)部署在多個機房,跨機房部署其實并沒有想象中的那么簡單和美好,實際上,將兩套或者多套系統(tǒng)部署在多個機房是有一定的復(fù)雜度和挑戰(zhàn)的。
以數(shù)據(jù)庫為例,假設(shè)目前有兩個機房,分別為機房A和機房B,數(shù)據(jù)庫主庫A和從庫B都在A機房,那么B機房的應(yīng)用如何讀取到數(shù)據(jù)呢?此時,總體上有兩種方案:跨機房讀取數(shù)據(jù)和本機房內(nèi)讀取數(shù)據(jù)。
3.1 跨機房讀取數(shù)據(jù)
如果是跨機房讀取數(shù)據(jù)的話,B機房中的應(yīng)用就會跨機房讀取A機房的數(shù)據(jù),如下圖所示。
圖片
可以看到,此時B機房的應(yīng)用會跨機房讀取A機房的數(shù)據(jù)。
3.2 本機房內(nèi)讀取數(shù)據(jù)
如果是本機房內(nèi)讀取數(shù)據(jù),則可以在B機房中部署一個從庫,B機房中的從庫跨機房同步A機房的數(shù)據(jù),隨后,B機房的應(yīng)用讀取本機房中從庫的數(shù)據(jù),如下圖所示。
圖片
可以看到,在B機房中部署一個從庫,跨機房同步A機房數(shù)據(jù),B機房中的應(yīng)用就可以讀取本機房內(nèi)從庫的數(shù)據(jù)。
4.3 跨機房問題
無論是B機房內(nèi)的應(yīng)用跨機房讀取數(shù)據(jù),還是讀取本機房內(nèi)的數(shù)據(jù),都會存在跨機房數(shù)據(jù)的傳輸問題,跨機房讀取數(shù)據(jù)是B機房的應(yīng)用直接讀取A機房數(shù)據(jù)時,產(chǎn)生的跨機房傳輸數(shù)據(jù)問題。
而讀取本機房內(nèi)的數(shù)據(jù),是數(shù)據(jù)庫同步數(shù)據(jù)產(chǎn)生的跨機房傳輸數(shù)據(jù)問題。只要涉及到跨機房傳輸數(shù)據(jù)的問題,就會對機房之間的數(shù)據(jù)延遲有比較高的要求。
根據(jù)以往的經(jīng)驗來說,機房之間的數(shù)據(jù)延遲,與機房之間的物理距離有直接的關(guān)系,這里,給大家列舉幾個經(jīng)驗數(shù)據(jù)。
(1)同城雙機房專線延遲
一般情況下,同城雙機房專線延遲在1ms~3ms之間。
假設(shè)接口的響應(yīng)時間要求控制在200ms之內(nèi),而一次接口調(diào)用可能會觸發(fā)一些RPC服務(wù)或者其他服務(wù),如果是同城雙機房專線網(wǎng)絡(luò)良好的情況下,跨機房調(diào)用服務(wù),接口的響應(yīng)時間可能會增加幾毫秒,再有就是跨機房讀寫數(shù)據(jù),接口響應(yīng)時間增加幾毫秒,都是可以接受的。
但是,如果跨機房調(diào)用服務(wù),讀寫數(shù)據(jù)的次數(shù)比較多,來來回回耗費了幾十、上百毫秒,此時就不能接受了。
(2)國內(nèi)異地雙機房專線延遲
一般情況下,就國內(nèi)的異地雙機房專線延遲在50ms之內(nèi)。
具體還是要根據(jù)機房之前的物理距離來確定,比如北京到上海的專線延遲一般在30ms左右,而北京到廣州的專線延遲在50ms左右,機房的物理距離不同,延遲也不盡相同。
在異地雙機房專線的數(shù)據(jù)延遲影響下,如果要將接口的響應(yīng)時間控制在200ms之內(nèi),就要避免頻繁的跨機房調(diào)用服務(wù)和跨機房讀寫數(shù)據(jù)。
(3)國際異地雙機房專線延遲
一般情況下,國際異地雙機房專線的網(wǎng)絡(luò)延遲會比國內(nèi)異地雙機房專線延遲高,一般會在100ms~200ms。
在這種場景下,就需要避免跨機房進行數(shù)據(jù)的同步處理,只考慮異步同步跨機房數(shù)據(jù)。
四、同城雙活
同城雙活方案是將系統(tǒng)部署在同一個城市的不同機房中,這種方案能夠做到機房級別的容災(zāi),而不能做到城市級別的容災(zāi)。
在同城雙活方案中,同城的兩個機房中,每個機房會承擔(dān)一部分流量,涉及到服務(wù)的調(diào)用和數(shù)據(jù)讀寫時,盡量在本機房內(nèi)完成,如果是RPC調(diào)用,不同機房的RPC服務(wù)可以向注冊中心注冊不同的服務(wù)分組,不同機房的RPC消費者只訂閱本機房內(nèi)的服務(wù)分組。
這樣就可以實現(xiàn)RPC調(diào)用盡量發(fā)生在本機房內(nèi)。如果是寫數(shù)據(jù),則可以向一個機房寫數(shù)據(jù),而實時同步到另一個機房,如下圖所示。
圖片
可以看到,在實施同城雙活方案時,主庫可以部署在A機房中,A機房和B機房的數(shù)據(jù)都寫到A機房的主庫中,主庫會將數(shù)據(jù)同步到A、B機房的從庫。一旦A機房發(fā)生故障,可以將B機房的從庫提升為主庫,B機房繼續(xù)對外提供服務(wù)。
在A機房和B機房同時部署了緩存,緩存中的數(shù)據(jù)可以由本機房內(nèi)的從庫進行同步,也可以由本機房的服務(wù)進行讀寫。
如果本機房的緩存中沒有需要的數(shù)據(jù),就到本機房的從庫中進行查詢,當(dāng)然這里查詢數(shù)據(jù)庫的操作,要考慮緩存擊穿、穿透和雪崩的問題。
當(dāng)更新數(shù)據(jù)時,可以同時更新每個機房的數(shù)據(jù)。
不同機房的RPC服務(wù)可以向注冊中心注冊不同的服務(wù)分組,不同機房的RPC消費者只訂閱本機房內(nèi)的服務(wù)分組,這樣就可以實現(xiàn)RPC調(diào)用盡量發(fā)生在本機房內(nèi)。
五、異地多活
一般情況下,系統(tǒng)做同城雙活容災(zāi)方案就夠了,如果系統(tǒng)的業(yè)務(wù)發(fā)展到了淘寶級別,就需要考慮異地多活了。
如果是采用異地多活方案,機房之間的距離不宜太近,部署到同一個城市就不太合適了,所以,起碼是要做跨城市級別的異地多活,甚至是跨國異地多活,在這種場景下,顯然不能跨機房寫數(shù)據(jù)了。
在異地多活場景下,數(shù)據(jù)同步可以采取主從同步+消息異步復(fù)制的方式來同步,也就是說,對于像MySQL、Redis這種數(shù)據(jù),可以采用主從復(fù)制的方式,由一個機房同步到另一個機房。像緩存數(shù)據(jù)和一些NoSQL數(shù)據(jù)庫的數(shù)據(jù),可以使用消息異步復(fù)制的方式來同步數(shù)據(jù),如下圖所示。
圖片
可以看到,在異地多活場景下,對于像MySQL、Redis這種數(shù)據(jù),可以采用主從復(fù)制的方式,由一個機房同步到另一個機房。像緩存數(shù)據(jù)和一些NoSQL數(shù)據(jù)庫的數(shù)據(jù),可以使用消息異步復(fù)制的方式來同步數(shù)據(jù)。
在異地多活場景下,還有一些要注意的問題:讀取用戶相關(guān)的數(shù)據(jù)時,盡量保證在同一個機房內(nèi)處理,這時,就需要對用戶的數(shù)據(jù)做分片處理,對同一個用戶數(shù)據(jù)的讀寫操作,路由到同一個機房內(nèi)。
對數(shù)據(jù)的讀取和服務(wù)的調(diào)用,也盡量在同一個機房內(nèi)完成。
另外,還有一種場景是在電商業(yè)務(wù)中,用戶相關(guān)的數(shù)據(jù),例如用戶查詢自己的訂單數(shù)據(jù)時,用戶自己的訂單數(shù)據(jù)與用戶數(shù)據(jù)在同一個機房內(nèi),但是訂單數(shù)據(jù)中的店鋪數(shù)據(jù)和商家的一些基本信息,可能就存儲在另外的機房了。
此時,對于服務(wù)的調(diào)用和數(shù)據(jù)的讀取,優(yōu)先保證在本機房內(nèi)進行,如果不得已發(fā)生跨機房讀取數(shù)據(jù)的操作,有一定的延遲,也可以接受。
還有一點需要說明的是:如果同城雙活架構(gòu)方案能夠滿足需求,就不要輕易嘗試異地多活架構(gòu),實際上,異地多活架構(gòu)過于復(fù)雜,很少有公司能夠搭建出真正的異地多活架構(gòu)。