自建MySQL實例遷移到雲平台實踐
(文中圖都掛,待補上)
簡介
我們把資料庫中部分或全部Schema和數據遷移到另一個實例的行為稱為實例遷移,將導出數據的實例稱為源實例,導入數據的實例稱為目標實例。根據遷移資料庫類型的不同,可以分為同種資料庫之間的遷移,如從MySQL遷到MySQL;跨資料庫類型的遷移,如從Oracle遷移到MySQL等。網易蜂巢是網易公司提供的全新公有雲平台,在資料庫產品(蜂巢RDS)中提供了業界領先的MySQL實例遷移功能,本文將介紹蜂巢RDS實例遷移功能的實現,並探討如何高效完成實例遷移任務。
使用場景
那麼,為什麼要進行MySQL實例遷移呢?實例遷移的場景歸納起來主要有以下幾種:
1、從自建實例遷移到RDS:在雲服務還未充分推廣時,存在大量的自建資料庫實例,舉網易公司為例,網易博客、網易郵箱等產品數百個MySQL實例直接部署在物理伺服器上,隨著業務的擴展,必然要對實例進行擴容、升規格等操作,相比自建實例,RDS實例在故障處理、在線擴容、升級等方面存在天然的優勢,所以,目前絕大部分網易互聯網產品的資料庫均已使用實例遷移功能遷移到RDS上;
2、從其他公有雲平台遷移到RDS:網易蜂巢推出近一年以來,廣受用戶好評,很多用戶將部署在其他公有雲平台上的MySQL實例遷移到蜂巢RDS上,享受更加專業而貼心的資料庫服務,蜂巢RDS實例遷移功能使用情況進行統計發現有50%是用於遷移其他公有雲的MySQL實例。
實例遷移技術實現
在設計實例遷移功能前,我們對業界公有雲進行了充分調研,僅有兩家主流公有雲平台提供實例遷移功能,那麼為什麼僅兩家呢,主要是因為提供在線實例遷移功能需要解決一系列問題,概括起來有以下幾點:
1、如何快速地對源實例進行一致性數據備份?
2、如何處理備份過程中對源實例業務的影響?
3、如何快速地將備份導入到目標實例?
4、如何同步源實例的增量數據到目標實例?
5、如何確保實例遷移高效完成?
下面為您逐條解析蜂巢RDS是如何解決這些難題的。
多線程邏輯備份
蜂巢RDS解決第一個問題的方法是採用多線程邏輯備份的方式來進行源實例一致性數據導出。MySQL的數據備份工具有很多,邏輯備份工具包括經典的mysqldump,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 Tablestablelist 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)也遷移到目標實例,蜂巢RDS採用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版本可使用新增的「CHANGEREPLICATION 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。這樣,第四個問題也得到了解決。
如何高效完成遷移
相信大家都認同,實例遷移是個重型操作,誰都不會閑得無事對線上庫來一把實例遷移。既然決定要進行實例遷移,那麼就希望能夠一次性完成遷移,避免來回折騰。如何確保高效地遷移就顯得尤為重要,用戶需先進行遷移評估並完成準備工作,蜂巢RDS通過遷移預檢查、提供出錯重試等措施來提高遷移成功率。
遷移評估和準備
用戶首先需在遷移前做好評估工作,包括選擇業務低峰期進行遷移,這樣既最小化對業務的影響同時也能夠提高遷移速度;確認業務連接資料庫的配置能夠進行一次性切換,縮短切換所需時間,同時避免部分業務邏輯連接源庫,另一部分連接目標庫導致數據不一致;其次,根據所遷移的數據量,合理選擇目標實例的存儲空間,避免因為目標實例空間不足導致失敗;最後,還需要創建滿足遷移要求的資料庫賬號。
預檢查
我們希望在開始遷移前就發現所有可能引起遷移失敗的因素並糾正。遷移預檢查是重要手段,主要包括用戶在源實例創建的遷移MySQL賬號許可權檢查、MySQL參數設置檢查。
遷移許可權檢查用於確認遷移賬號是否能夠順利完成遷移操作,主要包括對資料庫定義、表定義,視圖、觸發器、存儲過程和函數等Schema的查看許可權;對所選中資料庫中表的Lock Table許可權,及表中數據Select許可權;如果選擇增量遷移,則還需檢查賬號是否具備Replicationslave和Replication client許可權等。通過查詢源實例的mysql、information_schema或performance_schema等系統庫來檢查遷移所需許可權。MySQL參數檢查主要針對需要做增量數據同步的場景,如果用戶選擇增量遷移,源實例需正確設置server_id和log_bin等參數。如果在預檢查中發現錯誤,會給出明確的提示,引導用戶進行參數調整後再重新進行預檢查。
錯誤重試
在遷移過程中,提供了進度顯示功能,如下所示:
遷移的每個階段都會有帶進度條的百分比顯示,並周期性自動刷新。同時還會顯示整體的遷移進度,方便用戶隨時查看。若在數據導出或導入等階段發生錯誤,則會提示錯誤信息,一般出現遷移錯誤的原因主要是由於存在MyISAM表導致持鎖時間超時,根據錯誤信息可以對遷移參數進行針對性修改後進行重試,無需重新開始遷移。
結束遷移
在確認目標實例和源實例間沒有複製延遲後,就可以結束遷移並將業務的IP切換為目標實例IP,當然,在IP切換前,請確認已經在蜂巢RDS實例上創建業務訪問所需的資料庫賬號並賦予合適的許可權。
總結
實例遷移功能2014年上線網易RDS私有雲,2016年上半年我們對實例遷移功能及前端交互界面做了大量優化,正式發布蜂巢RDS。截止目前,已經遷移了網易公司內外數百個MySQL實例到RDS上,其中不乏數據量數百GB的大庫和大表,MySQL版本橫跨MySQL 5.1到MySQL 5.7。蜂巢RDS實例遷移功能是個經過實戰優化的成熟功能,在此過程中我們也積累了豐富的遷移經驗,歡迎大家使用蜂巢RDS的遷移功能將MySQL實例遷移到網易蜂巢上。
參考文獻
1、 Oracle官方並行邏輯備份工具mysqlpump 最有態度的MySQL社區
2、 Introducing mysqlpump
3、 開源MySQL多線程邏輯導出工具mydumper原理與改進 最有態度的MySQL社區
4、 15.6.3.4 Making the Buffer Pool Scan Resistant
5、 MySQL 5.7 Reference Manual :: 18 Replication
推薦閱讀:
※簡單說明下MySQL的內存使用
※Mysql 知識點
※1.3 Mysql 安裝與使用-基礎配置-NodeJs+Express+Mysql實戰
※如何快速了解資料庫,有否推薦書籍?
※mysql,zk這些強一致性的軟體為什麼要先寫日誌?