餓了麼MySQL異地多活的數據雙向複製經驗談

講師介紹數據庫

陳永庭,餓了麼框架工具部高級架構師,主要負責MySQL異地雙向數據複製,支撐餓了麼異地多活項目。曾就任於WebEx、Cisco、騰訊等公司。後端

今天我主要分享餓了麼多活的底層數據實施,會和你們介紹在整個多活的設計和實施過程當中咱們是怎麼處理異地數據同步的,而這個數據同步組件在咱們公司內部稱之爲DRC。安全

異地多活背景服務器

在講DRC或者講數據複製以前,先跟你們回顧一下異地多活的背景。數據結構

餓了麼MySQL異地多活的數據雙向複製經驗談

去年咱們在作多活調研的時候,整個公司全部的業務服務都是部署在北京機房,服務器大概有四千多臺,災備的機器是在雲端,都是虛擬機,大概有三千多臺。當時咱們峯值的業務訂單數量已經接近了千萬級別,可是基本上北京機房(IDC)已經沒法再擴容了,也就是說咱們沒有空餘的機架,沒有辦法添加新的服務器了,必需要再建一個新的機房,因而咱們在上海建一個新的機房,上海機房要在今年的4月份纔會投入使用,因此須要在上海機房建成以後,異地多活項目能具有在生產環境上進行灰度。架構

異地多活的底層數據同步實施併發

餓了麼MySQL異地多活的數據雙向複製經驗談

這是異地多活的底層數據同步實施的一個簡單的概要圖,你們能夠看到,咱們有兩個機房,一個是北京機房,一個是上海機房。在這個時候,咱們指望目標是北方全部的用戶請求、用戶流量所有進入北京機房,南方全部的用戶請求、用戶流量進入上海機房。困難的地方是,這個用戶有可能今天在北方,明天在南方,由於他在出差,還有就是存在一些區域在咱們劃分南北shard的時候,它是在邊界上面的,這種狀況會加重同一個用戶流量在南北機房來回漂移的發生。還有個狀況,當咱們某個機房出現故障,如核心交換機壞掉致使整個機房服務不可用,咱們但願能夠把這個機房的全部流量快速切到另外的數據中心去,從而提升整個餓了麼服務的高可用性。框架

以上全部的因素,都須要底層數據庫的數據之間是打通的。而今天我所要分享的DRC項目就是餓了麼異地MySQL數據庫雙向複製的組件服務,即上圖中紅色框標記的部分。運維

異地多活對底層數據的要求工具

餓了麼MySQL異地多活的數據雙向複製經驗談

咱們在前期調研DRC實現的時候,主要總結了的三點,而在後續的設計和實施當中,基本上也是圍繞這三點來去解決問題。

第一個咱們以爲是延遲要低,當時給本身定的目標是秒級的,咱們但願在北京機房或上海機房寫入的數據,須要在1秒鐘以內同步到上海或者北京機房。整個延遲要小於1秒鐘。

第二個就是咱們要確保數據的一致性,數據是不能丟也不能錯的,若是出現數據的不一致性,可能會給上層的業務服務、甚至給產品帶來災難性的問題。

第三個就是保證整個複製組件具有高吞吐處理能力,指的是它能夠面對各類複雜的環境,比方說業務正在進行數據的批量操做、數據的維護、數據字典的變動狀況,這些會產生瞬間大量的變動數據,DRC須要面對這種狀況,須要具有高吞吐能力去扛住這些狀況。

數據低延遲和一致性之間,咱們認爲主要從數據的併發複製這個策略上去解決,安全、可靠、高效的併發策略,才能保證數據是低延遲的複製,在大量數據須要複製時,DRC併發處理才能快速在短期內解決。數據一致性,用戶的流量可能被路由到兩個機房的任何一個機房去,也就是說一樣一條記錄可能在兩個機房中被同時更改,因此DRC須要作數據衝突處理,最終保持數據一致性,也就是數據不能出錯。若是出現衝突且DRC自身沒法自動處理衝突,咱們還提供了一套數據衝突訂正平臺,會要求業務方一道來制定數據訂正規則。

高吞吐剛纔已經介紹了,正常狀況用戶流量是平穩的,DRC是能應對的,在1秒鐘以內將數據快速複製到對端機房。當DBA對數據庫數據進行數據歸檔、大表DDL等操做時,這些操做會在短期內快速產生大量的變動數據須要咱們複製,這些數據可能遠遠超出了DRC的最大處理能力,最終會致使DRC複製出現延遲,因此DRC與現有的DBA系統須要進行交互,提供一種彈性的數據歸檔機制,如當DRC出現大的複製延遲時,終止歸檔JOB,控制每輪歸檔的數據規模。如DRC識別屬於大表DDL產生的binlog events,過濾掉這些events,避免這些數據被傳輸到其餘機房,佔用機房間帶寬資源。

以上是咱們在實施異地多活的數據層雙向複製時對DRC項目提出的主要要求。

數據集羣規模(多活改造前)

餓了麼MySQL異地多活的數據雙向複製經驗談

這是咱們在作多活以前的北京數據中心的數據規模,這個數據中心當時有超過250套MySQL的集羣,一千多臺MySQL的實例,Redis也超過四百個集羣。

DRC服務的目標對象就是這250套MySQL集羣,由於在正在建設的第二個數據中內心將來也會有對應的250套MySQL集羣,咱們須要把兩個機房業務對等的集羣進行數據打通。

多活下MySQL的用途分類

餓了麼MySQL異地多活的數據雙向複製經驗談

咱們按照業務的用途,給它劃分了多種DB服務類型。爲何要總結這個呢?由於有一些類型,咱們是不須要複製的,因此要甄別出來,首先第一個多活DB,咱們認爲它的服務須要作多活的。

比方說支付、訂單、下單,一個機房掛了,用戶流量切到另外新的機房,這些業務服務在新的機房是工做的。咱們把這些多活服務依賴的DB稱爲多活DB,咱們優先讓業務把DB改形成多活DB,DRC對多活DB進行數據雙向複製,保障數據一致性。多活DB的優點剛纔已經講了,若是機房出現故障、核心交換機出問題,整個機房垮了,運維人員登不進機房機器,那麼咱們能夠在雲端就把用戶流量切到其它的機房。有些業務對數據有強一致性要求,後面我會講到其實DRC是沒有辦法作到數據的強一致性要求的,它是有數據衝突發生的,須要引入數據訂正措施。

業務若是對數據有強一致性要求,比方說用戶註冊,要求用戶登陸名全局惟一(DB字段上可能加了惟一約束),兩個機房可能會在同一時間接收了相同用戶登陸名的註冊請求,這種狀況下,DRC是沒法自身解決掉這個衝突,並且業務方對這個結果也是沒法接受的,這種DB咱們會把它概括到GlobalDB裏面,它的特性是什麼呢?

它的特性是單機房可寫,多機房可讀,由於你要保證數據的強一致性的話,必須讓全部機房的請求處理結果,最終寫到固定的一個機房中。這種DB的上層業務服務,在機房掛掉以後是有損的。比方說機房掛了,用戶註冊功能可能就不能使用了。

最後一個非多活DB,它是不多的,主要集中於一些後端的管理平臺,這種項目自己基本上不是多活的,因此這種DB咱們不動它,仍是採用原生的主備方式。

DRC整體架構設計

餓了麼MySQL異地多活的數據雙向複製經驗談

這是DRC複製組件的整體架構設計。咱們有一個組件叫Replicator,它會從MySQL集羣的Master上把binlog日誌記錄抽取出來,解析binlog記錄並轉換成咱們自定義的數據,存放到一個超大的event buffer裏面,event buffer支持TB級別的容量。

在目標機房裏咱們會部署一個Applier服務,這個服務啓一個TCP長鏈接到Replicator服務,Replicator會不斷的推送數據到Applier,Applier經過JDBC最終把數據寫入到目標數據庫。咱們會經過一個Console控制節點來進行配置管理、部署管理以及進行各個組件的HA協調工做。

DRC Replicator Server

餓了麼MySQL異地多活的數據雙向複製經驗談

這是DRC Replicator Server組件比較細的結構描述,主要是包含了一個MetaDB模塊,MetaDB主要用來解決歷史的Binlog的解析問題。

咱們成功解析Binlog記錄以後,會把它轉換成咱們本身定義的一種數據結構,這種結構相對於原生的結構,Size更小,MySQL binlog event的定義在size角度上考慮事實上已經很極致了,可是能夠結合咱們本身的特性,咱們會把不須要的event所有過濾掉(如table_map_event),把能夠忽略的數據所有忽略掉。咱們比對的結果是須要複製的event數據只有原始數據size的70%。

DRC Applier Server

餓了麼MySQL異地多活的數據雙向複製經驗談

往目標的MySQL集羣複製寫的時候,由DRC Applier Server負責,它會建一個長鏈接到Replicator上去,Replicator PUSH數據給Applier。Applier把數據拿到以後作事務的還原,最後經過JDBC把事務從新寫到目標DB裏面,寫的過程中,咱們應用了併發的策略。

併發策略在提供複製吞吐能力,下降複製延遲起到決定的做用,還有冪等也是很是重要的,後面有不少運維操做,還有一些Failover回退操做,會致使發生數據被重複處理的狀況,冪等操做保障重複處理數據不會發生問題。

DRC防止循環複製

餓了麼MySQL異地多活的數據雙向複製經驗談

在作複製的時候,你們確定會碰到解決循環複製的問題。咱們在考慮這個問題的時候,查了不少資料,也問了不少一些作過相似項目的前輩,當時咱們認爲有兩大類辦法,第一大類辦法一開始否決了,由於咱們對MySQL的內核原碼不熟悉,並且時間上也來不及,雖然咱們知道經過MySQL的核內解決迴路複製是最佳的、最優的。

靠DRC自身解決這個問題,也有兩種辦法,一種辦法是咱們在Apply數據到目標DB的時候把binlog關閉掉,另一種辦法就是寫目標DB的時候在事物中額外增長checkpoint表的數據,用於記錄源DB的server_id。

後來咱們比較了一下,第一個辦法是比較簡單,實現容易,可是由於Binlog記錄沒有產生,致使不支持級聯複製,也對後續的運維帶來麻煩。因此咱們最後選擇的是第二個辦法,經過把事務往目標DB複製的時候,在事務中hack一條checkpoint的數據來標識事務產生的原始server,DRC在解析MySQL binlog記錄時就能正確分辨出數據的真正來源。

DRC數據一致性保障

在剛開始研發、設計的時候,數據一致性保障是咱們很頭疼的問題。並非在一開始就把全部的點都想全了,是在作的過程中出現了問題,一步步解決的,回顧一下,咱們大概從三個方面去保證數據的一致性:

餓了麼MySQL異地多活的數據雙向複製經驗談

首先,由於數據庫是多活的,咱們必須從數據中心層面儘量把數據衝突發生的機率降到最低,避免衝突,怎麼避免呢?就是合理的流量切分,你能夠按照用戶的維度,按照地域的維度,對流量進行拆分。剛纔咱們講的,北方用戶的全部數據在北京機房,這些北方用戶的下單、支付等的全部操做數據都是在北方機房產生的,因此用戶在同一個機房中發生的數據變動操做絕對是安全的。咱們最怕的是同一個數據同時或者是在相近的時間裏同時在兩個機房被修改,咱們怕的是這個問題,由於這種狀況就會引起數據衝突。因此咱們經過合理的流量切分,保證絕大部分時候數據是不會衝突的。

第二個咱們認爲你要保障數據一致性,首先你要確保數據不丟,一旦發生可能數據丟失的狀況,咱們會作一個比較保險的策略,就是把數據複製的時間位置回退,即便重複處理數據,也避免丟數據的可能,可是這個時候會帶來數據重複處理的問題,因此數據的冪等操做特別重要。

這些都是咱們避免數據發生衝突的方法,那衝突其實是不可避免的,衝突發生後,咱們怎麼解決?最終採用的辦法是在數據庫表上隱含地加一個時間字段(數據最後更新時間),這個字段對業務是透明的,主要用來輔助DRC複製,一旦數據發生衝突,DRC複製組件能夠經過這個時間來判斷兩個機房或者三個機房中的哪條數據是最後被更新的,最新優先的原則,誰最後的修改時間是最新的,就以它爲準。

DRC數據複製低延遲保障

餓了麼MySQL異地多活的數據雙向複製經驗談

剛纔咱們講的是數據的一致性,還有一個點很是重要,就是數據複製的低延遲保障。咱們如今延遲包括用戶高峯時間也是小於1秒的,只有在凌晨以後,各類歸檔、批量數據處理、DDL變動等操做會致使DRC延遲出現毛刺和抖動。若是你的延遲很高的話,第一在作流量切換時,由於運維優先保障產品服務的可用性,在不得以的狀況會不考慮你的複製延遲,不會等數據複製追平以後再切流量,因此你的數據衝突的機率就變的很大。

爲了保證複製低延遲,咱們認爲主要策略、或者你在實施時主要的作法仍是併發,由於你只有用高效的安全的併發複製策略,服務纔有足夠的吞吐處理能力,而不至於你的複製通道由於遇到「海量」數據而致使數據積壓,從而加重了複製延遲的產生。

咱們一開始採用的基於表級別的併發,可是表級別的併發在不少狀況下,併發策略沒辦法被有效的利用,比方說有的業務線的數據庫可能90%的數據集中在一張表或者是幾個表裏面,而大部分表數據量很小,那基於表的併發策略就併發不起來了。咱們如今跑的是基於行級別的併發,這種併發它更能容忍和適應不少場景。

DRC & MySQL Master切換

餓了麼MySQL異地多活的數據雙向複製經驗談

這個是DRC複製組件與MySQL集羣的關係關聯圖,一旦MySQL集羣裏面的Master發生了主備切換,原來的Master掛了,DRC怎麼處理?目前的解決方案是DBA系統的MHA工具會通知DRC控制中心,DRC的控制中心會找到對應的複製鏈路,而後把複製鏈路從老的Master切到新的Master,可是關鍵點是MHA在通知以前先把老的Master設置爲不可寫,阻斷DRC可能往老的Master繼續寫數據。

DRC線上運行情況(規模)

餓了麼MySQL異地多活的數據雙向複製經驗談

這個是咱們DRC上線以後的運行情況。如今大概有有將近400多條複製鏈路。這個複製鏈路是指單向的鏈路。咱們提供的消息訂閱大概有17個業務方接入,天天產生超過1億條的消息。

DRC線上運行情況(性能)

餓了麼MySQL異地多活的數據雙向複製經驗談

這是DRC線上運行的一個性能監控快照,咱們能夠看到,它是上午11點多到12點多的一個小時的性能,你會發現其實有一個DB是有毛刺的,有一個複製鏈路有毛刺,複製延遲最高達到4s,可是大部分的複製鏈路的延遲大概也是在1秒或1秒如下。

個人分享到此結束了,謝謝你們。

Q&A

**Q1:**你好,想問一下餓了麼是怎麼避免各個機房中的PK衝突的?

**A1:**主鍵自增的步長在各個機房中是固定相同的,可是每一個機房的增加offset是不一樣的,因此不會出現PK衝突。

**Q2:**DRC複製會不會對目標數據庫形成性能影響?

**A2:**有影響。由於DRC會佔用目標DB的IOPS。DRC Apply自己就是目標DB的上層服務。

**Q3:**DRC Applier採用JDBC去寫目標DB,除了這個辦法還有其它途徑嗎?

**A3:**目前咱們分析binlog還原事務,而後經過JDBC把事務寫到目標DB。咱們曾經模擬過MySQL的binlog server,讓目標DB啓動一個Replication鏈接到咱們僞造的binlog server上,咱們的binlog server會把binlog記錄發給目標DB,這個辦法會存在不少問題,咱們就放棄了這個辦法。

**Q4:**有監測數據一致性的工具嗎?

**A4:**這個是有的。DBA團隊開發了一套checksum工具來實時監測數據一致性。

**Q5:**餓了麼作異地雙活主要的緣由就是剛剛提到的單個機房是沒法擴容嗎?

**A5:**是的。

**Q6:**雙向同步後期的運維成本高嗎?

**A6:**對DBA的運維會形成影響,DBA的歸檔job、DDL發佈等操做都須要考慮DRC的雙向同步因素。

End.

相關文章
相關標籤/搜索