今天談下叢集和高可用方面的內容。在前面我談過IT基礎架構的高可用性設計,其核心的一個特點就是在執行期間沒有任何的單點故障。因此在基礎部署架構設計的時候,往往就有兩個思路,其一就是實現簡單的HA高可用,一種就是實現叢集,同時在叢集基礎上同時實現高可用。因此今天對這方面的內容做下簡單整理。
HA高可用架構HA高可用是最基礎的一種高可用架構,一般應用在資料庫,管理節點,負載均衡節點等。一主一備,只有一個節點提供能力,但是在主節點宕機後能夠自動切換到備用節點。對於任何型別的中介軟體或應用伺服器都可以搭建高可用架構,但是前提是共享儲存,因為高可用架構只會做浮動IP切換,而不會去做底層資料的同步。
HA高可用架構搭建過程中,一般又存在手工切換和自動切換兩種情況。
如果要做到自動切換,那麼必須配合心跳檢查,即透過指令碼進行心跳檢查,在心跳檢查出現異常的時候進行IP地址的切換操作。
對於作業系統級別的HA高可用性軟體當前大部分都屬於商用和收費軟體,包括類似紅帽的RedHat Cluster Suite,雖然是可以免費下載安裝,但是也需要購買相應的技術服務,否則後續無法得到相應的技術支援和版本升級服務等。
心跳檢查心跳檢查HeartBeart在搭建高可用架構的時候經常會使用。核心目的就是發現節點故障或問題,同時進行自動切換操作。
比如可以透過HaProxy+KeepAlived來搭建一個高可用架構。在資料庫中採用MySql Dual Master架構的時候,我們也會使用HaProxy+KeepAlived來搭建一個提供VIP的資料庫高可用架構。
心跳檢查一般包括了心跳監測部分和資源接管部分,心跳監測可以透過網路鏈路,傳送ping或連線請求,如果失敗或超時達到一個閾值,就認為對方失效,這時需啟動資源接管模組來接管運 行在對方主機上的資源或者服務。
叢集和負載均衡如果當前有6個Tomcat應用伺服器節點,我們統一接入到Ngnix或F5硬體負載均衡裝置。那麼6個節點是否就構成了一個完整的Tomcat叢集?
上面這種情況實際只實現了負載均衡能力,而沒有實現叢集管理能力。
一個完整的叢集必須具備叢集管理能力,其核心包括了節點的心跳檢查,配置檔案資訊的分發,高可用保障,請求負載均衡,統一的叢集節點監控和管理等。
比如一個應用要部署,我們可以在管理節點進行統一處理,部署包會自動部署到所有叢集節點,或者說我們可以在管理端對單個或整體叢集節點進行重啟等操作。
也就是說叢集一般會存在管理節點,管理節點對叢集提供上面說的管理能力。負載均衡能力你可以不用叢集本身的負載均衡,比如請求分發和均衡仍然透過接入F5硬體裝置完成等。
當前中介軟體或軟體一般存在兩種情況,一種就是自己實現Admin叢集管理能力,一種是基於開源的Zookeeper或Etcd來實現叢集管理能力。比如在dubbo中會採用Zookeeper來作為註冊中心,kurbernetes中則採用Etcd進行叢集管理。
在分散式任務協調場景下,兩者實際提供能力基本一致,對比如下:
其中Zookeeper 使用 java 開發的,被 Apache 很多專案採用。而Etcd 使用 go 語言開發的,主要是被 Kubernetes 採用。Zookeeper 非常穩定,是一個著名的分散式協調系統,Etcd 是後起之秀,前景廣闊。
基於Zookeeper或Etcd來實現叢集管理節點
如果你自己實現一個叢集,完全可以基於Zookeeper或Etcd來實現叢集管理節點。在叢集管理節點的管理中本身包括如下核心內容。
心跳檢查:對於心跳檢查如下異常的節點能夠自動剔除或者觸發該節點自動進行重啟,重啟後正常才能夠重新加入叢集。
部署或配置分發:具備進行統一部署或配置分發能力,只需要在管理節點更新部署或配置資訊,該資訊能夠自動分發到所有的叢集節點確保一致性。
軟負載均衡:具備基本的路由分發和負載均衡能力。
分散式鎖:當存在多節點同時觸發搶佔某一個任務的時候,具備分散式鎖能力,確保該任務只能夠被一個節點處理,如果該節點處理異常又能夠快速釋放鎖。其它監聽節點可以快速獲取鎖並進一步處理該任務。
叢集和分散式
很多時候這兩個概念是在混用,但是本身還是有一點區別。簡單來說對於叢集即所有的節點全部都是相同的,包括部署的內容,具備的能力,然後構成一個整體對外服務;但是對於分散式來說則可能各個節點本身具備分工,共同處理最終完成一個任務。
比如常見的負載均衡,多個節點本身完全相同,則是典型的叢集架構;而對於一個大矩陣的計算,可能要分解為多個部分,拆分到不同的機器進行計算則類似於分散式架構。簡單來說類似Master-Slave架構下,Master對任務進行分解到Slave進行計算,完成後再到Master進行彙總即可理解為典型的分散式架構。
叢集節點假死問題
對於中介軟體叢集,往往存在一種情況即節點處理任務的時候被Hang住或者叫假死。在這種情況下節點心跳檢查正常,但是無法處理正常分發過來的請求,或者請求處理全部超時。
因此心跳檢查還有一個重點就是需要去判斷叢集節點是否出現假死。
如果僅僅是類似tomcat應用伺服器,你可以直接去curl http訪問tomcat首頁看是否正常返回。但是如果是判斷應用功能是否正常,那麼還涉及到資料庫,在這種情況下一般需要單獨寫一個用於心跳檢查的介面進行心跳檢查,看這個介面在心跳檢查過程中能否正常返回。
動態擴容或動態分割槽
簡單來說即叢集節點不論是新增加,還是因為故障異常等原因下線減少的時候,對於新的請求路由分發,或者新任務的獲取都能夠再次基於當前可用節點數進行重新分配。
叢集能夠動態擴容,但是當新增加節點的時候並不會對已經在叢集其它節點執行的經常進行重新分配,而是僅僅對新增加的需求進行重新分配計算。在分散式資料庫叢集的實現中可以看到,這類叢集涉及到底層持久化資料,因此當增加節點的時候往往涉及到資料本身的ReSharding重新計算,這個動作本身是相對複雜的,一般不建議自動處理。
叢集管理節點至少3個節點以上奇數部署
在進行叢集架構部署的時候,可以看到管理或Master節點一般都要求3個節點或以上的奇數個節點進行部署。在這裡進行簡單說明如下。
在前面已經談到Master節點肯定不能單節點部署,否則就存在單點故障,那麼我們容易想到就是2個節點冗餘架構部署。
注意如果Admin或Master節點往往並不是簡單的保證自己的高可用性,而且還需要承擔對管理的Slave節點的管理和心跳監控職責。那麼2個節點部署的時候,如果2個節點進行心跳監控返回的狀態不一致,那麼應該聽誰的?因此為了避免這種情況必須要有一個奇數的投票機制來決策,因此至少需要3個節點來進行管理節點的部署。
分散式任務排程當構建一個分散式叢集的時候,實際上又存在兩種情況。
一種情況是本身叢集節點被動等待資訊分發,等待經過叢集路由過來的訪問請求;另外一種情況是叢集節點主動去獲取或搶佔任務並進行處理。
如果是第二種情況則涉及到分散式任務排程。
分散式任務排程簡單來說就是有多個任務處理節點也組成叢集,但是這些節點主動去搶佔和處理管理或排程階段的任務列表資訊,並進行加鎖,如果處理失敗或者處理節點宕機又能夠快速的釋放鎖方便其它任務處理節點處理。
當然對於這種情況,你也可以採用Zookeeper具備的分散式鎖功能來實現。但是對於分散式任務排程本身又是一個細分方向,有專門的分散式任務排程開源解決方案。
如開源的xxl-job分散式排程框架
從圖上也可以看到分散式排程框架本身也具備節點註冊管理,分散式鎖,心跳檢查等關鍵能力。因此如果是一個任務處理類分散式叢集構建,那麼採用開源的分散式排程框架進行擴充套件往往是一種更好的處理方案。
即在分散式任務排程框架中,我們將任務的產生和任務的處理兩個事件解耦,一個程序獨立執行產生待處理的任務,而另外程序執行則是透過併發和鎖機制搶佔和處理任務,如果處理任務過程中出現異常又能夠自動釋放任務。