內容來源:2017年7月22日,UCloud高階研發工程師王鬆磊在“餓了麼技術沙龍【第九彈】上海研發中心·運維專場”進行《資料庫高可用架構》演講分享。IT 大咖說(微信id:itdakashuo)作為獨家視訊合作方,經主辦方和講者審閱授權釋出。
閱讀字數:3280 | 9分鐘閱讀
摘要
分享UCloud在資料庫高可用上的最佳實踐。首先介紹MYSQL常見的高可用方式,並分析其存在的問題,然後給出UCloud對此的思考和解決方法。
MySQL常見的資料同步方式
MySQL資料同步方式大體分為兩大類,第一類是使用MySQL傳統的非同步或半同步複製協議,比較典型的有MHA+MySQL或者**Proxy+MySQL。第二類是使用分散式協議,這方面有Group Replication或Galera Cluster+MySQL。
原生的非同步或半同步複製協議
首先來看下原生的非同步或半同步複製協議。它通過Master的dump執行緒與Slave的IO執行緒進行互動,當binglog發生更新時,將Binlog傳輸到Slave,實現Master和Slave的資料同步。
然後還可以通過使用不同的拓撲結構來實現不同的功能,如master和多個Slave做資料同步,如多個master相互搭建複製。目前絕大多數的Proxy產品都是使用MySQL的原生複製作為資料同步方式。
分散式協議做資料同步
這種是近幾年新興的同步方式,它的分散式演算法是通過選舉的方式,解決在分散式的系統中如何就某一決議達成一致的問題。
使用分散式協力做資料同步的方式,在近兩年出現了一系列開源或閉源的產品,如騰訊的phxsql、perconna和mariadbde galera外掛、社群版的Group、Tidb等。分散式協議通常需要至少三節點的MySQL,相比於原生的MySQL複製提供了更可靠的保證資料一致性的方法,但是由於技術教新(相比於MySQL複製),暫時並沒有替代原生複製成為成為絕大多數MySQL資料庫同步方式。
MySQL雙節點架構
經典的雙節點架構有一個VIP接入某一個Proxy,然後下端接一主一從兩個節點,從節點做一個資料總集的節點,以防止當主節點掛掉後,服務仍然可以使用,當然也可以作為備份來用。
這種架構使用binglog這種二進位制日誌的方式來做主從同步,採用半同步進行複製,Proxy同一時間只接入有一個節點,另外還可以根據需求選擇是否使用GTID或進行拓撲結構的擴充套件。
當發生異常情況,例如Master發生當機後,Proxy會將業務切換到Slave,當機恢復後,再將業務回切並進行資料回補,或者使用恢復後的Master作為新的Slave,重新搭建複製。
MySQL複製常見問題
上圖時序圖可以從中間分開,左邊是主節點,右邊是從節點。主庫任何的事務結束後都會同步到從庫,保證資料的一致性。
退化為非同步複製
主庫在傳送binglog的時候會等待從庫的應答,而沒有接受到應答就會出現超時問題。這就會造成下一個事務到達的時候主庫就不會再應答了,也就我們說的退化,從半同步複製退化到非同步複製。退化之後資料的一致性就會得不到保證。
退化的複製是可以恢復為半同步複製的。每個事務提交時,會在半同步外掛記錄當前記錄的binglog的檔名和位置。IO執行緒在記錄relay log完成後,會將relay log對應的主庫的binglog的檔案和位置傳送給。Dump執行緒在接受應答後,會對比Slave傳送的應答和半同步外掛記錄的內容,如果Slave傳送的檔案和位置要大於等於半同步外掛中記錄的內容,那麼恢復半同步複製。
發生意外當機
從寫入binglog到通知Dump執行緒階段如果發生意外當機就會造成主庫和從庫資料不一致。
這種不一致只是在master完成了,但是沒來得及複製slave的資料庫操作。這些操作在業務看來是執行失敗的資料庫操作。但是在主庫當機恢復後,這些資料庫操作會被recovery機制作為成功的資料庫操作來處理,同時binglog是存在的,但是並沒有複製到slave。
如果發生了業務切換,繼續在slave執行資料庫操作,那麼在一些特性的場景下,如果master當即回覆,可能造成複製失敗的情況。
非auto_position的Master.info
Master.info記錄的IO執行緒複製的相關資訊,記錄的資訊與show slave status顯示的IO執行緒相關含義相同。用於在MySQL啟動時,裝載複製IO執行緒的相關資訊,保證重啟後複製仍能繼續進行。
對於非auto_position的Master.info在change master時,會記錄主機的IP、埠、使用者名稱等資訊到master.info中,IO執行緒在記錄relay log後更新master.info中的記錄master的檔案和位置。
當意外當機的時候,可能發生記錄了relay log但是沒有更新master.info的情況。
非GTID的Relay-log.info
Relay-log.info記錄著SQL執行緒複製相關資訊,記錄的資訊與show slave status顯示的SQL執行緒相關資訊含義相同。用於在MySQL啟動時裝載複製的相關資訊,保證重啟後複製仍能夠繼續進行。
當發生當機,複製重新啟動後,會存在relay-log.info中記錄的資訊要晚於真正執行relay log的情況。SQL執行緒啟動時,可能讀取到已經執行過的relay.log。
這是如果開啟了GTID,重複的GTID會被過濾,而沒有開啟,發生重複執行的情況,可能導致複製錯誤。
重複GTID的忽略
GTID為全域性唯一標示符,與事務一一對應的,master的事務對應的GTID不會因為複製到Slave而發生改變,級master的事務複製到slave,被sql重現後,記入Slave bining中的事務對應的GTID仍然為master的gtid。
相同的GTID對應的事務不會被重複複製到Slave,slave對於執行過的gtid也不會重複執行。
在重做主從或者誤操作的情況下,由於GTID不會重複執行,所以可能會導致master和slave的資料差異。
複製問題的解決方法
退化為非同步複製的解決方案
非同步複製階段的當機問題是主要因素,解決這一問題的主要思路是減少非同步複製的存在時間。
可以採用增加半同步的超時時間,犧牲一定的可用性來保障資料的一致性。也可以通過增加新複製通道,只記錄檔案和位置,並且不退化,只重連,保證複製正常的情況下一直存在一條半同步複製。增加非同步和同步共存的複製方式也是一個方案。
發生意外當機解決方案
針對這一問題,應該避免進行重複的操作,以及在MySQL-5.6以前的版本使用自增ID。對於recovery機制進行優化,通過配置或者其他方式連線原slave,讀取master當機時的複製進度。記錄binglog的樹屋,如果沒有同步到Slave,仍然事務回滾,回滾後對binglog做truncate處理,另外還需對刪除的binglog做日誌記錄。
Master.info和Relay_log.log
這裡主要是解決當機恢復後複製起點問題。建議儘量使用GTID作為複製的依據,取代較早的檔案和位置,slave當機恢復後,對relay log、binglog和當前複製的進度做較完善的校檢。
重複GTID的忽略
這方面大多是人為造成的。所以建議在重做主從後,做完整的複製進度檢查,增加簡單的審計表,對敏感的操作做記錄,如reset master、change master等,並對比master和slave的敏感操作記錄。