什麼是系統架構的高可用?需要從哪些方面去提高系統的高可用?

低調的牛肉


高可用性(HA),顧名思義,就是儘可能地減少系統不能提供服務的時間;如果一個系統能夠一直保持工作狀態,可以對外提供服務,那麼我們就說系統的可用性是100%;大部分公司不會把話說這麼滿,所以經常會提出三個9、四個9的目標,也就是全年系統可用性為99.9%、99.99%。

那麼如何保證系統的高可用呢?我認為核心的思想就是【防止單點,增加冗餘】,先讓我們看看傳統的架構是什麼樣的,哪裡會有風險。

可以看到,架構的每一個部分都是單點的話,簡直是風險重重,任何一個環節出現了問題,可能會造成整個系統垮掉(緩存部分可能不會直接影響系統,但往往緩存失去效果之後,會拖垮數據庫),解決方法也很容易,其實就是把系統的每個部分都增加冗餘:

  • 客戶端到Web應用:要增加Web應用,首先要增加反向代理層,也就是負載均衡,比如Nginx;不過如果只部署一個Nginx的話,它又是一個單點了,通常我們會部署多臺,一臺提供服務,另外的相當於“備胎”,通過keepalived的方式監控工作中的Nginx是否存活,當主服務器發生故障無法對外提供服務時,動態將virtual IP(虛IP)切換到備用機,繼續提供服務。

  • 負載均衡到Web應用:搭建多個Web應用,在負載均衡如Nginx中配置多個Web端的地址,並且可以監控多個Web端的存活性,當監控到某臺應用掛掉,那麼Nginx不在將請求分發到這臺機器上。

  • Web應用到服務層:這裡有很多種實現方式,比如服務層前端也掛負載均衡,或者走客戶端內的負載均衡(這裡Web應用就是客戶端,相當於配置多個服務層的地址,每次請求按照一定規則,選取連接來訪問下游服務,並使用service-connection-pool監控服務層應用的存活性);也可以使用服務註冊發現的方式(可提供服務的應用才會出現在註冊中心)。


  • 服務層到緩存:緩存的存在,本身就是一種冗餘;緩存層也可以通過集群來解決緩存層的高可用問題。以Redis為例,支持主從同步,而且有sentinel哨兵機制,來做Redis的存活性檢測。

  • 服務層到數據庫:數據庫一般會採用主從架構;數據庫【讀】的高可用,通常使用db-connection-pool來保證自動故障轉移;而【寫】操作,通常需要keepalived+virtual IP(虛IP)自動切換。

以上都是保證系統高可用的方案,儘量做到客戶端所有的請求都可以響應,但是系統資源不可能無限投入,所以需要一些方案保證系統的高可用,不過需要【犧牲】部分用戶:

  • 限流:我們接口只能支持200的併發,我們的頁面只能支持一萬人同時訪問,那麼多餘的部分,對不起,我需要限制你們進入;常見的限流算法有:漏桶、令牌桶;

  • 降級:犧牲非核心的業務功能,保證核心功能的穩定運行;

  • 熔斷:當服務鏈路中(A調B,B調C,C調D),某個服務響應時間過長或失敗,會進行服務的降級,進而熔斷該節點服務的調用,快速返回錯誤信息;不過嘛,我從來沒有見過誰敢用熔斷...

  • 灰度發佈:將部分流量導到新上線的應用上,來驗證新的功能修改,如果上線後有BUG,也可以快速回滾,儘可能降低發佈的風險。


我將持續分享Java開發、架構設計、程序員職業發展等方面的見解,希望能得到你的關注。


會點代碼的大叔


架構上講究“三高”(3H),這裡的“三高”可不是我們日常生活中說的“三高”,而是指:高併發、高可用、高性能。

那什麼是系統架構的高可用呢?

高可用性指的是系統在架構上通過某些手段,使得當發生異常時,最大程度減少服務中斷時間,從而保證了服務的高度可用性。

舉個例子來說明一下:有兩個網站平臺A和B,A和B是競爭對手關係,向用戶提供的都是類似的服務。此時又出現一個C想和A與B競爭,C使用了某種手段向A與B發起了攻擊,結果A網站掛了,B網站依舊堅挺,我們就說B較A而言更具高可用性。

具體在平臺架構中該如何實施才能提高整個平臺的高可用性呢?結合我的架構經驗給出一些方案供大家參考:

1、業務分層

我們知道,一個大型平臺業務是很複雜的,而且各個業務間還有複雜的調用關係。如果把所有業務的實現全部放在一起(代碼上放在一起、部署時放在一起)的話,那耦合度就太高了,很容易導致一個問題影響整個平臺的穩定性。

所以我們在架構實施初期就會考慮將業務分層,根據業務不同將整個系統橫向切割為多個部分,比如:用戶中心、訂單系統、支付系統、後臺系統、消息系統、日誌系統等。

另外站在技術角度上我們可以將整個系統再劃分為三大層,即:應用層、服務層、數據層,這3層的具體定位是:

  • 應用層:前端視圖展示,前後端用戶看到的界面性操作都劃到此類;

  • 服務層:為應用層提供服務支持與調用的,比如API;

  • 數據層:底層數據的存儲與交互,主要是:各類數據庫、各類緩存等。

分層的好處就是方便後期的擴展,比如說分佈式部署。

2、分佈式部署

上面說到,我們可以將大型系統進行模塊和業務上的分層,當分層後我們就可以分佈式部署了。分佈式部署能夠解決傳統集中式部署帶來的服務器性能瓶頸問題。

分佈式的實施有很多方面,如:

  • 應用及服務的分佈式:將不同模塊分別部署在不同服務器上、將數據庫和API部署在不同服務器上;

  • 動靜分離:將網站系統上所用到的靜態資源(如:CSS/JS/圖片/文件)等使用單獨的域名來部署,不和當前系統根域名相同,以此將動態腳本請求與靜態資源請求分離,這樣就可以減小應用服務器的負載了。

  • 數據庫分佈式:將服務庫分佈式部署,去中心化。

3、集群部署

說到集群和分佈式,可能很多人分不清楚兩者區別。簡單的說,兩者區別是:

  • 分佈式:將一個大業務拆分為多個子業務,部署在不同的服務器上,各司其職完成了一件事;

  • 集群:同一個業務,部署在多臺服務器上;

  • 分佈式是邏輯上的形態,集群是物理上的形態。

舉個例子:如果你是一個飯店老闆,客人上門時:前臺迎客、下單員下單、服務員端水擦桌、廚師做菜、收銀員結帳,這就是分佈式;你不可能只招1個廚師吧,你招了10個廚師來做菜,這就是集群,萬一哪天有個廚師生病了,還有其它廚師來做菜。

在架構中我們通常將數據庫集群部署,這樣可以避免單臺服務器的性能瓶頸。

4、負載均衡

負載均衡機制主要是用來處理高併發的,但這種分流機制在一定程度上也涉及到了高可用性。

5、異步任務

假設有這樣一個場景,用戶註冊我們平臺後,需要發送郵件給客戶確認、客戶確認後給這個用戶贈送初始的積分。通常我們是這樣做的:

  • 用戶註冊信息寫入數據庫;

  • 然後調用郵件發送服務,等待郵件發送成功後;

  • 再來給這個用戶進行積分贈送操作。

這樣做就是同步操作,是阻塞式的,如果發送郵件時超時了,後面的任務可能就無法繼續了,顯然,這是不合理的。

我們可以將一件事拆分為多件事讓不同的人去做,做好了你再來通知我。這樣異步操作可以節省整體事務完成的時間。

6、合理利用緩存

利用緩存,我們可以將熱點數據緩存下來,這樣在一段時間內就避免去數據庫中查詢。緩存的目的就是減輕服務器的計算壓力。

常見緩存實施種類也很多,比如說有:

  • 靜態資源走CDN加速;

  • 客戶端緩存策略,可以減少客戶端對於服務器的請求次數;

  • NoSQL存儲熱點數據,緩解數據庫壓力,就算數據庫掛了,在緩存期內不必去查詢數據庫,這樣調用方不會出錯。


以上就是我的觀點,對於這個問題大家是怎麼看待的呢?歡迎在下方評論區交流 ~ 我是科技領域創作者,十年互聯網從業經驗,歡迎關注我瞭解更多科技知識!

網絡圈


高可用(High Availability),主要是指減少系統的故障時間,保持系統的高度可用性。下面說一下個人的一些理解:

一、很多系統架構的高可用性,理解為雙機熱備。當然雙機熱備又可以分為主備方式,雙主方式,雙主方式主要是指互為主備。例如,使用比較多的是keepalived,通過keepalived配置雙機熱備的最大好處是,你無須對你的軟件系統做任何代碼改動,即可實現雙機熱備。

二、當然藉助負載均衡實現系統高可用性。實現負載均衡的第三方軟件也較多。例如LVS,Engix等。這方面的配置方式的資料也比較多,有興趣的同學,可以直接從網上查閱,此處不做詳細介紹。

三、混合方式。雙機熱備+負載均衡的方式。例如keepalived+LVS實現更加好的高可用性。如下例所示:主要增加了負載均衡器的雙機熱備功能,避免了負載均衡器的單點故障,增加了系統的高可用性。

四、藉助zookeeper分佈式框架,實現高可用。現在好多框架藉助zookeeper實現高可用。例如Dubbo微服務架構,HADOOP等,都採用zookeeper這種輕量級的分佈式框架實現高可用。這種方式就需要涉及到代碼編程。

看一下Dubbo:

上圖是Dubbo的框架,主要是使用zookeeper實現註冊器功能,生產者通過zookeeper的api接口向註冊器寫入服務提供者信息,消費者同樣通過zookeeper的api接口從註冊中心獲取服務信息,藉助zookeeper的分佈式,實現Dubbo的高可用,這就涉及到代碼的層面的實現。

當然,實現層面不止這些,歡迎大家評論,提出更好建議。

本人具有多年的java開發經驗,熟悉多種框架,熟悉網絡編程,熟悉java安全編程,熟悉大數據,熟悉多種安全協議,熟悉併發編程,有興趣的同學可以互相關注,互相學習!!!


分享到:


相關文章: