持續可用與CAP理論 - 一個資料庫系統開發者的觀點

技術瑣話發表於2019-04-22

本文作者為螞蟻金服OceanBase研究員日照,發表於2015年。

持續可用

本文主要針對金融資料庫,認為金融資料庫的持續可用包含兩點:一個是強一致性;另外一個是高可用性。

資料庫系統必須是強一致性的系統,這是因為資料庫系統有事務ACID的基本要求,而弱一致系統無法做到。業內也有一些流行的NOSQL系統,例如各種類Dynamo系統,如開源的Cassandra,對同一個最小資料單位(同一行資料)允許多臺伺服器同時寫入,雖然採用NWR機制處理衝突,但是由於不可能解決多臺伺服器之間的時序問題,而只能支援弱一致語義。弱一致語義的問題很多,例如無法支援複雜功能,無法構建嚴謹的測試體系,無法應用到核心場景。雖然弱一致性系統也有一定的應用場景,但本文認為其不符合核心業務持續可用的要求,不予討論。

高可用性可以有很多種解釋,實踐中最常見的解釋為:在一臺伺服器,一個交換機,一個機房,或者一個地區整體故障後,系統能夠在多長時間內恢復服務。當然,這裡的恢復服務是以保證強一致性作為前提條件的。如果能夠在秒級(10秒左右)恢復服務,本文認為這個系統是高可用的,絕大部分應用系統都能夠容忍硬體故障導致的秒級不可用。

CAP理論

CAP理論網上傳了很多版本,大致的意思是:一致性,可用性和分割槽可容忍性三者只能取其二,不可兼得。由於分割槽可容忍性是不可選擇的,因此,系統設計時只能在一致性和可用性之間權衡。這就帶來了一個很悲觀的結論:持續可用無法實現。然而,事實是這樣嗎?

首先,我們回到CAP理論的原始定義:

C(Consistency):A read is guaranteed to return the most recent writefor a given client

A(Availability):Anon-failing node will return a reasonable response within areasonable amount of time (no error or timeout)

P(PartitionTolerance):The system will continue to function when networkpartitions occur.

CAP理論的證明也比較直觀,如下:

持續可用與CAP理論 - 一個資料庫系統開發者的觀點

左圖中,假設有兩個節點N1和N2,N1和N2之間發生了網路分割槽(P),N1寫入新值y,N2一直是老值x,為了保證一致性(C),讀取N2總是返回失敗,違反了可用性(A)要求:任何一個沒有發生故障的節點必須在有限時間內返回結果,不允許為Error或者Timeout,系統只能保證CP。

右圖中,從另外一個角度看,假設總是要保證可用性(A),那麼,讀到N2中的老值x,由於x和最新寫入的y不同,違反了一致性(C)的要求,系統只能保證AP。

CAP理論本身毋庸置疑,證明可以參考Gilbert和Lynch合著的論文。

CAP中的A與高可用的HA

請讀者會到CAP理論中關於A的定義:CAP中的A要求任何一個沒有發生故障的節點必須在有限的時間內返回結果。然而,如果系統能夠做到當某個節點發生網路分割槽後,將它從系統中剔除,由其它節點繼續提供服務。雖然沒有滿足CAP中A的要求,但是,只要恢復時間足夠快,也符合高可用的要求。而高可用才是系統設計的本質需求,CAP中的A只是個理論上的需求。

CAP理論的作者Eric Brewer後來確實也寫過一篇文章來說明這個問題:<

Paxos與持續可用

Paxos是圖靈獎獲得者Lamport的經典之作,第一個版本的論文叫做:<

八卦完了Paxos,下面進入正題。Lamport和JimGray分別是分散式系統和資料庫領域的代表任務,同屬微軟研究院,不過也是共事多年才坐在一起聊兩個領域的問題。高可用是分散式系統的長項,為了實現高可用,首先必須至少寫三份資料(一主兩備)。這是因為,如果只寫兩份資料,當一份資料出現故障的時候,另外一份資料永遠無法證明自己是對,也無法證明自己是錯。這就是選舉的價值,類Paxos選舉協議允許在超過半數(Majority)節點正常的情況下提供服務。因此,當某臺伺服器,某個交換機,某個IDC甚至某個地區整體故障的時候,只要不超過整個系統的半數,系統都能夠很快從錯誤中恢復過來,而且完全自動,無需人工干預。

強一致性是資料庫的長項,做法就是強同步,Oracle,MySQL5.7,國內的MySQL定製版本,例如阿里、網易的MySQL版本都支援強一致性。強同步的問題在於效能損耗,例如傳統資料庫的執行模型(非執行緒池模型)一般為一個連線對應一個工作執行緒/程式,採用強同步模式後事務的延時必然延長,從而導致工作執行緒/程式數增多,高併發情況下日誌執行緒喚醒工作執行緒導致的上下文切換開銷也非常大。另外,為了實現高可用,必須同步至少兩個備庫,使得情況進一步惡化。

採用Paxos協議的持續可用系統有兩種常見的部署方式:

第一種部署方式比較簡單,也最為常見。有一個全域性Paxos服務,例如Zookeeper,它和其它機器之間保持租約。Master和兩個Slave之間保持強同步,事務至少要寫入到Master和其中一個Slave才可以返回成功。同一時刻對於同一份資料只有一個Master,全域性Paxos服務負責選舉,當Master出現故障時,選舉日誌號最大的Slave接替原來的Master繼續提供服務。

持續可用與CAP理論 - 一個資料庫系統開發者的觀點

第二種部署方式比較純粹,只出現在少量的分散式資料庫中,例如Google Spanner,OceanBase1.0。Leader(相當於Master)和Follower(相當於Slave)之間直接採用Paxos協議進行資料同步和選舉,相比第一種方案,這種方式實現複雜度要高很多,換來的好處是當機恢復時間更短,系統更優雅。

持續可用與CAP理論 - 一個資料庫系統開發者的觀點

共享儲存與硬體解決方案

資料庫領域經常採用共享儲存來解決強一致性問題,主庫將redo日誌持久化到共享儲存,如果主庫故障,假設共享儲存是持續可用的,備庫可以從共享儲存中讀取日誌恢復系統。共享儲存與share-nothing架構的強同步有何區別呢?共享儲存模式下只需要部署一個主庫和一個備庫,而share-nothing架構下強同步至少需要一個主庫加兩個備庫。為什麼呢?假設share-nothing架構只部署了一個主庫和一個備庫,只要任何一臺機器,即使是備庫當機,為了保證強一致性,整個系統都無法提供服務。顯然,這樣的系統在網際網路業務中幾乎沒有應用場景。

共享儲存本質上是硬體解決方案,相比Paxos解決方案,優勢是簡單成熟,在商用資料庫中廣泛使用。問題在於成本高,且依賴硬體本身高可靠和高效能,也無法跨IDC部署,只能容忍單臺伺服器故障,無法容忍單個IDC故障。

強同步效能

資料庫的效能分為兩個方面:

單個事務的延時:由於多了一次同步操作,單個事務提交的延時加長了。設計系統時能夠做的事情是將同步兩個備庫和主庫寫磁碟這三個操作完全並行起來,使得增加的額外延時只是三個操作的最大值,而不是三個操作之和。

系統的吞吐量:本質上看,強同步是否影響吞吐量取決於主備之間的網路頻寬是否成為瓶頸。在採用萬兆網路卡或者兩塊千兆網路卡的情況下,吞吐量基本沒有影響。

理想的系統應該是一個全非同步的系統,避免強同步佔用執行緒/程式等執行資源,且不應該帶來額外的上下文切換。日誌同步的優化有一些關鍵點,例如:組提交(GroupCommit),減少日誌緩衝區的鎖衝突,非同步化,避免不必要的上下文切換,資料庫提前解行鎖避免熱點。具體可以參考論文:<>。我參與實現的OceanBase系統強同步對單個事務帶來的額外延時只是一次網路同步,同一個機房內在0.5ms左右,同城的多個機房之間只有1ms左右,對系統吞吐量的影響也只有5%~10%左右。也就是說,如果實現做到極致,強同步的效能不會是問題。當然,這就要求將持續可用看成資料庫架構的核心目標,針對這個需求重構資料庫的執行引擎。

與效能相關聯的一個問題是成本。前面已經提到,基於Paxos的持續可用方案至少需要一主兩備,如果資料總是有三份,確實比較浪費。一個做到極致的系統應該能夠只需要兩個副本,第三個副本只儲存redo日誌即可。

引入選舉的難點

假設在關聯式資料庫的基礎上引入全域性Paxos服務,是否能夠解決高可用問題呢?理論上確實是可以的,不過實施起來難度也不小。這是因為,即使是Zookeeper這樣成熟的選舉服務,使用過程中總是會遇到各種各樣的問題,如果期望應用到核心業務,需要對Zookeeper系統完全的掌控力。也就是說,假設Zookeeper這樣的服務出現問題,需要能夠FixBug,而不是簡單重啟解決。另外,也需要做一套模擬各種異常的測試系統,確保不會在異常的情況下出現一些嚴重的問題,例如Zookeeper選出雙主導致資料不一致。總而言之,做一個持續可用的選舉服務並不是簡單地使用開源軟體,這是一個全域性服務,要麼不做,要麼就深入下去做到完全掌控。

跨機房問題

跨機房問題分為兩類:同城以及異地。前面已經提到,無論如何實現,強同步方案中單個事務至少增加一次網路同步延時。對於同城場景,如果網路環境比較好,例如公司的資料庫服務有專用的光纖或者頻寬比較高,那麼,增加的延時在1~2ms(光折射傳播的時間+交換機處理時間),業務是完全可以接受的。因此,可以做到同城持續可用,單個IDC故障時,能夠在保證強一致的前提下很快恢復服務。

對於異地場景,由於網路延時較大,例如100ms左右,業務往往不可接受。因此,無法做到跨地域持續可用,整個地區故障時,要麼犧牲一致性,要麼犧牲可用性,如果選擇可用性時可能會丟失最後幾秒內的資料。當然,實際上業務上往往會組合使用各種柔性解決方案,例如涉及到錢的業務停服務,其它業務容忍極端情況下的資料丟失;或者在外部系統中記錄一些資訊,例如記錄哪些使用者的資料不一致,出現問題是禁止這些使用者的寫服務,其它使用者正常提供服務;或者DBA採用各種辦法補資料,等等。

小結

總而言之,在金融資料庫中,由於強一致性是必選項,因此,要做到持續可用比較困難,但也並不是不可能,CAP和持續可用並不矛盾。成熟的商業資料庫都是基於共享儲存的,不過基於Paxos的持續可用方案開始越來越多地應用到核心場景,例如GoogleSpanner,Microsoft SQL Server雲版本,Amazon DynamoDB,而AliababaOceanBase也在金融核心場景得到了驗證。同時,筆者認為,採用Paxos協議,雖然工程難度很高,但是,只要在實現上做到極致,在同城的情況下,可以容忍單個IDC故障,且效能損耗非常小;而在異地的場景,考慮到光速不可突破,往往由業務在一致性和可用性之間權衡。越來越多的雲資料庫將會採用Paxos來實現持續可用。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31562044/viewspace-2642175/,如需轉載,請註明出處,否則將追究法律責任。

相關文章