1、什麼是高可用html
高可用HA(High Availability)是分佈式系統架構設計中必須考慮的因素之一,它一般是指,經過設計減小系統不能提供服務的時間。mysql
假設系統一直可以提供服務,咱們說系統的可用性是100%。nginx
若是系統每運行100個時間單位,會有1個時間單位沒法提供服務,咱們說系統的可用性是99%。web
不少公司的高可用目標是4個9,也就是99.99%,這就意味着,系統的年停機時間爲8.76個小時。redis
百度的搜索首頁,是業內公認高可用保障很是出色的系統,甚至人們會經過www.baidu.com 能不能訪問來判斷「網絡的連通性」,百度高可用的服務讓人留下啦「網絡通暢,百度就能訪問」,「百度打不開,應該是網絡連不上」的印象,這實際上是對百度HA最高的褒獎。sql
2、如何保障系統的高可用數據庫
咱們都知道,單點是系統高可用的大敵,單點每每是系統高可用最大的風險和敵人,應該儘可能在系統設計的過程當中避免單點。方法論上,高可用保證的原則是「集羣化」,或者叫「冗餘」:只有一個單點,掛了服務會受影響;若是有冗餘備份,掛了還有其餘backup可以頂上。json
保證系統高可用,架構設計的核心準則是:冗餘。後端
有了冗餘以後,還不夠,每次出現故障須要人工介入恢復勢必會增長系統的不可服務實踐。因此,又每每是經過「自動故障轉移」來實現系統的高可用。瀏覽器
接下來咱們看下典型互聯網架構中,如何經過冗餘+自動故障轉移來保證系統的高可用特性。
3、常見的互聯網分層架構
常見互聯網分佈式架構如上,分爲:
(1)客戶端層:典型調用方是瀏覽器browser或者手機應用APP
(2)反向代理層:系統入口,反向代理
(3)站點應用層:實現核心應用邏輯,返回html或者json
(4)服務層:若是實現了服務化,就有這一層
(5)數據-緩存層:緩存加速訪問存儲
(6)數據-數據庫層:數據庫固化數據存儲
整個系統的高可用,又是經過每一層的冗餘+自動故障轉移來綜合實現的。
4、分層高可用架構實踐
【客戶端層->反向代理層】的高可用
【客戶端層】到【反向代理層】的高可用,是經過反向代理層的冗餘來實現的。以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,這個切換過程對調用方是透明的。
5、總結
高可用HA(High Availability)是分佈式系統架構設計中必須考慮的因素之一,它一般是指,經過設計減小系統不能提供服務的時間。
方法論上,高可用是經過冗餘+自動故障轉移來實現的。
整個互聯網分層系統架構的高可用,又是經過每一層的冗餘+自動故障轉移來綜合實現的,具體的:
(1)【客戶端層】到【反向代理層】的高可用,是經過反向代理層的冗餘實現的,常見實踐是keepalived + virtual IP自動故障轉移
(2)【反向代理層】到【站點層】的高可用,是經過站點層的冗餘實現的,常見實踐是nginx與web-server之間的存活性探測與自動故障轉移
(3)【站點層】到【服務層】的高可用,是經過服務層的冗餘實現的,常見實踐是經過service-connection-pool來保證自動故障轉移
(4)【服務層】到【緩存層】的高可用,是經過緩存數據的冗餘實現的,常見實踐是緩存客戶端雙讀雙寫,或者利用緩存集羣的主從數據同步與sentinel保活與自動故障轉移;更多的業務場景,對緩存沒有高可用要求,可使用緩存服務化來對調用方屏蔽底層複雜性
(5)【服務層】到【數據庫「讀」】的高可用,是經過讀庫的冗餘實現的,常見實踐是經過db-connection-pool來保證自動故障轉移
(6)【服務層】到【數據庫「寫」】的高可用,是經過寫庫的冗餘實現的,常見實踐是keepalived + virtual IP自動故障轉移
末了,但願文章的思路是清晰的,但願你們對高可用的概念和實踐有個系統的認識,感謝你們。
==【完】==