攜程MySQL遷移OceanBase最佳實踐
一、前言
MySQL在業(yè)界流行多年,很好地支撐了攜程的業(yè)務發(fā)展。但隨著技術(shù)多元化及業(yè)務的不斷發(fā)展,MySQL也遇到了新的挑戰(zhàn),主要體現(xiàn)在:業(yè)務數(shù)據(jù)模型呈現(xiàn)多元化,OLTP和OLAP出現(xiàn)融合的趨勢;在MySQL數(shù)據(jù)庫上慢查詢治理成本高;使用傳統(tǒng)的分庫分表方案對開發(fā)不友好,核心數(shù)據(jù)庫改造成分庫分表方案,時間一般以年為單位。
分布式數(shù)據(jù)庫能比較好地解決上述問題,同時也帶來了新的挑戰(zhàn)。2021年,OceanBase(簡稱OB)開源,攜程開始逐步探索OceanBase的基本特性和應用場景。OceanBase兼容大部分MySQL的功能和語法,同時提供水平擴展性、強一致性和高可用性,能滿足業(yè)務需求并降低運維成本。因此,我們開始推進部分MySQL實例遷移到OB。為保證遷移順暢,我們設計了遷移評估工具、OB遷移流程、OB監(jiān)控大盤和OB故障診斷工具等。并將遷移過程中遇到的問題和大家進行分享。
二、評估工具
平滑遷移異構(gòu)數(shù)據(jù)庫,我們需要進行兼容性、性能和分區(qū)適應性等各項檢查。提前把不兼容或有可能引起遷移異常的場景找出來并解決。官方提供了OceanBase Migration Assessment(OMA)工具,用于異構(gòu)數(shù)據(jù)庫遷移到OB的可行性評估。遷移評估工具OMA有語法兼容性檢查和性能評估,但還不能完全滿足我們的需求。主要體現(xiàn)在下面幾點:
- 中間件版本檢查,一個DB有多個應用在訪問,只有某個版本后的中間件才開始支持OceanBase,需要檢查訪問該DB的所有應用的中間件版本,并督促開發(fā)進行升級,以確保都在支持OB版本之上。
- 性能采集和回放提供的MySQL General Log采集模式有一定風險,尤其是對于業(yè)務繁重的數(shù)據(jù)庫,我們需要更平滑的性能采集和回放方案。另外對于單實例多DB場景,存在遷移和不遷移的DB共存的情況,需要進行過濾。
- 線上存在非通過中間件訪問的數(shù)據(jù)庫賬號,如ETL取數(shù)賬號、數(shù)據(jù)查詢工具賬號、應用直連賬號等,對其兼容性需要進行檢查。因為遷移到OB之后,數(shù)據(jù)庫登錄賬號需要進行改變,包含租戶信息。
- OceanBase是分布式數(shù)據(jù)庫,數(shù)據(jù)如何進行分區(qū)就顯得非常重要,以避免形成熱點數(shù)據(jù)。一張表可能有多個字段都適合作為分區(qū)鍵,在遷移工具中,根據(jù)數(shù)據(jù)分布以及訪問情況,需要提供表分區(qū)推薦,以減少遷移成本。
因此我們對OMA評估工具進行了拓展和改造。在不影響現(xiàn)有的數(shù)據(jù)庫運行下,省去中間環(huán)節(jié),做到一鍵評估。其中MySQL數(shù)據(jù)采集與分析大致流程示意圖如下,全量數(shù)據(jù)導入OceanBase后,目標端我們用開源Locust工具,進行SQL回放和壓測,并最終形成評估報告。
三、遷移流程
在評估流程完成并且評估結(jié)果符合遷移要求的前提下,可以發(fā)起MySQL到OceanBase自動遷移流程。為減少遷移成本,我們把遷移流程進行了封裝,做到一鍵自動遷移,自動切換包含以下流程:
1)遷移前配置校驗。遷移前,會集中對所有的切換注意事項和相關(guān)配置再進行一次全面的檢查,提前排除配置問題可能導致的切換風險。
2)MySQL賬號兼容OceanBase帶租戶賬號創(chuàng)建。由于OceanBase是多租戶管理模式,應用的連接串必須指定租戶名,因此相應賬號需要在目標OB集群預先創(chuàng)建,中間件或工具切換賬號時,只需重置連接并切換到新賬號即可。
3)數(shù)據(jù)一致性校驗。數(shù)據(jù)通過Canal從MySQL同步到OB后,我們需要對一致性做校驗。校驗的方法是根據(jù)表主鍵進行切分,進行結(jié)果集比較是否一致。當遇到熱點表時,數(shù)據(jù)校驗過程會發(fā)起多次嘗試來反復驗證。
4)DDL表結(jié)構(gòu)修改暫停。由于MySQL和OceanBase表結(jié)構(gòu)變更方式差異較大,當DB遷移從MySQL到OceanBase觸發(fā)流程后,我們會在源MySQL禁止DDL操作。當然,如果開發(fā)有緊急發(fā)布需求,我們可以廢棄流程,等DDL發(fā)布完成后,再重啟遷移流程。
5)反向同步鏈路搭建。無論前面的遷移評估或者流程多么完善,反向同步鏈路對于異構(gòu)數(shù)據(jù)庫的遷移是必備的。一旦遷移出現(xiàn)異常,可以快速回退。反向同步鏈路是基于OceanBase的CDC服務,訂閱增量日志在MySQL端回放,保證遷移后OceanBase側(cè)和MySQL側(cè)數(shù)據(jù)始終一致。
當數(shù)據(jù)同步完成,并且沒有增量延遲后,遷移流程將生成具體的切換任務,切換流程如下:
我們只需要在預定的時間窗口內(nèi),點擊觸發(fā)切換流程,就可以完成從MySQL到OceanBase的切換。整個切換流程可在一分鐘之內(nèi)完成,而且業(yè)務端無需進行改造。我們擁有反向鏈路,如碰到有異常情況,可以隨時安排回退。反向鏈路在正常情況下將保留兩周以上。
四、OceanBase監(jiān)控
分布式數(shù)據(jù)庫和單機數(shù)據(jù)庫一個比較大的區(qū)別在于分布式監(jiān)控比單機版數(shù)據(jù)庫更為復雜。一是因為組件眾多,需要有一個全局視點;二是因為需要對告警點進行聚合。業(yè)務新遷移到OceanBase時,觀察集群監(jiān)控、關(guān)注告警信息是判斷遷移成功與否的關(guān)鍵。日常的冒煙現(xiàn)象或者不規(guī)范現(xiàn)象,需要及時發(fā)現(xiàn)、及時處理,避免問題惡化。準確監(jiān)控和及時告警可以幫助運維人員快速定位問題,快速解決故障。
4.1 監(jiān)控大盤
OceanBase的監(jiān)控數(shù)據(jù)主要通過在每臺Server上部署的Agent程序從本地直接采集。Agent中包含眾多組件,內(nèi)容如下:
Agent程序會向hickwall上報采集到的數(shù)據(jù),以模板化的形式展示出來,以此形成監(jiān)控大盤。如下圖所示:
4.2 告警郵件
OceanBase的告警,主要通過訂閱hickwall上的監(jiān)控數(shù)據(jù)以及定時的服務巡檢來完成。基于采集的監(jiān)控數(shù)據(jù)設立告警閾值,一旦指標超過閾值便會進行告警通知。另外,我們還會對配置進行定期檢查,來解決規(guī)范性問題等。
4.3 OceanBase SQL審計
OceanBase接入了攜程的SQL審計流程。與以往傳統(tǒng)的審計插件模式不同,現(xiàn)在以抓取網(wǎng)絡包的方式,通過對MySQL協(xié)議解析得到全量的SQL審計信息。接入審計流程后,可以快速定位到SQL信息,包括應用編號、訪問IP、執(zhí)行參數(shù)、有無報錯信息等。
4.4 OceanBase審計運用案例
在使用MySQL command-line tool連接OceanBase過程中出現(xiàn)連接不上的錯誤時,我們使用SQL審計日志進行定位,發(fā)現(xiàn)客戶端在連接OB的過程中會執(zhí)行一些元數(shù)據(jù)查詢工作,在進行show tables這一步驟后會報錯斷連,后續(xù)定位到一個特殊的表,該表表名的最后一個字符是分號(t_sample;)導致了這次報錯,隨即我們在開源社區(qū)反饋了這例問題。
五、OceanBase自動故障診斷
隨著越來越多的MySQL遷移到OceanBase,數(shù)據(jù)庫性能、故障定位的實時性和準確性的要求變得越來越高。自動故障診斷系統(tǒng)可以全方位、及時、精準地定位線上問題,為運維和排障提供依據(jù)。
5.1 構(gòu)建實時性能數(shù)倉
OceanBase性能數(shù)倉構(gòu)建的流程圖如下:
- 收集性能指標相關(guān)數(shù)據(jù),以下是常用的性能指標對應的數(shù)據(jù)源:
- 開發(fā)數(shù)據(jù)收集程序,在服務器本地每10秒采集一次上述性能指標的數(shù)據(jù)。并在采集之后對數(shù)據(jù)進行結(jié)構(gòu)化處理,包括對數(shù)值型數(shù)據(jù)進行標準化處理,對文本型數(shù)據(jù)進行時序化處理。
- 將結(jié)構(gòu)化處理之后的數(shù)據(jù)落地存儲到ClickHouse中。
5.2 自動化分析
自動化分析的流程圖如下:
5.3 實時檢測性能指標
通常判斷性能異常的指標包括CPU占用率、磁盤IO占用率、Threads Running、QPS、網(wǎng)卡流量等?;谶\維經(jīng)驗,可以針對每個指標設定相應的閾值,當突破閾值時,則認為當前實例存在性能問題。比如CPU占用率高于65%或磁盤IO占用率高于80%則代表服務器出現(xiàn)異常。
5.4 異常數(shù)據(jù)匹配數(shù)倉
首先,對于數(shù)值型數(shù)據(jù),分析工具會自動選取故障指標和故障時間段,通過相似性匹配數(shù)倉中數(shù)據(jù)所有數(shù)值型數(shù)據(jù)包含SQL、Table、Perf三種類型,它們相關(guān)的性能指標說明如下:
- SQL對應的性能指標:
執(zhí)行次數(shù)、總耗時、CPU耗時、邏輯讀次數(shù)、物理讀次數(shù)等。
- Table對應的性能指標:
增刪改行數(shù)、增刪改的SQL數(shù)、相關(guān)事務數(shù)等。
- Perf對應的性能指標:
CPU、I/O、RPC時長、索引緩存大小、緩存命中率等。
其次,對于文本型數(shù)據(jù),分析工具會通過故障時間區(qū)間獲取所有時序化的文本數(shù)據(jù),通常包含:
- 數(shù)據(jù)庫服務日志、系統(tǒng)內(nèi)部任務記錄、數(shù)據(jù)庫進程信息等。
最后,基于前面兩種類型的數(shù)據(jù)進行綜合性分析,分析要點主要有:
- SQL層面:
SQL性能消耗占比、有無正在執(zhí)行的慢SQL、是否缺失索引、是否存在遠程執(zhí)行或分布式執(zhí)行等。
- OceanBase內(nèi)部:
OceanBase是否在做合并、是否正在均衡副本、是否存在其他異常日志等。
- 應用層面:
客戶端是否進行發(fā)布。
最終基于以上自動化分析,實現(xiàn)服務器性能波動真實原因的精準定位,自動生成故障定位分析報告, 并通過郵件及時推送給DBA和相關(guān)開發(fā)人員。
5.5 運用案例
下面基于該工具自動生成的一例分析報告來介紹該工具的實際運用:
- 報告的故障指標板塊顯示4:30后服務器的CPU上升;
- 報告的OceanBase相關(guān)表板塊顯示CPU上升趨勢和下面這張表的訪問趨勢一致;
- 報告的OceanBase相關(guān)SQL板塊顯示這張表的訪問趨勢和下面的SQL語句訪問趨勢一致;
- 報告的分析結(jié)果板塊定位到CPU上升和tablex表的訪問上升有關(guān),而這張表的訪問上升又和這1條SQL語句訪問耗時增長有關(guān),最終定位由于該SQL導致CPU上升。后續(xù)我們聯(lián)系開發(fā)確認是正常業(yè)務上升,并添加服務器節(jié)點緩解CPU負載。
六、遷移遇到的問題和實踐
6.1 .Net應用訪問OceanBase失敗
在使用和測試OceanBase的過程中,我們發(fā)現(xiàn).Net應用的官方MySQL連接器連接OceanBase執(zhí)行SQL失敗。
經(jīng)排查,我們發(fā)現(xiàn).Net應用依賴連接中的ConnectionCharSetIndex,而OceanBase不存在Cnotallow=83即utf8_bin,只有utf8mb4_bin。因此我們對OceanBase的源碼進行了修復來滿足這類應用對OceaBase的適配性。
總結(jié):OceanBase不夠完美,但是隨著時間推移,通過反復的測試和迭代,正在逐步完善它的各方各面。我們也參與其中,以運維和產(chǎn)品使用者的視角對它進行優(yōu)化和完善。
6.2 Druid應用不兼容部分OB語法解析
我們在開發(fā)Oceanbase表結(jié)構(gòu)設計工具的時候,發(fā)現(xiàn)OceanBase的SQL通過Druid解析時存在報錯。這個錯誤會導致在表結(jié)構(gòu)設計的時候?qū)隨QL DDL語句報錯。遇到問題后,我們先調(diào)整到Druid最新版本,發(fā)現(xiàn)問題仍然存在。
我們將問題先從復雜的表結(jié)構(gòu)設計中抽離出最簡單的SQL DDL, 并結(jié)合分析Druid的源代碼,發(fā)現(xiàn)原來Druid代碼對OceanBase的兼容在SQLIndexDefinition中實現(xiàn),但沒有在SQLIndexOptions實現(xiàn)。根據(jù)OceanBase的語法樹,實際應該在SQLIndexOptions實現(xiàn)才合理,找到問題所在后,我們提交了Pull Request, 然后被合并到Druild主線。問題得以解決。
總結(jié):開源工具的一個好處在于碰到問題后我們可以進行代碼分析。并快速定位問題,最后反饋社區(qū)。
6.3 OceanBase讀寫分離支持
讀寫分離是數(shù)據(jù)庫非常重要的能力,在業(yè)務層面上,它覆蓋到了ETL取數(shù),BI報表生成,緩存刷新等多個場景。Oceanbase雖然支持讀寫分離功能,但需要在代碼層顯性設置弱一致性讀參數(shù),存在對業(yè)務高度侵入的缺陷。我們對OceanBase訪問代理OBProxy做了代碼改造,新增enable_weak_read以及weak_read_user_list兩個參數(shù),通過代理層控制開啟讀寫分離策略,對應用透明度高。
讀寫分離場景下,應用與OBProxy建聯(lián)的流程示意圖如下:
基于以上的代碼修改,我們設計了一套優(yōu)化版本的讀寫分離方案,即通過以賬號維度來控制是否使用讀寫分離。流量調(diào)度示意圖如下:
總結(jié):OceanBase源生雖然提供了強大的功能,但是它并不一定100%滿足業(yè)務的場景和需求,因此對其組件進行二次開發(fā)是有必要的。我們不單單對于OBProxy進行了相關(guān)的功能適配,對于其他組件如cdc、Deploy組件等我們也根據(jù)實際場景需求,進行相應調(diào)整。
6.4 query range過大導致內(nèi)存溢出
在初期使用OceanBase時,我們有碰到過Server Crash的經(jīng)歷。當一個查詢的條件中IN運算符中包含過多元素(一萬級別以上)時,會爆出stack overflow的異常。
經(jīng)過分析和社區(qū)交流,我們定位到優(yōu)化器在抽取query range會耗費大量的內(nèi)存。而OceanBase在算法迭代過程中沒有檢查查詢超時,導致該查詢一直消耗內(nèi)存,直到用盡了 SQL ARENA的內(nèi)存。這種模式?jīng)]有做好防御機制,從而導致內(nèi)存溢出造成系統(tǒng)崩潰。這個問題在新版本中已經(jīng)得到修復。當確認到問題后,我們第一時間通知開發(fā)減少IN內(nèi)的元素數(shù)量,并安排了版本升級。
總結(jié):OceanBase作為新鮮產(chǎn)品,社區(qū)論壇和Git issue是獲取日常運維和快速排障方案的利器,根據(jù)各種技術(shù)探索和交流分享,可以汲取優(yōu)質(zhì)內(nèi)容,收獲前沿知識,快速定位和解決問題。
6.5 修正執(zhí)行計劃
在遷移前后,數(shù)據(jù)庫的SQL性能是最值得關(guān)注的地方。作為分布式數(shù)據(jù)庫,OceanBase的優(yōu)化器相較于MySQL來說更復雜并且由于其特殊的存儲結(jié)構(gòu)導致表的統(tǒng)計直方圖刷新頻率很低,因此當可用索引和查詢條件的適配度不高時,優(yōu)化器在選擇執(zhí)行計劃時可能存在偏差。OceanBase自帶修正執(zhí)行計劃的能力,即通過在數(shù)據(jù)庫層面直接指定同類型SQL以outline注釋的方法強制綁定執(zhí)行計劃。
總結(jié):OceanBase相較于傳統(tǒng)數(shù)據(jù)庫,其分布式的架構(gòu)和特殊的存儲結(jié)構(gòu)也會帶來運維門檻的提高,不過它同時也給予運維人員更高的自由度。運維人員需要熟悉并掌握這些強大的功能和運維技巧,使線上業(yè)務具備更好的穩(wěn)定性。
七、未來展望
OceanBase開源已經(jīng)一年有余,我們的運維工具也逐漸趨于成熟,運維能力也在逐步提高。越來越多的MySQL正在逐步往OceanBase上遷移。隨著OceanBase 4.0版本的推出,許多新特性也已經(jīng)在逐步測試中。我們對4.0版本的新功能也非常期待。
7.1 單機分布式一體化架構(gòu)
OceanBase 4.0版本推出單機分布式一體化架構(gòu),支持類似MySQL的輕量化單機模式部署,同時也可以在必要時迅速地擴容成分布式模式來提高性能上限。單機與分布式的靈活切換可以大大降低成本,并且基于源生主備庫的能力可以快速的完成主備的DR切換,有更強的高可用性保證。
7.2 兼容性增強
OceanBase對MySQL的高兼容性一直是我們考量的重點,高度兼容為開發(fā)同事節(jié)省了大量學習成本和代碼成本。在4.0版本中,在字符集、約束、函數(shù)、存儲過程等多方面與MySQL的匹配度更高,在使用上與MySQL更加接近。
當然,兼容性還包括對MySQL生態(tài)的兼容,包括binlog兼容、canal兼容、閃回工具兼容等等。
7.3 運維能力提升
OceanBase作為分布式數(shù)據(jù)庫,組件多、運維環(huán)境復雜是痛點。我們后續(xù)將基于現(xiàn)有的日志收集工具和分析工具,完成鏈路式的問題診斷,更精準地定位性能問題、集群內(nèi)部任務問題等。