1. 程式人生 > 程式設計 >汽車之家從 SQL Server 到 TiDB 的異構變遷

汽車之家從 SQL Server 到 TiDB 的異構變遷

作者:汽車之家技術學院-技術架構組

SQL Server + .Net 是很多早期網際網路企業的標配技術棧,雖然 TiDB 是相容 MySQL 協議和生態的資料庫,但是 TiDB 適用的業務場景是通用的。在開源新技術大行其道的今天,如何從 SQL Server 無縫遷移至 TiDB,汽車之家做了一個創新的示範。

本文將從業務背景、遷移方案、同步、業務改造、上線效果、周邊建設等多個角度,詳細介紹瞭如何從 SQL Server 資料庫遷移至 TiDB 資料庫。相信無論你是架構師、業務開發、還是 DBA,都會有不同層面的收穫。

一、專案背景

汽車之家社群於 2005 年上線,作為汽車之家最老的業務之一,十四年來沉澱了億級帖子、十億級回覆資料,目前每天有千萬級 DAU、億級的訪問量,介面日均呼叫量 10 億+ 次 。期間經歷過架構升級重構、技術棧升級等,但其資料始終存放在 SQL Server 中。隨著資料的不斷遞增,我們在使用 SQL Server 資料庫方面遇到了很多瓶頸,以至於我們不得不尋找一個新的資料庫替換方案。

二、使用 SQL Server 遇到的瓶頸

隨著業務的不斷擴大,汽車之家社群的訪問量和發表量不斷上漲,遇到的資料庫問題也越來越多,下面列舉兩個必須很快解決掉的問題:

  1. 歷史上,汽車之家社群回覆庫採用了分庫分表的設計,用以解決 SQL Server 單表過大時效能下降等問題。時至今日,回覆庫有 100+ 個庫、1000+ 張表(根據帖子 ID 分庫分表)。這本身並沒有問題,程式碼寫好了,資料該寫哪裡寫哪裡,該讀哪裡讀哪裡。但是隨著應用的發展、需求的變化,我們發現在實現某些需求時,分庫分表的結構難以滿足。我們需要資料邏輯上在一張表裡。

  2. 近些年來,隨著業務加速成長,資料量突飛猛進,而硬碟容量是有限的,每臺伺服器上能擴充套件的硬碟數量也是有限的,致使每隔一段時間都要增加更大容量的儲存伺服器來應對。而且這個事情一開始是很複雜的,涉及到很多關聯專案,即便到現在我們輕車熟路了,每次換伺服器的時候依然需要關注它,並且大容量資料庫伺服器價格昂貴。我們需要讓擴容對應用來說,無感知。

三、分散式資料庫調研

3.1 確定方向

在 2018 年底的時候,公司專門成立了虛擬架構組來調研新的資料庫來解決汽車之家社群遇到的問題。經過各種分析和測試,今年年初確定方向為分散式資料庫,一共調研了三款當前比較火的分散式資料庫:TiDB(PingCAP),Ignite(ASF-TLP) 和 CockroachDB。經過無數次測試我們最終選擇了 TiDB,主要有以下幾個原因:

  1. 相容 MySQL 協議與生態,上手門檻低;

  2. 跟 TiDB 官方一直保持比較好的技術溝通;

  3. TiDB 公司在北京,有問題可以當面解決;

  4. TiDB 的設計架構更加優秀;

  5. 官方社群比較活躍,檔案豐富;

  6. 官方的技術人員經常到公司進行交流。

TiDB 的研發同學到之家進行技術交流

我們去 TiDB 進行系統的課程培訓

下面引用 TiDB 官方的一段描述:

TiDB 是一款定位於線上事務處理、線上分析處理(HTAP: Hybrid Transactional/Analytical Processing)的融合型資料庫產品,實現了一鍵水平伸縮,強一致性的多副本資料安全,分散式事務,實時 OLAP 等重要特性。同時相容 MySQL 協議和生態,遷移便捷,運維成本極低。

從中我們不難發現,TiDB 切實解決了我們在應用 SQL Server 時候的痛點:

  • 水平伸縮:在當前叢集內可以隨時加節點,更換節點也輕而易舉。
  • 海量資料支援:基於其特性以及業內使用的經驗,十億乃至百億級別的資料量輕鬆搞定。
  • 高可用:相較 SQL Server 的主從模式,TiDB 基於 Raft 協議,可以實現 100% 的資料強一致性,並且多數副本可用的情況下,可實現自動故障恢復。
  • HTAP:TiDB 自身就支援一定程度的 OLAP 場景,更復雜的 OLAP 分析可以通過 TiSpark 專案來完成。對於更深度的 OLAP 應用,我們也已經在實踐的路上。

3.2 實踐出真知

基於以上理論的支援,我們進行了大量的功能測試、效能測試、異常測試、業務接入測試等。

  1. OLTP 測試:2000 萬資料,500 併發執行緒測試,在 OLTP 場景測試下 TiDB 的響應時間 99% 在 16ms 以內,滿足業務需求。且在資料量級越來越大的情況下,TiDB 會體現出更大的優勢,後續還可以通過新增 TiDB/PD/TiKV 節點來提高讀寫效能,如下圖所示:

  2. OLAP 測試:50G TPC-H 測試,TiDB 相較 MySQL 有很大的速度優勢:

    TPC Benchmark™H(TPC-H) 是決策支援基準。 它由一套面向業務的臨時查詢和併發資料修改組成。 選擇查詢和填充資料庫的資料具有廣泛的行業範圍相關性。 該基準測試說明瞭決策支援系統,該系統可檢查大量資料,高度複雜地執行查詢併為關鍵業務問題提供答案。

  3. 異常測試:我們測試了 PD、TiKV 異常宕機情況下的表現,對業務影響很小,可實現自動故障恢復。

四、遷移方案

4.1 遷移前需要解決的問題

在真正的資料遷移之前,我們還有一些實際問題需要解決:

  • SQL Server 和 TiDB 的部分欄位型別是不一樣的。通過查閱相關檔案,將不同的欄位一一對應後再在 TiDB 中建表,例如 DATETIME 的精度問題。

  • 同步時將分庫分表的資料合併到一個表裡。值得慶幸的是原有設計中,我們除了自增主鍵 ID,還有一份業務 ID,其在各個表中均不重複,這樣省了不少事情。

  • 一次性匯入十億級資料以及後續增量同步的過程中,如何保證資料的一致性。

  • 如果 TiDB 在生產時出現了不可預估的問題,一時無法解決,那我們必須立刻切換到 SQL Server,保證業務不受影響。換句話說,在 TiDB 中產生的資料需要實時同步回 SQL Server。

  • 因為訪問量比較大,切換時間必須控制在秒級。

  • 因為 SQL Server 是商業資料庫,跟開源資料庫進行資料同步的方案較少,所以同步方案、架構設計、研發、測試必須我們自己解決。

4.2 整體遷移架構圖

下圖是我們整個遷移過程的架構圖,包含 SQL Server 到 TiDB 的全量同步、增量同步,以及 TiDB 到 SQL Server 的反向同步過程。

現在,需要確定的是整個專案的遷移流程,有了大的方向,在實施中目標會更明確一些。

以汽車之家社群的業務形態以及資料量級來看,動輒十多個小時的離線遷移是完全不可能接受的,我們只能在凌晨 1:00-3:00 這個時間視窗來完成遷移,且時間越短越好。

所以我們選擇線上遷移的方案,線上遷移稍微複雜一些,流程上有準備全量資料,然後實時同步增量資料,在資料同步跟上(延遲秒級別)之後,採用滾動升級的方式將應用的讀流量切換到 TiDB 上。

觀察應用正常執行,進行短暫停機和關停 SQL Server 寫許可權,確保沒有資料再寫入 SQL Server, 就可以將寫流量指向 TiDB,至此遷移完畢。

整個遷移流程中,應用的讀資料場景不受影響,寫入場景受影響週期為停機(關寫許可權)到寫流量指向 TiDB。

下圖是我們梳理出來的流程圖,我們在整個遷移的過程中必須嚴格按這些流程執行。

下面我們來詳細介紹全量和增量同步的實施方案。

五、全量同步

首先我們要感謝以下兩個開源專案,站在巨人的肩膀上使我們節約了很多時間。

愚公是阿里巴巴推出的一款 Oracle 資料遷移同步工具,而作者 alswl 在此基礎上實現了 SQL Server 資料來源的支援。在此愚公的使用方法我們不再贅述,感興趣的同學請自行檢視。

在認真拜讀了大神的專案,並進行了相關測試後,發現它並不能 100% 滿足我們的需求。

Yugong 資料流是標準 ETL 流程,分別有 Extractor、 Translator、Applier 這三個大類來實現 ETL 過程。

首先講 Extractor,愚公原有的配置方式是將需要匯出的庫表寫在配置檔案當中,這對於 1000+ 張表來說,太不現實了。這裡我們增了一個新特性,在不配置需要匯出的表名的情況下,將資料庫中所有的使用者表讀出來,並通過一個新增的配置項進行正則匹配,以此決定哪些表需要進行資料同步。

#查詢表
SELECT name FROM sys.databases WITH (nolock) WHERE state_desc = 'ONLINE'

#查詢開啟CDC的表
SELECT name FROM %s.sys.tables t WITH (nolock) JOIN %s.[cdc].[change_tables] ct WITH (nolock) ON t.object_id = ct.source_object_id

複製程式碼

其次,合庫合表後,原有 SQL Server 中各個表的自增主鍵 ID 衝突,所以新增實現 RowDataMergeTranslator,其功能是,讀取記憶體中的 RowData 然後進行轉換,將從 SQL Server 中讀取的行資料,丟棄其原有的主鍵列,轉而使用 TiDB 生成。並根據配置檔案決定哪些表需要實現這一特性。

record.removeColumnByName(config.getDiscardKey());
複製程式碼

最後的 Applier 並未做改動,處理好的資料直接寫入 TiDB。

自此合庫合表的事情我們解決了。

六、增量同步與實時校驗

在實現這部分需求的時候,我們應用了 SQL Server 的 CDC,並在增量同步的基礎上增加了延遲驗證資料正確性的功能。更多關於 CDC 的內容,這裡不再贅訴,你只需要知道它能獲取到增量資料,參考 CDC官方檔案

需要注意的是,CDC 開啟的時機需要在全量同步之前,保證 CDC 記錄可以覆蓋全量同步過程中產生的增量資料。

根據以上的流程圖可以看到,Producer 從 SQL Server 中讀取 CDC 日誌,並將其轉化成一條包含表資訊、列資訊和行資料的訊息,投遞到 Kafka 中。下游的消費者在拉取到訊息之後,把資料轉化成相容 MySQL 的 SQL 語句在 TiDB 中執行(這裡也實現了合庫合表),從而實現整個資料增量同步的過程。

這裡還有另一個消費者實現資料校驗功能,它會延遲五秒消費同一佇列,並通過提取主鍵(或索引)的方式從 TiDB 中查出該條已經寫入的資料,將兩側的整行資料做比較(本實踐中去除主鍵後比較),如果有問題會進行嘗試重新寫入,如出現異常則向相關人員傳送報警。

在實現了這些並進入到測試階段後,我們發現了一個問題,1000+ 回覆表,對應 1000+ CDC 日誌表,一個 Producer 就需要開啟 1000+ 執行緒。以設計的 5s 間隔去輪詢這些表時,伺服器 CPU 直接就跑滿了,產生了大量執行緒等待,輪詢 CDC 日誌的及時性無法保證。通過分析業務和 DBA 查詢得知,其實汽車之家社群每天產生的回覆有 95% 都集中在最新的 5% 的帖子當中。換言之,我們只有幾十張表需要如此高頻的去檢索 CDC 日誌,其他的表我們通過增加輪詢間隔、分批部署等方式,將這個問題解決了。

細心的同學讀到這裡會發現,校驗功能其實邏輯上並不嚴謹,如果說在五秒鐘內上游資料產生了變更,就有可能會產生拿著新資料去校驗老資料的問題。這裡有兩個解決方案:

  • 採用單 partition 的 topic 和單個消費程式,保證增量同步和校驗的順序嚴格一致,但此種方案效能相對較低,可用性無法保證。

  • 我們將 SQL Server 中的錶行加入上版本戳(rowversion),將版本戳一併同步到 TiDB 中。校驗時比較該值,如不一致則放棄本次校驗。本方案會損失一定的校驗樣本,但可通過增加 Partition 和消費者提高效能和可用性。

七、回滾方案

之前我們提到了,當專案切換到 TiDB 以後,需要預防其出現不可預估的問題,能夠隨時切回 SQL Server 才能保障萬無一失。

TiDB Binlog 使得這件事情輕而易舉。我們使用官方提供的 Pump 和 Drainer 將 Binlog 抽取到 Kafka 之中,解析資料變更的內容,根據業務 ID 計算出資料在 SQL Server 中原本屬於哪個庫哪個表,然後進行資料同步。

解析 Binlog (Protobuf 協議)

通過業務 ID 決定資料寫到哪個庫表

八、汽車之家社群業務 TiDB 遷移改造

就業務的改造這一環節,因歷史積澱,需修改的地方很多,分佈於各個專案之中,我們採取通過介面查詢實現、搜尋程式碼、DBA 幫助抓取 SQL 的方式,保證涵蓋了 100% 的相關業務,只有這樣才能保障上線後無故障。

  • 資料訪問層增加對 MySQL 語法的支援。

  • 去掉 SQL Server 中的儲存過程。

  • SQL Server 和 TiDB(MySQL)的語句和函式支援不盡相同,逐個改造、測試並優化。

  • 根據 TiDB 索引的原理以及梳理出來的 SQL 語句,重新建索引。

與此同時,我們針對每一條改造後的 SQL 都進行了優化,使可以精確的命中最優的索引,從而實現了在十億級資料量下,TP 業務 99% 的響應時間在 12ms,99.9% 的響應時間在 62ms。

九、TiDB 周邊體系建設

除以上遷移流程所涉及到的功能點以外,我們還制定了一些開發規範和一些實用工具的研發,用以保障 TiDB 在汽車之家更好的應用。

  • 我們建立了完善的 TiDB 開發規範、運維規範、上線規範,並在公司內部對開發同學進行相關的培訓。

  • 開發了實時慢 SQL 分析工具——TiSlowSQL,該工具可以提供實時、多維度、全視角的 SQL 報告,幫助我們快速定位慢 SQL 導致的叢集級故障。

  • 為解決監控單點問題,我們自己開發了一套監控工具,對 TiDB 核心元件進行監控,後續會將監控系統統一遷移到之家雲平臺。

  • 定期在汽車之家大學舉行技術培訓,定期在組內進行技術分享,經驗總結。

TiSlowSQL 也是汽車之家運維組參加 Hackathon 專案,具體內容敬請期待後續文章!

十、總結與展望

汽車之家社群已於 9 月底正式上線分散式資料庫 TiDB,目前執行穩定。在其他業務遷移完成之後,汽車之家社群的 SQL Server 服務會逐步下線。對於本次遷移的過程我們做了以下幾點總結:

  • 通過不斷的優化 SQL,目前線上 TP99 穩定,與遷移之前並無太大差別,跟測試效果相符。對使用者和業務都無感知。

  • 隨著業務的不斷擴大,可以更好的應對資料的暴增,再擴容叢集就不需要找昂貴的大儲存機器,而且可以線上不停業務隨時擴容。

  • 本次遷移我們積累了 SQL Server 轉 TiDB 的很多經驗,可以為其他團隊使用分散式資料庫 TiDB 提供技術支援,讓其他團隊在遷移過程中節省時間。

  • 目前正在與 TiDB 官方溝通,準備把遷移方案和與業務無關的遷移邏輯放到開源社群。

由 SQL Server 遷移至 TiDB,從傳統關係型到分散式 HTAP,從商業授權到開源社群,是汽車之家社群歷史上一次重大的技術方向轉型。

汽車之家有很多海量資料的應用場景,這一次從 SQL Server 到分散式資料庫 TiDB 的遷移,為我們以後其他業務遷移至 TiDB 打下了良好的基礎,也與 TiDB 官方建立了良好的定期溝通機制。希望 TiDB 官方一如既往的快速迭代,我們也會和 TiDB 官方合作開發一些比較實用的功能。

關於 TiDB 使用上的疑惑或經驗,可以登陸 www.asktug.com 和大家一起交流~