解密網易MySQL例項遷移高效完成背後的黑科技
網易蜂巢團隊:為企業提供專業容器雲平臺,深度整合IaaS、PaaS及容器技術,提供彈性計算、DevOps工具鏈、微服務基礎設施等服務,幫助企業解決IT、架構及運維等問題,使企業更聚焦於業務,是新一代的雲端計算平臺。
1簡介
我們把資料庫裡部分或全部Schema和資料遷移到另一個例項的行為稱為例項遷移,將匯出資料的例項稱為源例項,匯入資料的例項稱為目標例項。根據遷移資料庫型別的不同,可以分為同種資料庫之間的遷移,如從MySQL遷到MySQL;跨資料庫型別的遷移,如從Oracle遷移到MySQL等。本文將介紹蜂巢RDS例項遷移功能的實現,並探討如何高效完成例項遷移任務。
2使用場景
那麼,為什麼要進行MySQL例項遷移呢?例項遷移的場景歸納起來主要有以下幾種:
1、從自建例項遷移到RDS:在雲服務還未充分推廣時,存在大量的自建資料庫例項,舉網易公司為例,網易部落格、網易郵箱等產品數百個MySQL例項直接部署在物理伺服器上,隨著業務的擴充套件,必然要對例項進行擴容、升規格等操作,相比自建例項,RDS例項在故障處理、線上擴容、升級等方面存在天然的優勢,所以,目前絕大部分網易網際網路產品的資料庫均已使用例項遷移功能遷移到RDS上;
2、從其他公有云平臺遷移到RDS:蜂巢RDS推出近一年以來,很多使用者將部署在其他公有云平臺上的MySQL例項遷移到蜂巢RDS上,對例項遷移功能進行統計發現有50%是用於遷移其他公有云的MySQL例項。
3例項遷移技術實現
在設計例項遷移功能前,我們對業界公有云進行了充分調研,僅有兩家主流公有云平臺提供例項遷移功能,那麼為什麼僅兩家呢,主要是因為提供線上例項遷移功能需要解決一系列問題,概括起來有以下幾點:
1、如何快速地對源例項進行一致性資料備份?
2、如何處理備份過程中對源例項業務的影響?
3、如何快速地將備份匯入到目標例項?
4、如何同步源例項的增量資料到目標例項?
5、如何確保例項遷移高效完成?
下面逐條解析蜂巢RDS是如何解決這些難題的。
多執行緒邏輯備份
我們解決第一個問題的方法是採用多執行緒邏輯備份的方式來進行源例項一致性資料匯出。
MySQL的資料備份工具有很多,邏輯備份工具包括經典的mysqlpump,MySQL 5.7版本新推出的mysqlpump,Percona開源工具mydumper;物理備份主要是Percona的xtrabackup工具。俗話說沒有最好的,只有最合適的,那麼在這些備份工具中,哪種工具最適合用於進行例項遷移呢?我們的答案是mydumper。
首先我們排除了xtrabackup,雖然物理備份在效能上有優勢,但其無法在遠端備份源例項,在進行例項遷移時,我們不可能要求使用者賦予操作源例項伺服器的許可權,尤其在遷移其他公有云平臺的RDS例項時更不現實。此外,物理備份產生的備份資料往往比邏輯備份匯出的資料更大,因為xtrabackup直接拷貝物理檔案,而邏輯備份是匯出SQL語句。下面是我們對幾種備份工具的對比測試結果,可供參考:
排除了物理備份後,還有三個選項:mysqldump、mysqlpump和mydumper。我們最終選擇了mydumper,因為mydumper是多執行緒的。等等!瞭解MySQL的同學會質疑,mysqlpump也是多執行緒的?對,mysqlpump的多執行緒思想甚至比mydumper更先進,詳見參考文獻1和2。但mysqlpump是表級的併發,且還不成熟,而mydumper是記錄級的併發,針對單個大表的場景,更容易發揮多執行緒優勢。
也許你會好奇,mydumper是如何實現記錄級的多執行緒一致性備份的,其備份流程圖如下:
mydumper由主執行緒和多個工作執行緒配合完成資料一致性備份,主執行緒執行FTWRL或Lock Tables tablelist Read阻塞寫操作來建立一致性備份點並記錄當前BinLog和GTID。工作執行緒在主執行緒仍持有鎖的情況下將各session的事務級別設定為可重複讀(repeatable-read),並開始進行快照讀,由於此時各表無法進行資料寫入或更新,所以工作執行緒快照讀的資料就是主執行緒建立一致性備份點的資料。待所有工作執行緒均已開始快照讀後,如果不存在MyISAM等非事務性表,主執行緒即可釋放讀鎖。mydumper原理的詳細分析詳見參考文獻3。
業務負載監控與調整
無論是物理備份還是邏輯備份,都會或多或少對資料庫線上業務造成影響。如何處理備份過程中對源例項業務的影響是我們需要解決的第二個問題。蜂巢RDS例項的設計原則是線上業務永遠比遷移任務更重要。由於無法有效瞭解源例項所在伺服器層的監控資料,我們在MySQL資料庫層進行大量的優化來減低影響,包括引入持鎖時間超時機制、基於業務負載智慧調整匯出併發度和InnoDB Buffer Pool(BP)汙染控制等。
如前所述,為了能夠得到一致性的資料,各種備份工具,包括xtrabackup和mydumper,都需要有個短暫給源例項加讀鎖的過程,正常情況下短暫,但也會有例外,如源例項中存在資料量較大的MyISAM表時,持鎖時間會變長。
為了能夠避免持鎖時間過長導致業務的寫操作被阻塞,使用蜂巢RDS進行例項遷移時,使用者可以選擇允許持有讀鎖的最長時間,如下圖所示,如果超過該閾值時間,會無條件解鎖並讓遷移操作失敗,使用者可以選擇在業務低峰期進行重試。
在順利加鎖建立一致性快照並解鎖後,就進入到各種Schema和表資料的匯出環節,使用者應根據源例項的線上業務負載和例項的伺服器IO能力來合理選擇匯出資料的併發執行緒數,如上圖所示。
業務負載並不總是可以預測的,但業務總是最重要的,那麼當短暫的業務高峰上來時,我們希望將伺服器有限的IO能力還給業務,而不是用在遷移上。蜂巢RDS提供了負載監控閾值選項,在業務負載超過該閾值時,會暫停遷移操作,直到負載重新低於閾值。如果使用者選擇了多執行緒匯出,則能夠根據業務負載動態調整執行緒個數,確保在業務優先的前提儘可能快速的完成資料匯出操作。下圖為基於業務負載自適應調整匯出執行緒的例子。
在邏輯匯出過程中,還會根據使用者提供的遷移賬號許可權,選擇性調整InnoDB BP引數來最大限度減小遷移連線的查詢操作對BP熱點資料的汙染。儘可能將因遷移而進入BP的資料保留在BP的LRU List冷資料一側,並儘快被替換出BP,詳見參考文獻4。當然設定BP的引數需要賬號有Super許可權,對於公有云上的源例項,無法進行該項優化。
多執行緒資料匯入
使用與mydumper配套的多執行緒恢復工具myloader來將備份的資料匯入到目標RDS例項上,myloader執行流程如下圖所示。由於此時目標例項沒有負載,所以可以儘可能調大匯入併發執行緒數,將目標例項的IO能力吃滿。此外,在資料匯入時,我們通過關閉slow log和binary log,將innodb_flush_log_at_trx_commit設定為0來最大限度提高匯入效能,在完成資料匯入後再將對應的引數調整為原值。這是我們解決第三個問題的方法。
在完成資料匯入後,對於全量遷移的場景,遷移就結束了。若選擇增量遷移,還需將資料匯出和匯入時在源例項上產生的增量資料(Update/Delete)也遷移到目標例項,我們採用MySQL複製的方式來同步這些資料。
由於MySQL 5.5、5.6和5.7版本的複製存在較大差別,我們根據源例項的版本選擇對應的目標例項版本。對於MySQL 5.5及更低版本的源例項,選擇網易開源MySQL版本InnoSQL 5.5.30作為目標RDS例項版本,對於MySQL 5.6和5.7,選擇InnoSQL 5.7.12為目標例項版本。進行上述版本配對的原因在於:
一是希望使用者儘可能採用MySQL最新的穩定版本5.7,因為MySQL 5.7是有史以來最好的版本,帶來了眾多優秀的特性,包括基於GTID的複製、sys表等,同時相比之前的版本解決或優化了大量缺陷或不足。
二是能夠更加方便地配置複製。MySQL 5.7版本提供了基於GTID和基於BinLog兩套複製機制,針對源例項的不同的複製配置,能無縫適配。使用者在遷移源例項時,可選擇遷移例項上全部資料庫,也可選擇僅遷移部分資料庫,MySQL 5.7版本可使用新增的“CHANGE REPLICATION FILTER”語法線上進行過濾複製設定而無需重啟mysqld。由於MySQL 5.5及更低版本無法滿足MySQL 5.7版本與之建立複製所需的例項UUID,所以目標例項使用InnoSQL 5.5.30版本。當然,相比社群版MySQL 5.5.30,InnoSQL 5.5.30實現了線上過濾複製功能。
我們採用並行複製技術來提高增量資料同步的效率,快速縮短主從複製延遲。由於MySQL 5.6版本GTID特性並不完善,在將其遷移到MySQL 5.7版本時,採用基於DATABASE的並行複製方式,避免LOGICAL_CLOCK並行複製時由於GTID EVENT未記錄並行資訊導致複製出錯的bug。這樣,第四個問題也得到了解決。
4如何高效完成遷移
相信大家都認同,例項遷移是個重型操作,誰都不會閒得無事對線上庫來一把例項遷移。既然決定要進行例項遷移,那麼就希望能夠一次性完成遷移,避免來回折騰。如何確保高效地遷移就顯得尤為重要,使用者需先進行遷移評估並完成準備工作,蜂巢RDS通過遷移預檢查、提供出錯重試等措施來提高遷移成功率。
遷移評估和準備
使用者首先需在遷移前做好評估工作,包括選擇業務低峰期進行遷移,這樣既最小化對業務的影響同時也能夠提高遷移速度;確認業務連線資料庫的配置能夠進行一次性切換,縮短切換所需時間,同時避免部分業務邏輯連線源庫,另一部分連線目標庫導致資料不一致;其次,根據所遷移的資料量,合理選擇目標例項的儲存空間,避免因為目標例項空間不足導致失敗;最後,還需要建立滿足遷移要求的資料庫賬號。
預檢查
我們希望在開始遷移前就發現所有可能引起遷移失敗的因素並糾正。遷移預檢查是重要手段,主要包括使用者在源例項建立的遷移MySQL賬號許可權檢查、MySQL引數設定檢查。
遷移許可權檢查用於確認遷移賬號是否能夠順利完成遷移操作,主要包括對資料庫定義、表定義,檢視、觸發器、儲存過程和函式等Schema的檢視許可權;對所選中資料庫中表的Lock Table許可權,及表中資料Select許可權;如果選擇增量遷移,則還需檢查賬號是否具備Replication slave和Replication client許可權等。通過查詢源例項的MySQL、information_schema或performance_schema等系統庫來檢查遷移所需許可權。MySQL引數檢查主要針對需要做增量資料同步的場景,如果使用者選擇增量遷移,源例項需正確設定server_id和log_bin等引數。如果在預檢查中發現錯誤,會給出明確的提示,引導使用者進行引數調整後再重新進行預檢查。
錯誤重試
在遷移過程中,提供了進度顯示功能,如下所示:
遷移的每個階段都會有帶進度條的百分比顯示,並週期性自動重新整理。同時還會顯示整體的遷移進度,方便使用者隨時檢視。若在資料匯出或匯入等階段發生錯誤,則會提示錯誤資訊,一般出現遷移錯誤的原因主要是由於存在MyISAM表導致持鎖時間超時,根據錯誤資訊可以對遷移引數進行鍼對性修改後進行重試,無需重新開始遷移。
結束遷移
在確認目標例項和源例項間沒有複製延遲後,就可以結束遷移並將業務的IP切換為目標例項IP,當然,在IP切換前,請確認已經在蜂巢RDS例項上建立業務訪問所需的資料庫賬號並賦予合適的許可權。
參考文獻:
- http://www.innoMySQL.com/article/25383.html
- http://MySQLserverteam.com/introducing-MySQLpump/
- http://www.innoMySQL.com/article/25456.html
- http://dev.MySQL.com/doc/refman/5.7/en/innodb-performance-midpoint_insertion.html
- http://dev.MySQL.com/doc/refman/5.7/en/replication.html
文章出處:DBApllus社群