1. 程式人生 > 其它 >網際網路三高中的高可用的理解

網際網路三高中的高可用的理解

摘要:高可用(High availability,即 HA)的主要目的是為了保障「業務的連續性」,即在使用者眼裡,業務永遠是正常(或者說基本正常)對外提供服務的。高可用主要是針對架構而言,那麼要做好高可用,就要首先設計好架構,第一步我們一般會採用分層的思想將一個龐大的IT系統拆分成為應用層,中介軟體,資料儲存層等獨立的層,每一層再拆分成為更細粒度的元件,第二步就是讓每個元件對外提供服務,畢竟每個元件都不是孤立存在的,都需要互相協作,對外提供服務才有意義。要保證架構的高可用,就要保證架構中所有元件以及其對外暴露服務都要做高可用設計,任何一個元件或其服務沒做高可用,都意味著系統存在風險。

關鍵詞:高可用;架構;分層;服務

中圖分類號:   文獻標誌碼:A


0  引言

要保證架構的高可用,就要保證架構中所有元件以及其對外暴露服務都要做高可用設計,任何一個元件或其服務沒做高可用,都意味著系統存在風險。

那麼這麼多元件該怎麼做高可用設計呢,其實任何元件要做高可用,都離不開「冗餘」和「自動故障轉移」,接下來我們就來一起看看架構中的各個元件如何藉助「冗餘」和「自動故障轉移」來實現高可用。

1  網際網路架構剖析

其實任何元件要做高可用,都離不開「冗餘」和「自動故障轉移」,眾所周知單點是高可用的大敵,所以元件一般是以叢集(至少兩臺機器)的形式存在的,這樣只要某臺機器出現問題,叢集中的其他機器就可以隨時頂替,這就是「冗餘」。簡單計算一下,假設一臺機器的可用性為 90%,則兩臺機器組成的叢集可用性為 1-0.1*0.1 = 99%,所以顯然冗餘的機器越多,可用性越高。

但光有冗餘還不夠,如果機器出現問題,需要人工切換的話也是費時費力,而且容易出錯,所以我們還需要藉助第三方工具(即仲裁者)的力量來實現「自動」的故障轉移,以達到實現近實時的故障轉移的目的,近實時的故障轉移才是高可用的主要意義

怎樣的系統可以稱之為高可用呢,業界一般用幾個九來衡量系統的可用性,如下

圖1  系統可用性表

一般實現兩個 9 很簡單,畢竟每天宕機 14 分鐘已經嚴重影響業務了,這樣的公司遲早歇菜,大廠一般要求 4 個 9,其他要求嚴苛的業務要達到五個九以上,比如如果因為一個電腦的故障導致所有列車停駛,那麼就會有數以萬計的人正常生活受到阻礙,這種情況就要求五個九以上

圖2  常見架構

可以看到架構主要分以下幾層

接入層:主要由 F5 硬體或 LVS 軟體來承載所有的流量入口

反向代理層:Nginx,主要負責根據 url 來分發流量,限流等

閘道器:主要負責流控,風控,協議轉換等

站點層:主要負責呼叫會員,促銷等基本服務來裝配 json 等資料並返回給客戶端

基礎 service:其實與站點層都屬於微服務,是平級關係,只不過基礎 service 屬於基礎設施,能被上層的各個業務層 server 呼叫而已

儲存層:也就是 DB,如 MySQL,Oracle 等,一般由基礎 service 呼叫返回給站點層

中介軟體:ZK,ES,Redis,MQ 等,主要起到加速訪問資料等功能,在下文中我們會簡單介紹下各個元件的作用

如前所述,要實現整體架構的高可用,必須要實現每一層元件的高可用,接下來我們就來分別看一下每一層的元件都是如何實現高可用的

1.1     接入層&反向代理層

圖3  接入層&反向代理層

對外,兩個 LVS 以主備的形式對外提供服務,注意只有 master 在工作(即此時的 VIP 在 master 上生效),另外一個 backup 在 master 宕機之後會接管 master 的工作,那麼 backup 怎麼知道 master 是否正常呢,答案是通過 keepalived,在主備機器上都裝上 keepalived 軟體,啟動後就會通過心跳檢測彼此的健康狀況,一旦  master 宕機,keepalived 會檢測到,從而 backup 自動轉成 master 對外提供服務,此時 VIP 地址(即圖中的 115.204.94.139)即在 backup 上生效,也就是我們常說的「IP漂移」,通過這樣的方式即解決了 LVS 的高可用。

keepalived 的心跳檢測主要通過傳送 ICMP 報文,或者利用 TCP 的埠連線和掃描檢測來檢測的,同樣的,它也可以用來檢測 Nginx 暴露的埠,這樣的話如果某些 Nginx 不正常 Keepalived 也能檢測到並將其從 LVS 能轉發的服務列表中剔出。

借用 keepalived 這個第三方工具,同時實現了 LVS 和 Nginx 的高可用,同時在出現故障時也可以將宕機情況傳送到對應開發人員的郵箱以讓他們及時收到通知處理,確實很方便,Keepalived 應用廣泛,下文我們會看到它也可以用在 MySQL 上來實現 MySQL 的高可用。

1.2     中介軟體

我們再來看下這些中介軟體如 ZK,Redis 等是如何實現高可用的呢

1.2.1      zookeeper

圖4  zookeeper架構

Zookeeper 中的主要角色如下

Leader: 即領導者,在叢集中只有一個 Leader,主要承擔了以下的功能

1.事務請求的唯一排程和處理者,保證叢集事務處理的順序性,所有 Follower 的寫請求都會轉給 Leader 執行,用來保證事務的一致性

2.叢集內部各伺服器的排程者:處理好事務請求後,會將資料廣播同步到各個 Follower,統計 Follower 寫入成功的數量,超過半數 Follower 寫入成功,Leader 就會認為寫請求提交成功,通知所有的 Follower commit 這個寫操作,保證事後哪怕是叢集崩潰恢復或者重啟,這個寫操作也不會丟失。

Follower:

1.處理客戶端非事務請求、轉發事務請求給 leader 伺服器

2.參與事物請求 Proposal 的投票(需要半數以上伺服器通過才能通知 leader commit 資料; Leader 發起的提案,要求 Follower 投票)

3.參與 Leader 選舉的投票

可以看到由於只有一個 Leader,很顯然,此 Leader 存在單點隱患,那麼 ZK 是怎麼解決此問題的呢,首先 Follower 與 Leader 會用心跳機制保持連線,如果 Leader 出現問題了(宕機或者因為 FullGC 等原因無法響應),Follower 就無法感知到 Leader 的心跳,就會認為 Leader 出問題了,於是它們就會發起投票選舉,最終在多個 Follower 中選出一個 Leader 來(這裡主要用到了 Zookeeper Atomic Broadcast,即 ZAB 協議,它是為 ZK 專門設計的一種支援崩潰恢復的一致性協議)

除了 ZAB 協議,業界上常用的還有 Paxos,Raft 等協議演算法,也可以用在 Leader 選舉上,也就是是在分散式架構中,這些協議演算法承擔了“第三者”也就是仲裁者的作用,以承擔故障的自動轉移

1.2.2      Redis

Redis 的高可用需要根據它的部署模式來看看,主要分為「主從模式」和「Cluster 分片模式」兩種

主從模式,架構如下

圖5  主從模式架構

主從模式即一主多從(一個或者多個從節點),其中主節點主要負責讀和寫,然後會將資料同步到多個從節點上,Client 也可以對多個從節點發起讀請求,這樣可以減輕主節點的壓力,但和 ZK 一樣,由於只有一個主節點,存在單點隱患,所以必須引入第三方仲裁者的機制來判定主節點是否宕機以及在判定主節點宕機後快速選出某個從節點來充當主節點的角色,這個第三方仲裁者在 Redis 中我們一般稱其為「哨兵」(sentinel),當然哨兵程序本身也有可能掛掉,所以為了安全起見,需要部署多個哨兵(即哨兵叢集)

1.2.3      ES

再來看一下 ES 是如何實現高可用的,在 ES 中,資料是以分片(Shard)的形式存在的,如下圖所示,一個節點中索引資料共分為三個分片儲存

圖6

但只有一個節點的話,顯然存在和 Redis 的主從架構一樣的單點問題,這個節點掛了,ES 也就掛了,所以顯然需要建立多個節點

圖7

一旦建立了多個節點,分片(圖中 P 為主分片,R 為副本分片)的優勢就體現出來了,可以將分片資料分散式儲存到其它節點上,極大提升了資料的水平擴充套件能力,同時每個節點都能承擔讀寫請求,採用負載均衡的形式避免了單點的讀寫壓力

1.2.4      MQ

ES 利用資料分片來提升高可用和水平擴充套件能力的思想也應用在其他元件的架構設計上,我們以 MQ 中的 Kafka 為例再來看下資料分片的應用

圖8

如上是 Kafka 叢集,可以看到每個 Topic 的 Partition 都分散式儲存在其它訊息伺服器上,這樣一旦某個 Partition 不可用,可以從 follower 中選舉出 leader 繼續服務,不過與 ES 中的資料分片不同的是,follower Partition 屬於冷備,也就是說在正常情況下不會對外服務,只有在 leader 掛掉之後從 follower 中選舉出 leader 後它才能對外提供服務

1.3     儲存層

接下來我們再來看一下最後一層,儲存層(DB),這裡我們以 MySQL 為例來簡單地討論一下其高可用設計,其實大家如果看完了以上的高可用設計,會發現 MySQL 的高可用也不過如此,思想都是類似的,與 Redis 類似,它也分主從和分片(即我們常說的分庫分表)兩種架構

圖9

如果 master 宕機了,Keepalived 也會及時發現,於是從庫會升級主庫,並且 VIP 也會“漂移”到原從庫上生效,所以說大家在工程配置的 MySQL 地址一般是 VIP 以保證高可用

資料量大了之後就要分庫分表了,於是就有了多主,就像 Redis 的分片叢集一樣,需要針對每個主配備多個從,如下

圖10

2 總結

看完了架構層面的高可用設計,對高可用的核心思想「冗餘」和「自動故障轉移」會有更深刻的體會,觀察以上架構中的元件會發現,冗餘的主要原因是因為只有一主,為什麼不能有多主呢,也不是不可以,但這樣在分散式系統下要保證資料的一致性是非常困難的,尤其是節點多了的話,資料之間的同步更是一大難題,所以多陣列件採用一主的形式,然後再在主和多從之間同步,多陣列件之所以選擇一主本質上是技術上的 tradeoff

最後我們以一張圖來總結一下高可用的常見手段

圖11