如何設計和實現高可用MySQL

騰訊雲加社群發表於2018-11-15

歡迎大家前往騰訊雲+社群,獲取更多騰訊海量技術實踐乾貨哦~

本文由騰訊雲資料庫 TencentDB發表於雲+社群專欄

王甲坤,騰訊高階工程師、騰訊雲關係型資料庫MySQL負責人,擁有多年客戶端、資料庫研發經驗。在IOS客戶端、MySQLPostgreSQLSQL Server等產品有豐富的研發和產品策劃經驗。

img

下面開始我們今天的主要內容,今天主要是通過什麼、為什麼、怎麼做,這條思路跟大家呈現MySQL的高可用。

首先介紹一下什麼是高可用?在我看來就是業務在高質量的情況下,對使用者提供服務的可執行的總時長。其實我們從事MySQL相關的工作,大家對9這個數字比較敏感,大家選擇雲廠商雲產品的時候,首先會看它的資料庫有幾個9。目前騰訊雲MySQL可以做到99.95,全年在25分鐘的樣子。

據我瞭解,高可用最高是能做到3個9,1個6,做到4個9很困難,做到5個9就是極限了。

img

為什麼我們要做高可用?因為我們不可控的因素太多了,比如說,挖挖機,我記得基本上每隔一年都會出現這種類似的事件,讓我記憶猶新的是2015年杭州蕭山的某個主幹網被刮斷,導致阿里的部分服務不可用。另外,還有類似的一些停電,或者一些天災等等。值得一提是,運維人員的一些操作失誤案例,rm整個目錄或者drop表,民間有說法叫從刪庫到跑路。不可控制的因素很多,你的資料、使用者是你的,如果不可控的話,你的業務上不去。

img

一般來說,有兩個指標會被當作衡量的標準,第一是RPO,第二是RTO。RPO從故障開始到業務恢復所丟失的資料量,RTO就是從故障開始到業務恢復所耗費的時長,兩者都是越短越好。

我們怎麼做呢?一般來說業界有三種方式,左邊是基於單機儲存方式,這種方式在遊戲場景比較多,大家上層是用單獨的計算機節點,下層用三副本保證資料的可靠性。在計算節點發生故障以後可以快速遷移到另一個計算節點,當然我們騰訊雲的MySQL已經推出了這種模式,相對來說非常廉價,是基礎版,大家在官網都可以購買到這種模式。第二種是基於共享儲存方式,也叫share disk模式,這種比較典型的是oracle的RAC架構。底層基於共享儲存的方式,上層採用多個計算節點,某個計算節點故障可立即從ip列表中提出,不影響使用者訪問。第三種就是基於資料複製模式,也就share nothing模式,通過資料傳輸、複製協議達到兩臺主機資料一致性,也是本次講解的重點。另外,除了儲存節點的高可用,其整個鏈路也需要高可用,比如,我們們的IDC機房,交換機,以及主機伺服器等。

img

下面我們介紹下基礎設施的高可用。大家經常聽到幾個術語,第一是同城雙活,第二是兩地三中心,兩地三中心對於金融相關的場景是個強需求,其實說白了就是說我們在同城兩個節點相差十公里之外有兩個資料中心,在100公里異地以外有另個災備中心,保證了機房的高可用。另外包括網路、主機,其實架構上是這樣的,至少說你的交換機網路都有備份,一個倒了以後,另一個需要替換上去。

img

下面進入我們的重點,基於資料複製的高可用,首先介紹一下備份,備份確實是非常重要的,而且備份是一個實在沒辦法最後的一個保障,所以說建議大家不管是在雲上用的業務,還是自己的IDC儘量做好備份。

MySQL備份基本上是這兩種:邏輯備份、物理備份。邏輯備份通常使用官方的MySQLDump與第三方工具MyDumper,MyDumper優勢在於多執行緒備份,速率快。物理備份使用Percona的xtrabackup,可以不落盤,通過基於流式併發與壓縮,生產出成功率較高、速率較快並且暫用儲存空間較低的備份。最後一種就是快照,我們騰訊雲的基礎版的備份就是通過快照生成的。

那基於資料複製方式,一般是主從兩個節點,資料怎麼保證一致性呢?其實是通過複製協議進行資料傳輸,通過Switch切換保證故障以後服務能夠儘快恢復。右邊的圖基本和騰訊雲MySQL差不多的架構,我們採用了一主一從的方式,從節點只負責故障的轉移,當主節點掛了以後,通過自動故障探測與自動切換,從而做到業務儘快恢復。另外針對讀寫分離,騰訊雲MySQL現可以支援一主掛5個只讀節點。

下面介紹一下複製,在介紹複製之前有必要介紹一個重要的概念:binlog,binlog是二進位制檔案,主要記錄使用者對資料庫更新的sql資訊,binlog是什麼樣子呢?它是在磁碟上是這個樣子,使用show binlog events後它是這樣的,裡面會記錄一些元資訊,比如位點、事件等等,我們通過MySQL官方解析工具mysqlbinlog解析後是這樣的,裡面sql語句是使用base64編碼的,解碼後是這樣的,可以看到這裡是條插入語句。那什麼時候寫binlog呢?大家來看這個圖,我們知道事務提交有兩個階段:prepare與commit,請問是哪個階段寫binlog呢?binlog其實是在prepare後commit前寫入的,同時寫事務過程中,會產生redolog與undolog,那這兩者有什麼區別呢?我們知道MySQL是多引擎的關係型資料庫,binlog是MySQL Server層的日誌,而redolog是MySQL引擎InnoDB層的日誌;另外一個不同是兩者寫入時機不同,redolog是prepare階段每執行sql語句就寫redo了,而binlog是在prepare完commit前寫的。那MySQL在主從架構下怎麼保證資料一致性呢?眾所眾知,MySQL為了保證效能,資料是先寫記憶體後落盤的。當你資料庫執行的時候,發生了當機,機器再次恢復的時候可能是部分資料落盤了,部分未落盤。這時,mysql是找到binlog最新同步的位點或GTID,來確定redolog或者undolog中哪些例項需要回滾,哪些事務需要重做。另外,在寫日誌的時候,比如redolog或binlog,MySQL為保證高效能,也是先寫記憶體後落盤的,所以日誌的落盤策略也會影響資料的一致性。為保證資料的一致性,建議大家將涉及日誌的引數配置為“雙1”,也就是如圖上所示。

img

下面我們來看看複製整個流程,其實很簡單,Master通過dump執行緒將binlog落盤,在Slave上會有兩個執行緒,分別是IO執行緒和SQL執行緒。IO執行緒接受來自Master的binlog並落地形成Relaylog,SQL執行緒並行讀取relaylog中的sql資訊,執行回放動作。一般來說, 複製分三種:非同步複製、半同步、強同步。這三者的區別在於何時將sql執行的結果反饋給客戶端。非同步複製,Master不管Slave,Master執行sql完畢後立即返回給客戶端,這種方式效能最好,但是存在資料不一致的可能;強同步呢,Master完全關心Slave,等待Slave將relaylog回放後才返回給客戶端,這種方式能夠保證資料強一致,但是其效能有一定損耗;半同步則是Master部分關心Slave,認為只要binlog傳輸到Slave側,落為relaylog後,即可以返回給客戶端了。半同步是一種兼顧的實現,一方面保證資料一致性,另一方面兼顧了資料庫的效能。

img

在複製過程中,我們經常遇到延遲問題,大家看圖中所示,複製經歷三個階段:Dump執行緒落盤binlog、IO執行緒落盤relaylog、以及SQL執行緒回放,請問三個步驟裡面哪個步驟是一個瓶頸?是SQL執行緒,是因為SQL執行緒在回放日誌過程中是序列執行sql的,而Master對外是並行提供服務的。所以這裡瓶頸是SQL執行緒。大家可用通過開啟並行複製來解決延遲問題,MySQL5.6基於庫級別並行複製;MySQL 5.7基於邏輯時鐘並行複製,也就是表級別的並行;而MySQL8.0則是行級別的並行複製,粒度更細,複製效率更高。

img

剛才是說在協議級別進行復制,其實還有一種方式是塊級別的資料複製,其不關心上層是什麼,只需要保證在磁碟層面資料複製即可。當然這種方式的話,應用的比較少。說完複製後,我們們來說一下切換,其實MySQL官方之前並沒有提供故障自動發現與轉移的能力,基本上靠第三方工具來實現。

img

第一種是Keepalived,Master和Slave相互探測對方,時刻詢問對方存活狀態。當出現網路抖動或者網路出現問題的時候,可能會出現腦裂問題,變成了兩主,資料就寫錯亂了。第二種就是MMM的方式, M1M2互為主備,再加上一個Slave節點做冗餘。從圖上看,雖然是雙主,但該模式下同一時間點下只能有一個節點可以寫,當發現這個主寫節點出現故障,會將vip切換到另一個主上比。整體看,這種方式比較老,問題比較多。第三種是MHA,其應用廣泛,這種方式是由複製組與管理節點組成,每個複製組裡是由至少三個資料節點組成,資料節點上部署監控agent,定時上報到管理節點,當主節點出現問題時,由管理節點裁決是否切換到從節點。騰訊雲是自己實現了一套故障檢測,結構如右邊的圖,由高可用保證的Monitor節點來進行故障檢測與切換。另外,目前我們還在做MySQL高可用的重構,屆時能夠做到故障檢測恢復30秒鐘以內,大大提高了高可用。

img

下面我們來說下叢集的高可用架構,比較有名的就是PXC、MGC、MGR,PXC和MGC是結構比較類似,MGR是官方提供的,具有故障轉移的高可用架構。大體的層級是這樣的,MGR以外掛的形式存在的,MGR主要是把複製協議進行改造,因為MGR支援多活,所以這裡另一個重點是衝突檢測,若多個節點同時寫同一主鍵時,依照哪個為準呢?MGR是採用基於Paxos協議實現的衝突檢測。下面,我們大致看下結構,MGR是支援多個節點寫,即多活,支援某個節點掛了後自動剔除,恢復後自動加入叢集。這張圖是介紹一下MGR資料流邏輯,圖上有三個節點構成最小MGR叢集。假設DB1有一次寫提交,在Prepare階段,MGR外掛會生成一個叫WriteSet的集合,並將其廣播給其他節點。這個WriteSet集合包含此次提交的binlog和更新的唯一鍵,此唯一鍵由db名、表名和主鍵組成。這裡可以看出MGR有個限制,表中必須要有主鍵,要不無法進行衝突檢測。我們再說回來當節點收到這一資訊時,會進行比對,每個節點都有一個快取,儲存當前同步情況,即唯一鍵對應的GTID SET。通過比對後將結果返回給DB1,只要多於半數的節點返回說OK,可以提交,那DB1接下來就會執行binlog的落盤操作,然後返回OK到客戶端。其他節點則執行寫Relaylog的動作,接下來進行回放的動作。若多數節點返回衝突,DB1則執行回滾操作,其他節點會drop掉複製過來的binlog。

其實PXC和MGC思路是差不多,應該說是MGR借鑑的,因為PXC和MGC是比較早就出來的,這裡大同小異,主節點將WriteSet寫集合廣播出去,廣播完後進行驗證與裁決。

img

最後我們說一下NewSQL高可用架構,首先對AWS表示致敬,孵化出非常優秀的NewSQL產品-Aurora。那Aurora是怎麼產生出來的呢?這與AWS資料庫架構有關。我們來看看這個圖,AWS資料庫是架構在虛擬機器與雲盤上的,我們都知道MySQL的log比較多,所以很多IO是通過耗時較高的網路來完成的,因此AWS這種架構網路IO是它的瓶頸,效能也跑不上去。在此基礎上,我們來認識下Aurora。

Aurora是計算與儲存分離的架構,典型的share disk 的結構。底層儲存採用6副本,部署在三個不同的AZ上,可以保證一個AZ掛了,或者至多兩個AZ的一個副本丟失的情況下資料不丟失,業務可以正常對外服務。Aurora的理念是“日誌即資料庫”,其把MySQL儲存層進行了徹底的改造,摒棄了很多LOG,只留下了Redolog,具備將redolog轉換到Innodb page的能力。通過這種方式,Aurora宣稱其減少至少85%比例的IO。另外其把備份和回檔下沉到儲存節點,使得備份恢復更快並得到保障。Aurora整體感覺相對比較接地氣,成本相對比較低。

另一個就是阿里雲的Polar,理念和AWS不同,阿里雲覺得未來網路不是問題,未來網路可以接近匯流排的質量,所以是架構在RDMA網路的機房裡,日誌方面大動作較少,保證後續MySQL社群新特性可快速迭代近來。Polardb也是share disk的架構,其儲存節點是通ParallelRaft協議保證資料的完備性。可見這也是個偉大的架構,但是相對來說成本比較高一些。

我們騰訊雲自己的NewSQL在研發中,只是目前還沒有正式上線,我們的名字叫CynosDB,相比來說我們的理念是兼顧兩者,未來在高網路新硬體的基礎實施下,會發揮更大的效能,更穩健的服務和更高的可用性。請大家拭目以待。

本次我的分享就到此為止。更多資料庫前沿技術可關注 我們公眾號:騰訊雲資料庫CDB

img

Q & A

Q:我想問一下在騰訊遊戲的高併發行業裡面,我們主要採用哪種架構?

A:騰訊內部有很多自研專案,但基本上我們是基於資料複製的方式。內部有phxsql等分散式叢集架構。

Q:如何在高併發情況下,保證總庫的定延時呢?

A:可以開啟並行複製,業務做分庫分表,分散到多個例項上。

Q:比如說像遊戲類的,在遊戲高峰期的話會有很多人同時線上,這種情況下怎麼在後臺看資料呢?

A:可以對比較熱的資料進行分層,前一層可以通過KV方式快取,比如Redis,來提高熱資料的讀取,後一層使用MySQL,定期將資料同步落盤。

Q:這種情況下怎麼保證資料庫是一致的呢?

A:寫資料可以不經過KV快取,直接寫MySQL資料庫,讀取時,快取內沒有資料,需要從DB中撈取出來。另外,KV快取也有落地能力,非關鍵資料也可以不使用MySQL落地。

相關閱讀 【每日課程推薦】機器學習實戰!快速入門線上廣告業務及CTR相應知識

此文已由作者授權騰訊雲+社群釋出,更多原文請點選

搜尋關注公眾號「雲加社群」,第一時間獲取技術乾貨,關注後回覆1024 送你一份技術課程大禮包!

海量技術實踐經驗,盡在雲加社群

相關文章