超大規模資料庫叢集保穩系列之一:高可用系統

美團技術團隊發表於2023-05-12
基於過去多年在大規模資料叢集保穩方面的實踐經驗,我們希望能夠跟業界進行一些技術交流,美團技術團隊舉辦了第75期技術沙龍。本文整理自主題分享《美團資料庫的高可用系統》,系超大規模資料庫叢集保穩系列的第一篇文章。對資料庫而言,非常核心的就是如何保證其高可用性。本文圍繞4個方面的內容展開,包括高可用簡介、高可用部署、重點模組的設計思考以及對未來思考。希望能夠對大家有所幫助或啟發。

| B站影片美團資料庫高可用系統

00 出品人說

在資料庫叢集規模迅速擴大的背景下,如果出現故障,如何快速恢復成百甚至數千個叢集的資料和服務,是很多大型網際網路企業面臨的重要挑戰。線上部署了幾十萬的微服務,資料庫結構和拓撲隨時在發生變更,系統重構、核心升級、硬體裝置汰換、機房搬遷等等,也都會對資料庫的穩定工作產生一定的影響。作為整個IT系統中最為重要、最為底層的服務,即便遇到了極小機率事件的衝擊,也會造成非常大的影響。對美團資料庫團隊來說,“低垂的果實已經摘完”,我們開始著力應對這些小機率事件對業務造成的衝擊。

資料庫穩定性保障的破局之道:一方面是提升平均無故障間隔(MTTF),另一方面是提升應急響應能力,即縮短平均修復時間(MTTR)。在這個兩個目標的指引下,美團資料庫團隊從能力驅動和故障驅動兩個維度來構造整個穩定性保障的閉環體系。

從能力驅動的角度,我們借鑑了Google的穩定性保障體系。在最底部的三層,透過故障演練/預案建設、覆盤、可觀測性的維度,思考怎麼縮短故障處理時長;中間四層更多的是圍繞研發需求、設計、上線、變更管控來降低故障的發生機率;頂層是產品運營,即透過面向內部使用者的運營,指導業務對資料庫進行選型和合理的使用,不斷提升產品和平臺易用性,並針對業務特點提供相應的解決方案。

從故障驅動的角度來說,包含事前預防和發現,事中故障定位,事後恢復、覆盤和改進等等。從事前、事中、事後的全生命週期以及軟體開發的各個階段,全面提升管控和應急響應能力。

圖1 資料庫穩定性保障的破局之道

基於過去多年保穩定方面的實踐,本次沙龍將從如何提升進攻和防守能力,如何提升快速恢復能力,以及在進攻、防守、恢復形成閉環後,如何讓人、系統、流程更好的協同和應對大規模故障幾個方面,圍繞資料庫的高可用系統、資料庫攻防演練建設實踐、資料庫容災體系建設、資料庫自治服務平臺建設等4個議題進行介紹。希望能給從廣大資料庫從業者、業務研發人員帶來啟發和幫助。

01 高可用簡介

1.1 面臨的挑戰

首先分享下美團資料庫高可用面臨的問題和挑戰,主要從3個層面進行展開:

第一個挑戰是例項增長越來越快。下圖1擷取了2019年1月到2022年1月的資料,可以明顯地看到例項規模的增長非常迅速,在大規模場景下,如何保證每一個例項的高可用性是一個非常大的挑戰。大家都知道,保障幾臺機器穩定執行,跟保障幾萬臺甚至幾十萬臺機器的穩定執行,其複雜度完全不在一個量級。

圖2 例項增長曲線

第二個挑戰是可用性(RTO)要求越來越嚴。美團業務型別偏線上實時交易,對系統可用性有非常高的要求,特別是即時配送要求更高。在業務發展的早期階段,體量併發也不高,對系統可用性要求可能只有99.9%。但是隨著業務體量快速增長,對系統可用性的要求就會不斷增加,特別是比較偏底層的資料庫系統,從99.9%到99.99%甚至更高。

圖3 系統可用性對應的當機時間

第三個挑戰是容災場景的複雜性。容災場景主要分成三個層面,第一個是常規容災,比如日常軟體、硬體或者網路故障;第二個是AZ容災,即機房層面,如機房斷網、機房當機等;第三個是Region容災,即更大空間容災,典型的是城市級容災,目前主要還在解決AZ級容災,分如下五個階段:

圖4 AZ容災能力等級

從圖4可以看到,我們將AZ容災分設第0至第4共5個階段,簡稱L0-L4。隨著等級的提高,場景越來越複雜,相應的規模也越大。從容災規模維度看,單點->單個叢集->某個業務依賴的叢集->AZ內的叢集,不同規模要求的能力是完全不一樣的,除了規模之外還有容災的場景也會在變化。

  • “L0-L1”這兩個等級側重面向常規容災,是例項級容災。
  • “L2-L3”這兩個等級側重面向AZ容災,相比L1有非常大的跨越,因為既要解決“L0-L1”面臨的常規容災問題,還要解決一個很核心的問題,即整高可用自身是否能夠快速恢復,以及高可用依賴的下游服務是否具備容災切換能力。由於高可用本身是一個系統,它有資料面和控制面,有上下游依賴,所以先保證自己是可用的,才能保證資料庫的RTO和RPO。
  • L4,從L3到L4又有一個很大的跨越,因為L3是的規模是相對可控的,而L4直接是斷AZ的網路,AZ的大小不同,它涉及更大場景是更真實的AZ容災。

1.2 發展歷程

接下來,分享一下美團高可用系統發展歷程。總的來說,美團的高可用發展歷程是根據不同的階段的矛盾和挑戰,做出的相應解決策略和方案。到目前為止,有三次比較大的系統架構迭代:

  • 第一代架構是2015年之前,稱為MMM(Multi-Master Replication Manager for MySQL),該架構包括接入層VIP、Agent和Manager,這架構本身存在很多問題,比如VIP接入無法支援跨機房、跨網段;Agent和例項綁死,本身也沒有高可用,維護起來比較困難;Manager還是單點。
  • 第二代架構是2015-2019年,稱為MMHA(Meituan Master High Availability),是在MHA的基礎上結合美團資料庫生態定製的架構,解決了第一代架構中VIP接入和Agent誤判的一些問題,但在2019年以後,由於例項規模變得很大且增長迅速,該架構管理起來異常複雜,Manager是單點且本身沒有高可用。同時,2019年整個PAAS在演練機房故障,所以當時這個架構逐漸暴露出各種穩定性問題。
  • 第三代架構是2019年,新開了基於Orchestrator定製的高可用系統,實際開始時間是2018年,2019年開始灰度。當時MGR在業界已經有些公司在使用,MGR透過分散式協議來解決高可用難題,我們對此進行了深入的思考:我們是否能引入一個類似分散式協議解決高可用系統面臨的問題,本質上就是把MGR中內建的分散式協議放到高可用系統實現。

後來根據這個想法落地的架構就是當前的高可用系統,是一個Raft Group,多節點、多機房部署。以前主要關注主從切換,但新系統類似八爪魚,所有在叢集裡的節點都是統一託管,如主庫、從庫、Ripple(後續有說明)等;另一方面,它是一個高可用、高效能、大規模併發處理架構,我們部署了多個Raft Group分組來託管不同地域和服務等級資料庫叢集。除此之外,我們也正在思考新一代去中心化的新架構,將在文章的最後一個章節進行介紹。

圖5 美團高可用架構的發展歷程

02 高可用部署

2.1 高可用架構(資料流、控制流)

這部分主要分兩條線:控制流和資料流。

  • 資料流:如果業務應用要訪問資料庫,它是如何拿到資料的,一個SQL過來是如何把資料返回回去的,業務應用透過訪問中介軟體看到MySQL的拓撲,資料流比較簡單,也是業界比較通用的做法。
  • 控制流:業務應用要透過訪問中介軟體來訪問到正常資料庫拓撲,需要用高可用元件來解決故障轉移難題。

由下圖6可看出,高可用元件分四個部分:HA Core是經典的3節點Raft Group部署(也可以是多節點部署);HA平臺是管控系統,如主動切換、狀態機檢視、兜底等;HAservice是HA的API服務,負責跟外圍系統交付;排程系統包括(Scheduler、Worker),是一個流程排程服務,處理狀態機的輪轉。後設資料儲存是外圍依賴的核心服務,負責基礎配置的管理,當配置變更後會透過它下發到所有的中介軟體節點,保證業務看到的是正常的資料庫拓撲。

圖6 高可用架構圖

2.2 高可用部署(HA Core、微服務、資料層)

下面我們圍繞4個高可用元件來展開介紹一下,高可用部署在應對AZ級容災或Region級容災的策略。

圖7 高可用部署架構

一是HA Core部署,它有三個特徵:一是多Region,如下圖6所示,以紅色線為分界,左邊是Region 1,右邊是Region 2;二是多AZ,每一個HA Core是3AZ部署;三是多叢集,每個HA Core的3節點叢集會託管MySQL千級別例項。

二是微服務,有同步服務、排程服務和配置中心。

  • 同步服務:簡單來說,我們的工程師在RDS申請叢集或DB之後的資訊會全部同步註冊到HA Core服務裡面去,相當於HA Core是一個“八爪魚”,它能發現這些資訊。
  • 任務排程:它也包括API Service、Scheduler和Worker,主要做狀態機任務執行。這兩個服務都是多Region、多機房部署,它們本身沒有狀態。
  • 配置中心:業務應用訪問中介軟體和高可用之間的資料同步紐帶,是MySQL的節點發現和處理的核心元件,是雙Region部署,有自己的元件,比如有API、Config和Consistency。

三是資料層,微服務除了配置中心,其他服務沒有狀態,因為狀態都在資料層,資料層服務都是MGR叢集,而且這些叢集各自作用不一樣,MGR是單Region寫、多Region讀,所以這裡我們回到最開始說的Region容災,這些資料需要做單元化或者隔離,現在這些叢集還是單Region寫的。

四是管控層,它是正常的平臺服務,常規化的部署。

03 重點模組設計

3.1 故障發現(減少漏判、降低誤判)

故障發現有兩個核心指標:

  • 第一個指標是不要漏判,如果故障沒有判斷,那RTO其實根本就不生效。
  • 第二個指標是降低誤判,因為我們知道RTO不可能等於0,即RTO一定對業務有影響,如果一天誤判幾次,那對業務是無法接受的,對業務是有損的。

先說漏判,如下圖8所示的故障探測通道,每個探測通道完全獨立,如普通探測通道,心跳探測通道、從庫探測等完全獨立決策,誰先發現都可以作為決策依據,現階段這些通道都是在服務端主動併發發起探測。另外一方面就是業務端,訪問中介軟體有業務端的報錯,也納入故障探測和決策,這個是業務視角的故障,不管什麼問題只要業務達到有損閾值就可以判斷決策,這部分還在建設中。綜合多通道、以及客戶端和服務端判定,哪一個通道發現了問題,直接開始做決策,不受其他通道影響,這是解決漏判問題的策略。

圖8 故障發現

再說減少誤判,我們引入了多節點協商機制,比如我們遇到某些問題會引入“民主”決策讓大家發揮更多意見,最終彙總得出結論。HA Core是多節點,當每個節點獨立探測,探測後也會獨立去做判斷和分析,如只有一個Follower節點認為故障是沒用的,還需要Leader的分析並向其他Follower節點發起協商共同決策,只有大多數節點認為故障才會把它確定為故障,會註冊故障並進行故障處理流程。圖中的Backend DB是Raft Group每個節點各自獨立的儲存,各自探測的拓撲以及判定決策資訊等都存在本地。

3.2 故障選舉(選舉因子、選舉策略)

所謂故障選舉一定是多個從庫,一主一從不存在選舉。美團的MySQL叢集現狀是1主多從,所以選舉異常複雜,因為我們要保證容災N+1、多AZ甚至多Region部署,選舉時選誰做主庫就非常重要,主要有兩個影響因素:選舉因子和選舉策略。選舉因子+選舉策略 = 決定誰是新主。

(1)選舉因子是影響選舉的核心要素,一次故障有20多個選舉因子會共同影響如何排序。

圖9 選舉因子

舉兩個例子,第一個是版本,一主五從的叢集可能有三個版本,如果讓最新的版本作為新主就會有問題,要儘量不讓它作新主,因為如果新主的版本是最新的,但從庫都是比他落後的低版本,就會出現一些相容性問題;第二個是權重,假設其他因子都一樣,但存在運維和例行維護的情況下會人為說把權重降低,或標記一個例項不能作為新主,那麼權重100的比權重50的有更大機會成為新主。每個選舉因子都有權重,最終做綜合排序,如版本、binlog格式、權重、伺服器配置等,綜合選舉因子的選舉結果是1M(first master)。

但1M並不一定是最優,有業務是北上跨Region部署,如之前主庫在北京,按照選舉因子排序選出的1M到上海去了,顯然是業務無法接受的,因為老主庫在北京說明絕大部分業務部署在北京,一旦讓它跨Region寫入到上海,那麼RT會增加很多,所以引入了選舉策略。

(2)選舉策略是同機房優先>同中心優先>同區域優先,是一個靈活的fallback策略。按照選舉策略重新選舉一個新主(稱為2M),如果2M和1M是重疊的,就認為這個1M是滿足業務訴求的Master,會將1M作為最終的主庫。但有時候1M和2M的排序相差很大,這時我們儘量讓那種沒辦法改變的因素以它為基礎,把其它能改變的因素對齊,比如地域很難改變,但是要改位點等容易改變,最終權衡後選舉出新主庫。

圖10 選舉策略

舉例

  • 如圖11(主庫M,從庫S1、S2、S3、S4四個例項),S2的選舉規則(promotion rule)是一票否決的Must Not,那它一定不能做主庫,即使選不出來其他,它也做不了主庫。
  • S1和老主庫是同AZ的即都是AZ1,S1比AZ2的S3和S4有更高優先順序,即更大的機會作為新主。
  • S4權重100,S3權重90,S4比S3權重更高,即使S4是獨享容器,它也有更高的選舉權。

圖11 選舉示例

這個例子說明最終選舉出的主庫是綜合考慮後的排序,受各種因子影響。

3.3 資料一致性(四個風險及解決方案)

為什麼要保證資料一致?在我們現在這種規模的業務場景下,可用性優先策略已經沒辦法覆蓋所有的業務場景,但是在主從架構下面,資料丟失又無處不在,參考圖12為例,資料丟失的風險點比較多:

  • 問題1,可能binlog未實時落盤。
  • 問題2,IO執行緒沒拿到最新資料。
  • 問題3,SQL執行緒沒有和IO執行緒對齊,包括從庫之間binlog位點也不一樣。
  • 問題4,從庫不完整事務問題,在主庫事務提交時它是完整的,但是它透過IO執行緒同步給從庫時不是按事務粒度去同步而是按事件event粒度同步,如果事務未完整接收也可能會產生資料丟失不一致。

圖12 四個風險

  • 針對問題3和問題4,其實歸納一下就是說只要有從庫拿到資料,不管是否對齊,我們是有策略能夠保證一致性,這個策略叫S1,只要資料同步過去了則就可以透過S1保證一致性。
  • 針對問題2,就是主庫Event,沒有任何一個從庫有獲取全,這種情況必須解析老主庫binlog以及計算binlog位點並獲取到資料,並在切換中補齊資料,即在開放給業務寫流量之前,會將資料給新主庫補全保證一致性,這個策略叫S2。
  • 但S1+S2也不能保證0RPO,伺服器當機時拿不到老主庫binlog,沒有辦法計算、解析和處理,不能保證0RPO,大概有20%到30%的比例。

接下來,講一下針對老主庫當機拿不到資料時的解決方案(這個叫策略S3)。在此,也參考MySQL主從庫架構透過IO執行緒和SQL執行緒去解決一致性的思路。第一個難點,IO執行緒要儘量把資料拿全,這是非常關鍵的點,也是很難的事情;第二個難點,SQL執行緒能夠快速把資料應用下去,達到這兩方面才能保證0RPO。

第一個難點解決方案如圖13所示,核心是Ripple,它是一個高效能的binlog訂閱伺服器,作用類似IO執行緒,保證快速的獲取binlog。第一個特性是它的效能極高,因為普通從庫IO執行緒除了處理binlog接收請求外,也處理很多比如寫Relay log、一些鎖邏輯處理,以及配合SQL執行緒一致性的工作,而Ripple的任務就是快速將資料全部拿過來而不用處理其它邏輯,binlog同步速度是普通MySQL IO執行緒的3倍以上;第二個特性是可以配置強一致,支援半同步機制,如果你認為可以犧牲RTO,比如可以犧牲3分鐘但不能丟失資料,那麼配置多副本的半同步超時策略(如3分鐘),由於Ripple的效能高,實際超時時間遠遠小於這個值,退化機率非常低;第三個特性,它本身是一個存算分離的架構,即Ripple是輕量級容器+EBS雲盤,用這樣一種架構來保證資料完全。

圖13 基於Ripple的一致性方案

第二個難點是事中從Ripple補資料,Ripple畢竟不是普通的MySQL,所以需要HA去相容,但HA處理資料比SQL執行緒靈活很多,因為SQL執行緒在需要實時處理資料來保證一致性,而HA只有在故障期間才處理資料,可以拉長RTO做很多定製。還有這裡提到的RPO≈0,為什麼是近似,因為雖然可以做到RPO=0,但要接受RTO的損耗。如果你既要RTO,又要RPO,那麼可以在策略靈活配置。

在目前業務規模下沒辦法兼得RTO和RPO,如果想要RTO就要犧牲一部分RPO或者反過來。本身裡面有一些不可控因素會影響核心指標,比如事務的大小、延遲、完整性等,我們將這些配置透過策略開放給業務,讓業務自己去決策。舉個例子,如果你的業務有很多大事務,但你又要想0RPO,那麼你就需要配置更長的RTO損耗。

  • 可用性優先:可根據業務特性自定義,承諾RTO不保證RPO。
  • 一致性優先:可根據業務特性自定義,保證RPO但不會無限制,RTO會控制上限。
  • 不可控因素:事務大小、延遲、事務完整性等。

圖14 可用性優先/一致性優先

3.4 多機房高可用

常規場景,Leader故障後會在4秒之內快速選舉一個新Leader出來繼續工作,但也有一些場景,如下圖15所示,MySQL Master和HA 的Leader都在AZ1,如果AZ1當機之後怎麼辦?其實就出現右邊這個圖。老Leader在處理AZ1裡的MySQL節點故障的同時,由於自身Leader也在AZ1,會中斷老Leader的處理狀態機並選舉一個Leader,但新Leader並不知道老Leader狀態機如何處理,就直接導致切換的失敗。

圖15 多機房高可用

多機房高可用的的核心解決思路是保證各個節點之間狀態機的連續性。所謂狀態機的連續性,就是Leader實時把狀態機同步到所有Follower節點,一旦Follower節點重新變為Leader點後,它會繼續老Leader的狀態機,會有動作的臨界狀態判斷。如下圖15所示,它根據執行的代價判斷是回滾還是繼續執行,如果回滾,就會把老Leader狀態機全部回滾之後從零開始處理;另外一方面,如果由於叢集的拓撲和狀態被破壞了,導致回滾狀態機比較麻煩或回滾不了,那麼就會繼續執行老Leader狀態機沒有執行完的動作。

保證多節點狀態機連續性:

圖16 保證各個節點之間狀態機的連續性

  • 狀態同步:Leader實時將狀態機透過Raft同步到所有的Follower節點
  • 臨界狀態:根據執行代價確定的狀態機臨界點
  • 回滾:新Leader執行狀態機回滾,包括對應的操作
  • 繼續:新Leader繼續執行老Leader的狀態機

3.5 配置下發(雙Region下發)

由於配置服務是雙Region部署,分為同Region下發和跨Region下發。同Region下發會寫到儲存層,而config-server會更新最新配置,並將配置並推送到客戶端。跨Region下發,比如說北京、上海和深圳都有業務服務節點,最終把它推送下去的時候也會走一致性服務(Consistency-Server),即一旦某個Region更新後,我們會把資料推送到另一個Region裡,Region之間的資料完全一致,如果另外一個的Region有業務服務節點,就會繼續走同Region下發流程。

圖17 雙Region下發

04 未來思考

最後,分享一下對高可用未來的一些思考,主要包括以下三個方面:

  • 提升容災能力,主要是AZ級容災和Region級容災。這兩方面我們還在建設中,AZ級容災需要減少依賴,不能減少的需要AZ級閉環獨立部署,以及提升大規模併發處理的能力等;Region級容災方面,我們在做一些單元化的思考和方案,儘量讓包括資料層等所有服務閉環,不要跨區域訪問。
  • 去中心化架構。業界也有資料庫把高可用內建到MySQL,如MGR,內建到MySQL有非常多的有優勢,但對於美團一主多從架構是現狀前提。另外,MGR架構對網路抖動的容忍度較低,以及對請求延時有一些增加,導致大部分業務場景沒法接受。所以,我們在做另外一種思路,即把高可用內建到Proxy程式,讓Proxy自帶資料庫高可用的能力,跟內建到MySQL的思路類似。
  • 去依賴化、叢集化。將HA的Service、Scheduler和Worker及配置中心等下游依賴去掉,希望內建到Proxy程式後,內部資料透過Raft/Gossip協議同步而不再依賴中心化服務,讓它完全做叢集化,這也是我們2023年在思考的策略。

| 在美團公眾號選單欄對話方塊回覆【2022年貨】、【2021年貨】、【2020年貨】、【2019年貨】、【2018年貨】、【2017年貨】等關鍵詞,可檢視美團技術團隊歷年技術文章合集。

| 本文系美團技術團隊出品,著作權歸屬美團。歡迎出於分享和交流等非商業目的轉載或使用本文內容,敬請註明“內容轉載自美團技術團隊”。本文未經許可,不得進行商業性轉載或者使用。任何商用行為,請傳送郵件至tech@meituan.com申請授權。

相關文章