天天看點

美團超大規模資料庫叢集高可用設計實踐

作者:散文随風想

對資料庫而言,非常核心的就是如何保證其高可用性。本文圍繞4個方面的内容展開,包括高可用簡介、高可用部署、重點子產品的設計思考以及對未來思考。希望能夠對大家有所幫助或啟發。

一、出品人說

在資料庫叢集規模迅速擴大的背景下,如果出現故障,如何快速恢複成百甚至數千個叢集的資料和服務,是很多大型網際網路企業面臨的重要挑戰。線上部署了幾十萬的微服務,資料庫結構和拓撲随時在發生變更,系統重構、核心更新、硬體裝置汰換、機房搬遷等等,也都會對資料庫的穩定工作産生一定的影響。

作為整個IT系統中最為重要、最為底層的服務,即便遇到了極小機率事件的沖擊,也會造成非常大的影響。對美團資料庫團隊來說,“低垂的果實已經摘完”,我們開始着力應對這些小機率事件對業務造成的沖擊。

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

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

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

美團超大規模資料庫叢集高可用設計實踐

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

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

二、高可用簡介

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故障。

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 美團高可用架構的發展曆程

三、高可用部署

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

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

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

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

美團超大規模資料庫叢集高可用設計實踐

圖6 高可用架構圖

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寫的。

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

四、重點子產品設計

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

故障發現有兩個核心名額:

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

先說漏判,如下圖8所示的故障探測通道,每個探測通道完全獨立,如普通探測通道,心跳探測通道、從庫探測通道等完全獨立決策,誰先發現都可以作為決策依據,現階段這些通道都是在服務端主動并發發起探測。

另外一方面就是業務端,通路中間件有業務端的報錯,也納入故障探測和決策,這個是業務視角的故障,不管什麼問題隻要業務達到有損門檻值就可以判斷決策,這部分還在建設中。綜合多通道、以及用戶端和服務端判定,哪一個通道發現了問題,直接開始做決策,不受其他通道影響,這是解決漏判問題的政策。

美團超大規模資料庫叢集高可用設計實踐

圖8 故障發現

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

2.故障選舉(選舉因子、選舉政策)

所謂故障選舉一定是多個從庫,一主一從不存在選舉。美團的MySQL叢集現狀是一主多從,是以選舉異常複雜,因為我們要保證容災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.資料一緻性(四個風險及解決方案)

為什麼要保證資料一緻?在我們現在這種規模的業務場景下,可用性優先政策已經沒辦法覆寫所有的業務場景,但是在主從架構下面,資料丢失又無處不在,參考圖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 可用性優先/一緻性優先

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的狀态機

    5.配置下發(雙Region下發)

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

    美團超大規模資料庫叢集高可用設計實踐

    圖17 雙Region下發

    五、未來思考

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

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

    繼續閱讀