天天看點

jeesz分布式架構-分布式高可用

版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。

什麼是高可用

高可用ha(high availability)是分布式系統架構設計中必須考慮的因素之一,它通常是指,通過設計減少系統不能提供服務的時間。

假設系統一直能夠提供服務,我們說系統的可用性是100%。

如果系統每運作100個時間機關,會有1個時間機關無法提供服務,我們說系統的可用性是99%。

很多公司的高可用目标是4個9,也就是99.99%,這就意味着,系統的年停機時間為8.76個小時。

如何保障系統的高可用

我們都知道,單點是系統高可用的大敵,單點往往是系統高可用最大的風險和敵人,應該盡量在系統設計的過程中避免單點。方法論上,高可用保證的原則是“叢集化”,或者叫“備援”:隻有一個單點,挂了服務會受影響;如果有備援備份,挂了還有其他backup能夠頂上。

保證系統高可用,架構設計的核心準則是:備援。

有了備援之後,還不夠,每次出現故障需要人工介入恢複勢必會增加系統的不可服務實踐。是以,又往往是通過“自動故障轉移”來實作系統的高可用。

接下來我們看下典型網際網路架構中,如何通過備援+自動故障轉移來保證系統的高可用特性。

常見的網際網路分層架構

常見網際網路分布式架構如上,分為:

(1)用戶端層:典型調用方是浏覽器browser或者手機應用app

(2)反向代理層:系統入口,反向代理

(3)站點應用層:實作核心應用邏輯,傳回html或者json

(4)服務層:如果實作了服務化,就有這一層

(5)資料-緩存層:緩存加速通路存儲

(6)資料-資料庫層:資料庫固化資料存儲

整個系統的高可用,又是通過每一層的備援+自動故障轉移來綜合實作的。

分層高可用架構實踐

【用戶端層->反向代理層】的高可用

用戶端層到反向代理層的高可用,是通過反向代理層的備援來實作的。以nginx為例:有兩台nginx,一台對線上提供服務,另一台備援以保證高可用,常見的實踐是keepalived存活探測,相同virtual ip提供服務。

自動故障轉移:當nginx挂了的時候,keepalived能夠探測到,會自動的進行故障轉移,将流量自動遷移到shadow-nginx,由于使用的是相同的virtual ip,這個切換過程對調用方是透明的。

【反向代理層->站點層】的高可用

反向代理層到站點層的高可用,是通過站點層的備援來實作的。假設反向代理層是nginx,nginx.conf裡能夠配置多個web後端,并且nginx能夠探測到多個後端的存活性。

自動故障轉移:當web-server挂了的時候,nginx能夠探測到,會自動的進行故障轉移,将流量自動遷移到其他的web-server,整個過程由nginx自動完成,對調用方是透明的。

【站點層->服務層】的高可用

站點層到服務層的高可用,是通過服務層的備援來實作的。“服務連接配接池”會建立與下遊服務多個連接配接,每次請求會“随機”選取連接配接來通路下遊服務。

自動故障轉移:當service挂了的時候,service-connection-pool能夠探測到,會自動的進行故障轉移,将流量自動遷移到其他的service,整個過程由連接配接池自動完成,對調用方是透明的(是以說rpc-client中的服務連接配接池是很重要的基礎元件)。

【服務層>緩存層】的高可用

服務層到緩存層的高可用,是通過緩存資料的備援來實作的。

緩存層的資料備援又有幾種方式:第一種是利用用戶端的封裝,service對cache進行雙讀或者雙寫。

緩存層也可以通過支援主從同步的緩存叢集來解決緩存層的高可用問題。

以redis為例,redis天然支援主從同步,redis官方也有sentinel哨兵機制,來做redis的存活性檢測。

自動故障轉移:當redis主挂了的時候,sentinel能夠探測到,會通知調用方通路新的redis,整個過程由sentinel和redis叢集配合完成,對調用方是透明的。

說完緩存的高可用,這裡要多說一句,業務對緩存并不一定有“高可用”要求,更多的對緩存的使用場景,是用來“加速資料通路”:把一部分資料放到緩存裡,如果緩存挂了或者緩存沒有命中,是可以去後端的資料庫中再取資料的。

這類允許“cache miss”的業務場景,緩存架構的建議是:

将kv緩存封裝成服務叢集,上遊設定一個代理(代理可以用叢集備援的方式保證高可用),代理的後端根據緩存通路的key水準切分成若幹個執行個體,每個執行個體的通路并不做高可用。

緩存執行個體挂了屏蔽:當有水準切分的執行個體挂掉時,代理層直接傳回cache miss,此時緩存挂掉對調用方也是透明的。key水準切分執行個體減少,不建議做re-hash,這樣容易引發緩存資料的不一緻。

【服務層>資料庫層】的高可用

大部分網際網路技術,資料庫層都用了“主從同步,讀寫分離”架構,是以資料庫層的高可用,又分為“讀庫高可用”與“寫庫高可用”兩類。

【服務層>資料庫層“讀”】的高可用

服務層到資料庫讀的高可用,是通過讀庫的備援來實作的。

既然備援了讀庫,一般來說就至少有2個從庫,“資料庫連接配接池”會建立與讀庫多個連接配接,每次請求會路由到這些讀庫。

自動故障轉移:當讀庫挂了的時候,db-connection-pool能夠探測到,會自動的進行故障轉移,将流量自動遷移到其他的讀庫,整個過程由連接配接池自動完成,對調用方是透明的(是以說dao中的資料庫連接配接池是很重要的基礎元件)。

【服務層>資料庫層“寫”】的高可用

服務層到資料庫寫的高可用,是通過寫庫的備援來實作的。

以mysql為例,可以設定兩個mysql雙主同步,一台對線上提供服務,另一台備援以保證高可用,常見的實踐是keepalived存活探測,相同virtual ip提供服務。

自動故障轉移:當寫庫挂了的時候,keepalived能夠探測到,會自動的進行故障轉移,将流量自動遷移到shadow-db-master,由于使用的是相同的virtual ip,這個切換過程對調用方是透明的。

總結

方法論上,高可用是通過備援+自動故障轉移來實作的。

整個網際網路分層系統架構的高可用,又是通過每一層的備援+自動故障轉移來綜合實作的,具體的:

(1)【用戶端層】到【反向代理層】的高可用,是通過反向代理層的備援實作的,常見實踐是keepalived + virtual ip自動故障轉移

(2)【反向代理層】到【站點層】的高可用,是通過站點層的備援實作的,常見實踐是nginx與web-server之間的存活性探測與自動故障轉移

(3)【站點層】到【服務層】的高可用,是通過服務層的備援實作的,常見實踐是通過service-connection-pool來保證自動故障轉移

(4)【服務層】到【緩存層】的高可用,是通過緩存資料的備援實作的,常見實踐是緩存用戶端雙讀雙寫,或者利用緩存叢集的主從資料同步與sentinel保活與自動故障轉移;更多的業務場景,對緩存沒有高可用要求,可以使用緩存服務化來對調用方屏蔽底層複雜性

(5)【服務層】到【資料庫“讀”】的高可用,是通過讀庫的備援實作的,常見實踐是通過db-connection-pool來保證自動故障轉移

(6)【服務層】到【資料庫“寫”】的高可用,是通過寫庫的備援實作的,常見實踐是keepalived + virtual ip自動故障轉移

來源:minglisoft.cn/technology 扣扣 2042849237