歡迎大家前往 "騰訊雲+社區" ,獲取更多騰訊海量技術實踐乾貨哦~ 本文由 "騰訊雲資料庫 TencentDB" 發表於 "雲+社區專欄" 王甲坤,騰訊高級工程師、騰訊雲關係型 "資料庫MySQL" 負責人,擁有多年客戶端、資料庫研發經驗。在IOS客戶端、 "MySQL" 、 "PostgreSQL ...
歡迎大家前往騰訊雲+社區,獲取更多騰訊海量技術實踐乾貨哦~
本文由騰訊雲資料庫 TencentDB發表於雲+社區專欄
王甲坤,騰訊高級工程師、騰訊雲關係型資料庫MySQL負責人,擁有多年客戶端、資料庫研發經驗。在IOS客戶端、MySQL、PostgreSQL、SQL Server等產品有豐富的研發和產品策劃經驗。
下麵開始我們今天的主要內容,今天主要是通過什麼、為什麼、怎麼做,這條思路跟大家呈現MySQL的高可用。
首先介紹一下什麼是高可用?在我看來就是業務在高質量的情況下,對用戶提供服務的可運行的總時長。其實我們從事MySQL相關的工作,大家對9這個數字比較敏感,大家選擇雲廠商雲產品的時候,首先會看它的資料庫有幾個9。目前騰訊雲MySQL可以做到99.95,全年在25分鐘的樣子。
據我瞭解,高可用最高是能做到3個9,1個6,做到4個9很困難,做到5個9就是極限了。
為什麼我們要做高可用?因為我們不可控的因素太多了,比如說,挖挖機,我記得基本上每隔一年都會出現這種類似的事件,讓我記憶猶新的是2015年杭州蕭山的某個主幹網被刮斷,導致阿裡的部分服務不可用。另外,還有類似的一些停電,或者一些天災等等。值得一提是,運維人員的一些操作失誤案例,rm整個目錄或者drop表,民間有說法叫從刪庫到跑路。不可控制的因素很多,你的數據、用戶是你的,如果不可控的話,你的業務上不去。
一般來說,有兩個指標會被當作衡量的標準,第一是RPO,第二是RTO。RPO從故障開始到業務恢復所丟失的數據量,RTO就是從故障開始到業務恢復所耗費的時長,兩者都是越短越好。
我們怎麼做呢?一般來說業界有三種方式,左邊是基於單機存儲方式,這種方式在游戲場景比較多,大家上層是用單獨的電腦節點,下層用三副本保證數據的可靠性。在計算節點發生故障以後可以快速遷移到另一個計算節點,當然我們騰訊雲的MySQL已經推出了這種模式,相對來說非常廉價,是基礎版,大家在官網都可以購買到這種模式。第二種是基於共用存儲方式,也叫share disk模式,這種比較典型的是oracle的RAC架構。底層基於共用存儲的方式,上層採用多個計算節點,某個計算節點故障可立即從ip列表中提出,不影響用戶訪問。第三種就是基於數據複製模式,也就share nothing模式,通過數據傳輸、複製協議達到兩台主機數據一致性,也是本次講解的重點。另外,除了存儲節點的高可用,其整個鏈路也需要高可用,比如,咱們的IDC機房,交換機,以及主機伺服器等。
下麵我們介紹下基礎設施的高可用。大家經常聽到幾個術語,第一是同城雙活,第二是兩地三中心,兩地三中心對於金融相關的場景是個強需求,其實說白了就是說我們在同城兩個節點相差十公裡之外有兩個數據中心,在100公裡異地以外有另個災備中心,保證了機房的高可用。另外包括網路、主機,其實架構上是這樣的,至少說你的交換機網路都有備份,一個倒了以後,另一個需要替換上去。
下麵進入我們的重點,基於數據複製的高可用,首先介紹一下備份,備份確實是非常重要的,而且備份是一個實在沒辦法最後的一個保障,所以說建議大家不管是在雲上用的業務,還是自己的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”,也就是如圖上所示。
下麵我們來看看複製整個流程,其實很簡單,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後,即可以返回給客戶端了。半同步是一種兼顧的實現,一方面保證數據一致性,另一方面兼顧了資料庫的性能。
在複製過程中,我們經常遇到延遲問題,大家看圖中所示,複製經歷三個階段:Dump線程落盤binlog、IO線程落盤relaylog、以及SQL線程回放,請問三個步驟裡面哪個步驟是一個瓶頸?是SQL線程,是因為SQL線程在回放日誌過程中是串列執行sql的,而Master對外是並行提供服務的。所以這裡瓶頸是SQL線程。大家可用通過開啟並行複製來解決延遲問題,MySQL5.6基於庫級別並行複製;MySQL 5.7基於邏輯時鐘並行複製,也就是表級別的並行;而MySQL8.0則是行級別的並行複製,粒度更細,複製效率更高。
剛纔是說在協議級別進行複製,其實還有一種方式是塊級別的數據複製,其不關心上層是什麼,只需要保證在磁碟層面數據複製即可。當然這種方式的話,應用的比較少。說完複製後,咱們來說一下切換,其實MySQL官方之前並沒有提供故障自動發現與轉移的能力,基本上靠第三方工具來實現。
第一種是Keepalived,Master和Slave相互探測對方,時刻詢問對方存活狀態。當出現網路抖動或者網路出現問題的時候,可能會出現腦裂問題,變成了兩主,數據就寫錯亂了。第二種就是MMM的方式, M1M2互為主備,再加上一個Slave節點做冗餘。從圖上看,雖然是雙主,但該模式下同一時間點下只能有一個節點可以寫,當發現這個主寫節點出現故障,會將vip切換到另一個主上比。整體看,這種方式比較老,問題比較多。第三種是MHA,其應用廣泛,這種方式是由複製組與管理節點組成,每個複製組裡是由至少三個數據節點組成,數據節點上部署監控agent,定時上報到管理節點,當主節點出現問題時,由管理節點裁決是否切換到從節點。騰訊雲是自己實現了一套故障檢測,結構如右邊的圖,由高可用保證的Monitor節點來進行故障檢測與切換。另外,目前我們還在做MySQL高可用的重構,屆時能夠做到故障檢測恢復30秒鐘以內,大大提高了高可用。
下麵我們來說下集群的高可用架構,比較有名的就是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寫集合廣播出去,廣播完後進行驗證與裁決。
最後我們說一下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,相比來說我們的理念是兼顧兩者,未來在高網路新硬體的基礎實施下,會發揮更大的性能,更穩健的服務和更高的可用性。請大家拭目以待。
本次我的分享就到此為止。
Q & A
Q:我想問一下在騰訊游戲的高併發行業裡面,我們主要採用哪種架構?
A:騰訊內部有很多自研項目,但基本上我們是基於數據複製的方式。內部有phxsql等分散式集群架構。
Q:如何在高併發情況下,保證總庫的定延時呢?
A:可以開啟並行複製,業務做分庫分表,分散到多個實例上。
Q:比如說像游戲類的,在游戲高峰期的話會有很多人同時線上,這種情況下怎麼在後臺看數據呢?
A:可以對比較熱的數據進行分層,前一層可以通過KV方式緩存,比如Redis,來提高熱數據的讀取,後一層使用MySQL,定期將數據同步落盤。
Q:這種情況下怎麼保證資料庫是一致的呢?
A:寫數據可以不經過KV緩存,直接寫MySQL資料庫,讀取時,緩存內沒有數據,需要從DB中撈取出來。另外,KV緩存也有落地能力,非關鍵數據也可以不使用MySQL落地。
此文已由作者授權騰訊雲+社區發佈,更多原文請點擊
搜索關註公眾號「雲加社區」,第一時間獲取技術乾貨,關註後回覆1024 送你一份技術課程大禮包!
海量技術實踐經驗,盡在雲加社區!