您當前的位置:首頁 > 收藏

OceanBase高可用實踐

作者:由 阿里云云棲號 發表于 收藏時間:2019-08-19

背景

高可用是構建分散式系統的基石。一方面,出於成本考慮, 分散式系統往往採取比較廉價的硬體,其可靠性相對於小型機、專有硬體有很大的不足, 而分散式系統的規模一般比較大,假如硬體的可靠性只有三個9(99。9%), 一個1000臺機器規模的叢集每天將面臨1臺機器宕機的風險,在如此大規模的情況下,儲存介質,比如硬碟可能會隨時都有損壞,結點之間的網路可能隨時都會有抖動,機房可能區域性或整體斷電,地區或資料中心可能會出現不可用,如果不在設計時考慮這些問題,當這些情況出現的時候,系統將很快處於不可用的狀態;另一方面,分散式系統的程式在設計與實現上也更為複雜,軟體上既要容錯硬體的不可靠,同時軟體自身也有可能有問題, 在對外部環境容錯的同時需要考慮對軟體BUG的容錯。

OceanBase在設計之初就充分考慮了高可用問題,確保OceanBase有能力在這些異常出現後,仍然能最大可能的提供服務。

高可用的基本策略

冗餘是實現高可用的通用方法,為防止資料丟失,將資料冗餘多份;為防止系統中某些節點故障,對某些功能節點進行冗餘。 冗餘帶來的好處是可以抵禦某些節點的損失,而帶來的壞處則主要是成本、效能和一致性問題。

成本主要包括額外的儲存、網路、機櫃等硬體成本,這是構建高可用分散式系統的必不可少的開銷,其總體成本較專有硬體仍然要低,因為專有硬體實際上也需要在內部對某些模組進行冗餘以獲取高可用性。 效能和一致性問題則是高可用分散式系統必須要處理問題,這兩個問題直接影響整個系統正確性、延時與吞吐量。

在傳統myql或oracle中,我們往往透過新增備機來實現高可用,且為了實現高效能和高可用,一般會使用“最大可用”模式:

OceanBase高可用實踐

主機盡力將資料同步到備機,而不管是否同步成功,當主機掛掉以後,將備機升級成主機以繼續提供服務,這就意味著如果主機在宕機前有資料沒有同步到備機,要麼透過某種特殊的手段將資料從宕掉的主機同步到備機,要麼就接受暫時的資料不一致而繼續提供服務,在這種情況下,如果出現主機永久損壞,則會造成資料丟失:

OceanBase高可用實踐

為了解決這個問題,可以使用最大保護模式(早期的MySQL版本不支援),即主機將日誌同步到備機成功後再應答客戶,這樣會引入另外一個問題,即備機故障或網路抖動會導致失敗,影響可用性; 小微引入了共享儲存,將資料庫redo log放在共享儲存上,主機宕機以後,備機需要確保主機所有的資料都已經同步才能對外提供服務:

OceanBase高可用實踐

這樣在主機宕機時,備機作一些額外的檢查後升級為主機繼續提供服務,這樣可以確保資料一致性,但引入了共享儲存。傳統的主備模式還有另外一個問題是主備之間無法透過自身決出主備,需要人工切換或者使用一個第三方元件:

OceanBase高可用實踐

但是又引入了HA模組的穩定性問題,如果HA模組和主機的網路不通, HA將不能識別主機是活著還是網路有問題,此時HA如果進行切換而主機還活著則會造成後果很嚴重的雙主問題。

OceanBase高可用策略

故障可以分為單機故障(磁碟、記憶體等硬體介質損壞或單臺軟體Crash都屬於單機故障),機架/機房故障(比如整個機架或機房的電源斷電)以及地區/資料中心(比如地區地震造成該區網路隔離)故障,一般來說,故障單位越小,出現頻率越高,而除非自然災害,一個地區出現故障的機率極小,故障單位越小,實現高可用的難度和成本越低,故障單位越大,由於引入環境、距離等因素,實現高可用的難度和成本會呈指數倍增長。比如為了預防單機故障,只需要在本機房預備冗餘節點,故障時透過某些技術方案,可以做到實時切換;而為了預防資料中心故障,則需要在另外一個地區預備冗餘的資料中心,在故障時由於通訊距離等原因,基本上無法做到無損切換。

OceanBase雖然在設計之初就考慮到了硬體和軟體的不可靠,但OceanBase的高可用並非一蹴而就,在實現過程中,為了快速實現或者繞過某個暫時無法攻克的技術難點,會進行綜合權衡,只實現一些出現機率較高的基本高可用策略,而透過人肉或其它手段來保證在某些很難出現的災難出現後可以儘快恢復。然後透過逐步迭代,逐漸完善,將高可用的範圍提高,比如OceanBase最初的時候只考慮單機故障的高可用,到目前為止已經可以實現同城IDC之間的容災。

分散式系統為了設計與實現的簡單,往往會在系統中設定一個全域性單點,來負責相對比較輕量的管理任務, OceanBase中的rootserver就是這樣一個角色;它主要負責叢集中其它角色的管理並作為使用者的入口,通常其壓力不高且無本地資料需要儲存,所需資訊都可以透過其它角色的彙報來重建。

而作為一個分散式資料庫,OceanBase面臨著兩個很難解決的問題:資料一致性與分散式事務,在早期的OceanBase版本中,採取的策略是暫時繞過這兩個問題,等技術積累到一定程度後再回過頭來解決,所以在OceanBase中另外增加了一個單寫入節點,這個節點的壓力很高,資料無法透過其它節點來恢復,我們需要保證這些單節點的高可用。另外一個是儲存基線資料結點的高可用,這些結點被設計成可以彈性伸縮,本身具備高可用屬性,但仍然需要考慮磁碟故障以及資料副本之間的一致性。 我們會在下面的章節分別描述對這兩類節點的高可用策略。

系統單點

在早期OceanBase的版本中,主要依靠主備來為單點提供高可用, 使用兩臺機器,其中的一臺角色為主的機器對外提供服務,另外一臺機器做為熱備, 當主機掛掉後,備機切換為主,繼續提供服務。

如前所述,這種“最大可用”模式的主備機制主要有兩個問題:第一個問題在於這兩臺機器無法透過自身來決出主備,必須要依賴於一個第三方元件,早期我們使用了HA(

http://

linux-ha。org

) 來做為仲裁元件,HA使用VIP機制,兩臺機器共享VIP, 同一時刻VIP只會載入在其中的一臺機器, VIP會提供給外部應用程式作為OceanBase叢集的入口地址,即VIP載入在哪一臺機器上,該機就會作為主對外提供服務,程式可以透過不斷檢測VIP是否存在來判斷本機是否為主機,當HA透過我們提供的檢測程式檢測到主機故障後,就會將VIP切換到備機, 此時外部請求就會路由到原來的備機,原來的備機檢測到VIP“飄”到本機後,會將自己的角色置為主:

OceanBase高可用實踐

使用HA主要有幾個問題:

HA為了防止網路抖動帶來的誤判,要求將兩臺機器使用網線直連, 這就限制了兩臺機器只能放在一個機櫃,如果整個機櫃斷電,則服務不可用,這樣就不能抵禦機櫃以及機房的容災。

資料一致性不能保證,一般不要求使用HA的角色持久化特別重要的資料。 其資料應該能透過其他角色的彙報而重建。

另外一個問題在於這種機制無法保證資料不丟失, 某些極端情況下需要停機恢復,如果有機器永久損失,則可能會造成資料的丟失,在某些業務上可能無法接受。

而Updateserver是OceanBase中至關重要的節點,其資料丟失直接影響使用者,也不能透過其它型別節點來重建,所以Updateserver最早拋棄HA模式,而改為透過Rootserver來選主:

OceanBase高可用實踐

Updateserver每次寫入都會生成一條日誌,每條日誌有一個惟一且單調遞增的日誌號, 各Updateserver向Rootserver彙報自己的日誌號, Rootserver選取日誌號最大的Updateserver為主併發放租約,備Updateserver同時需要向主Updateserver註冊,由主Updateserver發放租約。Updateserver使用一主多備的形式, 每次寫入必須要寫入多數派個節點成功才能應答客戶,寫入請求首先發送到主Updateserver,主Updateserver生成日誌並同步到備機,收到多數派個成功迴應以後應答客戶。如果收不到足夠多的迴應,則不會應答客戶端,該條寫入可能生效,也可能不生效。

由於要求寫入多數派個節點才算成功,所以主備間的網路延遲不能太高,目前OceanBase要求updateserver主備分佈在同城的不同IDC, 如果採取一主兩備的模式, 最大可以容忍一個同城IDC故障。

當某一臺機器同步日誌失敗時,主機會將其剔除在恢復之前不再向其同步日誌, 這對網路要求很高,如果網路連續出現抖動,則會造成可用性問題。在最新版本OceanBase, 將同步日誌的方式也改為Paxos方式,一條日誌只需要寫到多數派個結點上成功便為成功,不需要各臺備機順序迴應,進一步容忍短暫的網路問題。

雖然Updateserver去掉了對HA的依賴,但Rootserver仍然需要HA來選主,由於HA無法部署在兩個IDC,所以我們對IDC之間的容災使用的策略是在另外一個IDC部署一個備叢集,在主叢集出現故障時,透過人肉的方式將備叢集切換為主來提供服務。

基於這個原因,OceanBase 在0。5裡徹底取消了基於HA的主備機制,而是透過使用類似paxos的演算法來進行選舉:

OceanBase高可用實踐

讓程式自身投票來決出主備, 當一臺機器得到多數派的認可,它即可以成為主,這樣系統能容忍一定數量節點的不可用,比如,如果是2臺,則不能容忍有機器宕機,3臺則可以容忍一臺機器宕機, 3臺機器可以部署在不同的機房以容忍機房故障。

Updateserver仍然透過Rootserver來選主,但這樣也存在一個問題,當Updateserver和Rootserver同時故障的時候,Updateserver必須要等Rootserver恢復完成後才能恢復,增加了故障恢復的時間 。在後續的OceanBase版本中,將去除Updateserver這個單寫入節點,並將其選主的權力下放到自身,擺脫由Rootserver選主的局面。屆時Rootserver的工作會更為簡單,單點不會成為OceanBase的瓶頸。

基線資料

Rootserver/Updateserver是透過冗餘節點來進行容災,備節點一般不提供服務或只提供有限的服務,基線資料則是透過冗餘資料來實現高可用與擴充套件服務能力。透過冗餘3~6份資料來提供更多的服務能力。冗餘的資料不能儲存在相同的機器上,以避免機器宕機後損失可用性。同時在可能的情況下,資料需要分佈在不同的機架上,以抵禦整機架斷電或斷網,OceanBase在早期的實現中,為了簡化實現與對機器分佈的要求,未考慮資料分佈在不同的機櫃,曾出現過整機架斷網而造成服務不可用。

基線資料的副本數決定了一個叢集同時有多少臺機器可以宕機,如果使用三副本,則同時可以有兩臺機器宕機,每個基線資料結點都和Rootserver保持心跳,當該結點宕機以後,rootserver會檢測到並根據目前系統中所擁有的副本數量啟動複製,為了避免因網路抖動所帶來的不必要的副本複製,我們設定在安全的情況下(比如剩餘副本數大於1) 可以容忍副本丟失一段時間(比如8小時),當副本丟失超出該時長後才啟動複製。

副本數的選擇和叢集中機器的數量、單機資料量以及資料恢復速度相關,一般情況下會選擇至少3個副本,因為2副本情況下,如果出現一個副本丟失,叢集需要立即啟動複製,而此時叢集可能正處於請求高峰期。陽老師有一個關於副本數選擇的計算方法:

“假設總共有N個節點計算機,它們的平均無故障時間都是M,雲計算系統對一個數據副本丟失並進行復制的時間為T,則一臺計算機在T時間內出故障的機率是T/M,不出故障的機率是(1-T/M):

N臺機器在該時間內都不出故障的機率是(1-T/M)的N次方;

N臺機器在該時間內恰好有1臺出故障的機率是:(1-T/M)的(N-1)次方

T/M

N;

N臺機器在該時間內恰好有2臺出故障的機率是:

(1-T/M)的(N-2)次方

T/M

T/M

N

(N-1)/(2*1)

因此,N臺機器在該時間段內至少有兩臺機器故障的機率是:

P2(N, M, T)=1-都不出故障的機率-恰好1臺出故障的機率

因此,N臺機器在該時間段內至少有兩臺機器故障的機率是:

P3(N, M, T)=1-都不出故障的機率-恰好1臺出故障的機率——恰好2臺出故障的機率

因此假如N=1000,M=50,000小時,T=600秒,則

P2 (N=10臺,M=50,000小時,T=600秒) = 5。0*10的-10次方;

P2 (N=1000臺,M=50,000小時,T=600秒) = 6。1*10的-9次方;

P2 (N=5000臺,M=50,000小時,T=600秒) = 1。4*10的-4次方;

P3 (N=10臺,M=50,000小時,T=600秒) = 4。5*10的-15次方;

P3 (N=1000臺,M=50,000小時,T=600秒) = 6。2*10的-9次方;

P3 (N=5000臺,M=50,000小時,T=600秒) = 7。6*10的-7次方;

可以看出,當機器數量達到5000臺時,至少3臺機器出故障的機率低於百萬分之一,而至少兩臺機器出故障的機率高於萬分之一。因此採用3個數據副本時資料有比較高的可靠性。”

並計算出一個表格,假設故障時其它伺服器以25MB/s的速度恢復丟失資料:

OceanBase高可用實踐

MTBF為機器的平均無故障時間,從表中可以看出三副本同時喪失的機率是極低的。

基線資料的另一個較為普遍的異常為磁碟損壞, OceanBase儲存基線資料的角色為ChunkServer, ChunkServer並未使用RAID方式來使用磁碟,一塊磁碟損壞就意味著永久損失該盤上的所有資料,需要Rootserver從另外的機器上進行復制。 當ChunkServer檢測到該磁碟出錯(讀取或寫入失敗)時,會主動將該盤剔除並上報, 讓Rootserver啟動複製程式補足副本。

基線資料需要和增量資料合併而產生新的基線資料,這個過程是由每臺ChunkServer各自完成自己所負責的資料分割槽,即相同資料的幾個副本會各自己完成這個合併過程,為了保證各臺ChunkServer合併出來的新基線資料是一致的,每臺Chunkserver在彙報副本資訊的時候需要同時彙報校驗值,以檢查副本是否一致,如果出現不一致的情況,則是軟體有bug或資料有問題,ChunkServer保留兩個版本,解決問題後回退到上一個版本進行重新合併。這種問題出現一般都是軟體Bug, 根據之前的經驗,出現這種情況的時候,使用者有可能已經讀到不正確的資料,而造成這種問題的主要原因是Updateserver節點的資料不一致,我們透過改造Updateserver的日誌同步方式(由主備改為一主多備且要求多數派成功)和加強校驗後,這個問題已經得到杜絕。

跨資料中心容災

到目前為止,OceanBase可以部署在同城的不同IDC並容忍少數個IDC故障。OceanBase一般會在同城選擇三個不同的IDC進行部署。 目前還無法做到跨資料中心的容災。 主要原因是由於通訊距離的增加,異地資料中心之間的網路延時較高,無法做到同步複製資料,而透過非同步的形式進行復制則無法做到無損容災,我們目前透過一些手段,比如實時複製資料庫的redo log到異地資料中心,可以做到最壞情況只丟失幾秒的資料。

總結

相較於傳統的主備模式,OceanBase可以容忍少數派的節點損壞不中斷服務且不丟失資料,為很多需要高可用且不能丟資料的業務提供了共享儲存以外的解決方案。

OceanBase仍然在高速發展和逐步完善,包括可用性在內的各方面都在穩步推進,我們在目前也在嘗試將OceanBase以雲的形式提供給使用者, 我們接下來將介紹OceanBase雲平臺,請關注下一篇《OceanBase雲平臺簡介》。

本文作者:KB小秘書

原文連結

更多技術乾貨敬請關注雲棲社群知乎機構號:阿里云云棲社群 - 知乎