饿了么异地双活数据库实战
https://mp.weixin.qq.com/s/Z9PhwylHywhiOTTc5RLoLg
虢國飛,餓了么 DBA負責人
從事數據庫行業10+年,專注于MySQL、PgSQL、MSSQL等數據庫領域的管理、研究和平臺的研發等工作,目前負責餓了么數據庫團隊的管理和數據庫維護方面的工作。
我今天分享是餓了么在數據庫和多活數據庫這塊的實戰經歷,供大家參考。
主要分享以下五點:
1、多活當中的難點
2、多活的架構
3、數據庫改造
4、DBA 挑戰
5、收益與展望
一、多活當中的難點
我們先來看一下多活的第一個難點:要考慮做多活到底是同城的多活還是異地的多活,跨地域網絡延時是現階段很難突破的點,因為餓了么面臨的是異地的多活,所以我們需要基于延時這個前提來考慮方案。
從北京到上海中間有30毫秒的延遲,這個會帶來什么問題?我們接下來會講。
上圖是同城和異地多活不同的點,復雜性和可拓展性對架構的影響方面會有很大的不同。
我們挑幾個點講一下:
1、如果只是做同城多活的話,像30毫秒的延時不需要考慮,因為同城的延時通常只有幾毫秒,跟同機房差不大。
2、如果是異地30毫秒的延時就需要重點考慮了,因為如果是反復調用的應用,放大的時間就不只是30毫秒了,可能是300毫秒、500毫秒,對很多應用來說是不可接受的。
在可擴展性方面如果做的是異地多活的話,你的可擴展性理論上來說沒有太多的邊界。我們做同城多活只能在上海機房里面選,如果是異地多活,可能是全國甚至是全球都可以選。
還有一個比較難的問題,就是怎么保證數據的安全。多活數據可能面臨多個寫入點,可能會錯亂、會沖突、循環復制、數據環路等問題,這種情況下怎么保障一致性。如果這些沒有考慮好之前,你是不能上多活方案的,多點寫入的風險對數據的考驗是很大的。
綜合考慮下來我們選擇了異地多活,所以這些問題我們都需要克服,也意味著會面臨很多的改造。
如何解決跨機房延時對業務的影響,包括各種抖動甚至是斷網的問題。怎樣有效區分我們訪問的流量,最大限度地保障用戶的訪問落在正確的機房,這個都是需要解決的難點。
我們采取了一些措施:
1、盡量把業務做成類聚的,讓一個用戶的訪問落在同一個地方。
2、不是所有的業務都有多活特性的,還可以有全局使用的業務(比方用戶數據),所以需要做業務類型劃分。
-
在服務劃分這一層怎么定義業務調用的邊界,還有我們基于什么對流量和用戶做劃分的呢,目前根據我們的業務特點使用的是地理圍欄(POI),用戶、商戶、騎手當前所在的地理位置是我們入口流量劃分的依據。
-
再看看路由控制這一塊,除了入口流量這一層做了機房的劃分,還在內部使用了虛擬的Shardingkey,ShardingKey會把全國流量分成多個部分,并且與POI標簽綁定,這樣就可以把邏輯ShardingKey和物理位置對應起來,切換的時候訪問就可以隨ShardingKey分流到不同的機房。APIRouter就是為了完成這個工作的,它會根據配置的規則把Shardingkey對應的流量分到對應的機房。
-
臟寫預防方面,為防止數據沖突,我們也需要業務配合做一些多活規則的改造,這些規則對業務還是有一些侵入性的。另外SOA-Route就是內部跨業務調用的訪問路由。還有一個DAL,就是數據庫的代理層。
業務訪問在我們多層的路由控制下,理論上應該能正確路由到合適的機房,如果超越規則或者沒有按規則改造的意外流量真正穿透到DAL這一層的時候我們是強制拒絕的,因為底層認為這個訪問是屬于異常的調用,流量走錯了機房,這時候就會拒絕。所以我們寧愿讓他失敗也不能讓控制之外的數據進來,這樣才能保障規則和數據的可控性。
-
數據一致性方面我們有一個重要的DRC數據同步組件,數據庫這塊有一些自增的控制,DBA還研發了一個數據一致性校驗的工具(后面會介紹)。
二、多活的架構
粗略過了多活的一些難點和我們的應對方案后,我們現在來看一下整個多活的架構。這個上面是我們從入口流量、分流控制、數據多機房同步,包括各個重要組件的架構等。還有里面有globol zone這一項,它是我們剛剛講的需要全局依賴的業務會把它放在globol zone里面。
DRC這是做多活時相當重要的組件,主要解決數據在多個機房當中的同步復制。我們從北京機房寫入的數據,會同步到上海的機房。上海的機房寫入的數據也會通過DRC這個組件同步到北京的機房。大家可以看它其實包含三塊服務,Replicator、Applier和Manager,一個收集變更數據、一個將變更數據寫入到另一個機房,另外一個是做管理控制。
DB架構這塊我們有兩類(準確講還有一類是多推的,比較少),第一類是ShardingZone,不管是數據寫入還是訪問都是本機房提供,出問題的時候也只是流量的切換,并不涉及到底層的變動,這個是真正多活的架構。
還有一種是剛剛講的,有些沒有辦法做業務分區的,是globolZone的架構,寫是集中在一個機房,讀在本地機房完成。大家可能會想到globalzone這種架構會天然面臨一些剛剛講的數據延遲的問題,所以這塊我們的定義是一些寫入量不大,訪問量大,對數據延時是不那么敏感的業務就可以放到這里面來。
三、數據庫改造
多活項目我們調研大概花的時間有半年左右,但真正做改造的時候時間是相當短的。從啟動這個項目到真正上線就用了三個月左右的時間。那時候時間是相當緊的,大家可以看一下我列舉大的為配合多活數據庫所做的改造項目。
首先面臨的問題,就是我們要把數據全量的從一個機房導入到另外一個機房,這個不光有測試環境還有生產環境都要全量的同步。我們數據有幾百T數據,幾百套集群,有各種主從結構需要搭建需要去搭起來,每個節點時間也很短。
我們剛剛講的DRC會做數據的同步,但同步的時候也會面臨數據沖突的問題,為解決這個問題我們需要在所有表上增加一個DRC時間戳字段,用來判斷哪一邊數據是最新的,這樣在數據發生沖突的時候,我們會選最新的數據作為最終的數據。
為防止多活主鍵沖突,數據庫做了一些自增的調整,自增步長放大后馬上就會面臨數據溢出的問題,所以我們需要把主鍵都從int調整為bigint。主鍵改完以后還有一些外鍵依賴的也會需要改造,所以整體會要做很多的DDL(幾乎是全量表),而在MySQL里面DDL其實是風險比較高的操作。
第二個大改造是因為區分了不同的業務類型(我們剛剛講了有goloblZone這些),就會面臨各種不同類型的業務原來在同一套實例上的,現在需要拆分遷移到不同的實例上,這個我們也陸陸續續遷移50+的DB,現在還在有些在遷移。
下一個改造是我們現在用DRC做跨機房的數據同步了,所有的數據同步都是原生的改成DRC的模式,也會做很多的調整。
還有一個問題,就是帳號網段也需要做調整,因為我們原來基于安全考慮會限制某些IP網段,現在網段范圍放大了,所有帳號都要面臨調整網段的問題,如果量比較多的話,調整賬號風險還是挺高的(很多歷史遺漏會使得主從賬號不一致,同名賬號不同網段等問題,如果出現不一致調整的時候主從會中斷)。
另外怎么保證全局參數的一致性,起碼要保證同一個集群,在各個機房參數都是一致的,這個是比較臟活累活的東西,但是很容易出問題,到處是坑。
另外HA也面臨改造,因為原來在一個機房,現在有多個機房,怎么做到HA的可靠性也是一個問題。這塊我們也做了很多的改造。
改造完成之后,我們對比下改造前后在數據庫這端的變化。實例就翻了一倍,集群數量、Proxy配置、數據量、HA都會翻倍。這里特別列了一些DDL的變化,為什么會有變化,因為DRC不做DDL同步這個事情,這個事情都需要DBA分開機房來做(后面會細講)。
機器故障每周也增加了,原來一周碰不到一臺,現在可能一周面臨兩到三臺這樣的機器故故障,所以必須要保證你的HA是足夠可靠的。
但是我們人數是沒怎么增加,而且我們馬上要上第三個zone,維護的工作量會增加更多,不過我們沒有加人的計劃,之所以這樣是因為我們在把很多的工作通過平臺、自動化和項目的方式來推動解決掉。
四、DBA挑戰
剛剛講了那么多的改造前后的變化。對DBA來講,除了業務在多活的時候做改造,架構在多活時候的支持外,我覺得做多活改動最大的就是DBA了,對DBA的挑戰真的很大。就像前面說的在集群數量很大的情況下,怎么有效保障數據一致性、HA、配置、容量,還有DDL等問題。
我們可以看一下。剛剛講數據這塊我們需要保證他不能錯、不能亂,也不能說因為有一些數據的沖突,我們整個的數據流就停下來,這也不合理,否則多活就沒有意義了。
再一個即便是把前面流量的東西,都按規則走了,但你也不能保證各個組件不會出一些bug的問題,比如說DRC同步的時候就有bug,我們就要有兜底的檢測,把有問題的數據及時的發現,甚至是修復好。
所以我們DBA研發了一個DCP的平臺,DCP就是為數據一致性兜底的,它會全量的對比我們各個機房的數據,告訴DBA到底什么時候有數據不一致的問題,大概是多少,是什么樣的類型,怎么修復,不一致量大的時候還需要有合適的修復工具。
對DCP設計來說,因為我們有很多套集群,變動很多,如果說一旦變動就要人為調整的話,這個維護量也是很大的,也很難保證它的準確無誤,所以它必須能自適配。它需要支持全量、增量、延時的控制校驗和隨時手動校驗。
延時校驗就是我們有時候跨機房的時候天然就面臨延時,這時候如果有延時數據肯定有差異,DCP需要知道到底是因為延時導致的數據不一致還是數據真的不一致。
還有黑白名單機制,自定義規則,白名單有一些表我們不需要校驗就可以跳過。自定義規則就是可以設定一些相應的過濾條件來比較,濾掉一些不需要比較的數據。
DCP不光是支持對數據一致性的校驗,表結構不一致了也需要校驗,甚至說多維數據也能提供校驗支持,比如說一個訂單可能根據用戶做了拆分,也根據商戶做了拆分,這兩個數據是否一致是需要校驗的。還有我們需要控制比較的時候它的延時、并發、校驗的時長等,因為你的校驗一直在跑,消耗過大,跑的時間很長勢必對生產會造成影響。
最后我們是需要提供靈活修復的工具和配套的腳本。這樣比出來的數據才能夠快速的恢復,否則你雖然知道數據有問題,但要找這些數據怎么樣不一致的,怎么去修復,再根據條件去把腳本寫出來,這個過程就很長了,等你修復說不定業務已經影響比較大了。
DCP平臺上線以后,每天大概有400多套集群需要校驗,日均校驗的數據有60多億,分鐘級別的校驗頻率。實際發現數據一致性的問題起碼有50+例。
不一致的原因可能是業務寫錯了,DRC出BUG了,還有可能是各環節(包括DB)的配置問題,如果你沒有相應數據校驗的工具,其實你是很難知道到底數據是不是一致的,多活做的時候這個情況必須要能掌握,否則心里沒底了。
剛剛講的是數據校驗DCP的平臺,還有一個HA的保障,集群數量翻番了,這時候你需要保證任何一個節點掛了都能盡快的切過去,同時如果你的節點有調整有下線等,你都需要保證HA配置能夠跟著變動,否則HA的成功率就會得不到保證,800多套集群也不可能再依賴人肉去保證了。
所以我們做一個EMHA,他有什么作用呢?首先集群任何節點變動都能夠自動感知,當然我們底層是依賴于MHA的,MHA的配置大家用過的話都知道它需要對SSH做互通,有任何一個調整需要把他從配置文件里面加進去或者刪除,否則切換就有問題,所以EMHA新增了自動感知配置保持的功能,自動解決這些問題。
第二個重要的功能是變動信息的擴散通知的機制,因為我們是通過DRC同步數據的,如果有一個master出問題切換了,這時候要通知DRC去連新的master,并且還需要提供相應的位點信息,還有各種監控也需要得到通知,要知道這個master掛了以后,新的master是哪一個,否則后面維護的信息其實都會錯亂;
第三點我們的切換需要讓Proxy這一層自動感知,如果不能自動感知的話,每次切換Proxy都需要維護,這個可能會中斷生產的訪問,而且這個維護質量基本也得不到保證,所以EMHA也會自動完成與Porxy配置層信息的互通。
還有配置的保持也是比較麻煩的事情,我們在代理層的配置,如果節點變動了也需要變(調整區別于切換,切換DAL可以通過EMAH自動感知)。有各種參數,如果說調整不一樣了,也需要全局的同步的,這些東西都需要有很多自動發現的手段,包括自動處理的方式。
當然我們現在有些也還沒有能完成做到自動化(正在努力中),目前還有些是通過巡檢腳本來發現的,起碼保證能夠發現它然后解決掉。
容量這塊,現在是兩個機房,兩個機房的流量并不一定均衡,比如上海機房70%的流量,北京機房30%的流量,但流量會隨時切換,所以必須保證每個機房都能夠承擔所有流量。
當然三個機房的話,不一定百分之百的冗余,但也一定要知道每套集群是不是能承載切換過來的流量,否則切換過來就面臨雪崩的效應。所以對各項指標我們都要有相應的水位監控,提前發現這些問題。
還有一個很大的困難是在DDL這塊,因為DRC里面不方便做DDL這個事情,之前我們也嘗試讓DRC同步DDL操作,比如說我們做DDL的時候,一般是用PT工具來做,這個過程要拷貝整張表的數據,如果這個表比較大,DDL時兩個機房之間的流量就會面臨很大的沖擊,而且延時會相當大,比如說100G的表在一個機房做完要同步到另外一個機房去,這沖擊業務影響是不可接受的。
所以DDL需要DBA在每個機房單獨做,我們開發了一套DDL發布工具。因為我們有很多數據類型,有GlobalZone還有shardingZone我們還有大量Sharding 表。對單個業務邏輯表的DDL來說,實際上我們一套集群里面有幾百張表,這個表又分布在多套集群里面,所以實際業務一張邏輯表的DDL操作,實際DDL需要做一千張表,同時還有各種不同的業務集群類型,我們在發布工具必須要能自動適配和識別這些情況(這個時候元數據維護相當重要了,因為人已經識別不了啦,只能依靠工具)。
還有剛剛講DDL的時候大家普遍用PT的工具,我們用的時候也發現了很多問題,畢竟是它是同步觸發器的,一旦加上去之后,瞬間TPS很高的話,就把數據庫打爆了。
所以我們在這塊也做了大量改造,到現在大部分情況下我們已經不用PT了,大家看這個圖上有好幾種工具可以選擇。我們基于開源社區的gh-ost做了一個二次開發改造,改造后的工具叫mm-ost,是一個跨機房的DDL工具,不僅解決了DDL的時候threadrunning不可控、主從延時不可控的問題,還解決了跨機房延時的問題,速度比gh-ost要快一倍。
我們是多機房,多機房和你做一個機房的DDL時完全不一樣的,因為你的機器可能有差異或者繁忙程度不一樣,可能這個機房DDL做完了,另外一邊要半小時之后才能做完,尤其是一個業務邏輯表的DDL對應的是上千張物理表的DDL時,差異性就更大了,這樣造成的跨機房延時業務可能沒法接受,所以我們需要的不僅是能保證同機房DDL主從延時的可控,還要保證跨機房的延時的可控。
mm-ost現在就能夠支持到跨機房同步完成DDL的時差控制在3到5秒之內。這延時對業務來說就沒什么感覺了,而且他可以支持暫停、探測到DDL數據延時的時候能夠減慢速度,能根據機器負載動態調整DDL的速度等,所以現在DDL基本上對業務來說是沒有感覺的。
另外,大家可以看我們的發布平臺做的很復雜,它底層調用的是mm-ost,在發布平臺上我們也做很多控制,比如說DDL空間滿不滿足,各個主機是不是都滿足去做DDL的條件,主從我們需要控制的延時在30秒之內,有鎖的時候需要減緩速度,還支持定時執行(因為我們有些業務的低峰是晚上4點,所以DBA不可能每次都是4點來做這個事情,這時就要定時功能的支持)。
另外系統還可以通過識別業務高低峰推薦什么時候做DDL比較合適,還有一些風險識別的控制,我們還要預估DDL的時長,如果開發問一個500G的表DDL大概多久能做完?你需要能大概告訴他,給他一個預期??傊l布這塊是我們面臨最大的一個挑戰,我們在上面做了很多工作。
我們DDL數量相當多,可以說在多活改造的時候,DBA發布的量是最多的。多活改造期間我們DDL基本上每周的工單都在四位數,四位數的工單數量,放到底層來講,可能一個邏輯表生成一千個DDL,就是最少是5位數DDL物理表的量了。
如果完全依賴DBA來執行,也很難支持了,所以我們加了自動發布功能,對于風險不高的工單是系統自動執行的,粗略的比例大概是8:2,絕大部分都是自動發布了。風險性比較高的工單我們才需要人去處理,我們統計了一下半年大概有15000個工單。
五、收益與展望
大概的挑戰主要的方面已經跟大家分享了。我們最后看一下多活做完以后收益有哪些。
做多活之前,我們也面臨過很多棘手的問題,比方我們之前面臨著整個機房出現問題(核心交換機出問題、網絡出問題),還有些機房因為在業務沒有那么大之前你不可能預留特別多的機柜,但你現在說我業務漲的很快,現在要加一千臺機器、兩千臺機器的時候,發現你加不了,因為你的IDC不能給你這個支持,他們不可能給你預留這么多機柜,這個時候你就面臨單機房沒法擴容的麻煩,之前只能考慮遷移到一個更大的機房去,但也是個耗時費力成本高的事情。
我們多活做了之后,首先打破了單機房容量的瓶頸,單機房不能擴容的時候,我們現在可以在另外的機房擴容我的機器,也可以分不同的流量來滿足負載,就不再受到單個機房容量的限制。
另一個,多活上線到現在我們流量切了有20次左右,有時候是演練,有時候是真實發生故障,現在其實就不再受到單機房故障的影響,甚至是單地域的影響,假如說上海哪一天全斷電了對我們影響也不大(當然只是指技術層面)。
還有故障兜底,有的問題可能是比較麻煩的問題,一下子沒有辦法判斷或者解決,那時候可能影響很大,但只影響單個機房,這個時候就可以把業務切到另外一個機房,等我們把問題解決了以后再把流量切回來,這樣對業務就基本沒有損失了,所以多活之后對我們整體可用性也有一個很大提升。
另外一塊是動態調整各個機房的流量,尤其是在做一些促銷活動的時候,有些地區的流量明顯是不均衡的,這時候如果能動態的調整機房之間的流量訪問,這是比較好的分擔壓力,像阿里雙11這種活動,應該會根據流量壓力來調整各機房之間的分配。
接下來在來講下多活這塊后續我們可能要做一些事情,一個是剛剛講的多個機房,我們現在正在準備第三個機房,因為兩個機房的代價比較高,冗余比較多,我們需要做第三個機房分攤這塊的成本,當然一開始成本是比較高的,往后業務繼續上漲的話,可能不需要做太多的擴容。而且現有百分之百冗余的機器資源,可以再做調配,這樣成本往后來看的話是會下降的。
另外一塊是數據的Sharding,這個我們還沒有做到,因為我們在各個機房都是全量的數據,這也是我們后面努力的方向;
還有一個是自動動態擴縮容,我們需要有更細的控制能力來自動的完成這些動作,尤其是在硬件資源利用率上能動態調整;
最后一個點是希望能夠提供多機房數據強一致性的架構方案,因為我們現在來講都是最終一致性的,怎么對一些非常重要的數據,提供各個機房數據及時強一致性,這塊也是我們接下來需要努力的方向。
轉載于:https://www.cnblogs.com/davidwang456/articles/8241499.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的饿了么异地双活数据库实战的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深入理解Python字符编码--转
- 下一篇: 千万级日订单下,饿了么异地多活数据实施D