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

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

SQL Server + .Net 是不少早期互聯網企業的標配技術棧,雖然 TiDB 是兼容 MySQL 協議和生態的數據庫,可是 TiDB 適用的業務場景是通用的。在開源新技術大行其道的今天,如何從 SQL Server 無縫遷移至 TiDB,汽車之家作了一個創新的示範。github

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

1、項目背景

汽車之家社區於 2005 年上線,做爲汽車之家最老的業務之一,十四年來沉澱了億級帖子、十億級回覆數據,目前天天有千萬級 DAU、億級的訪問量,接口日均調用量 10 億+ 次 。期間經歷過架構升級重構、技術棧升級等,但其數據始終存放在 SQL Server 中。隨着數據的不斷遞增,咱們在使用 SQL Server 數據庫方面遇到了不少瓶頸,以致於咱們不得不尋找一個新的數據庫替換方案。數據庫

2、使用 SQL Server 遇到的瓶頸

隨着業務的不斷擴大,汽車之家社區的訪問量和發表量不斷上漲,遇到的數據庫問題也愈來愈多,下面列舉兩個必須很快解決掉的問題:安全

  1. 歷史上,汽車之家社區回覆庫採用了分庫分表的設計,用以解決 SQL Server 單表過大時性能降低等問題。時至今日,回覆庫有 100+ 個庫、1000+ 張表(根據帖子 ID 分庫分表)。這自己並無問題,代碼寫好了,數據該寫哪裏寫哪裏,該讀哪裏讀哪裏。可是隨着應用的發展、需求的變化,咱們發如今實現某些需求時,分庫分表的結構難以知足。咱們須要數據邏輯上在一張表裏。
  2. 近些年來,隨着業務加速成長,數據量日新月異,而硬盤容量是有限的,每臺服務器上能擴展的硬盤數量也是有限的,導致每隔一段時間都要增長更大容量的存儲服務器來應對。並且這個事情一開始是很複雜的,涉及到不少關聯項目,即使到如今咱們輕車熟路了,每次換服務器的時候依然須要關注它,而且大容量數據庫服務器價格昂貴。咱們須要讓擴容對應用來講,無感知。

3、分佈式數據庫調研

3.1 肯定方向

在 2018 年末的時候,公司專門成立了虛擬架構組來調研新的數據庫來解決汽車之家社區遇到的問題。通過各類分析和測試,今年年初肯定方向爲分佈式數據庫,一共調研了三款當前比較火的分佈式數據庫:TiDB(PingCAP),Ignite(ASF-TLP) 和 CockroachDB。通過無數次測試咱們最終選擇了 TiDB,主要有如下幾個緣由:服務器

  1. 兼容 MySQL 協議與生態,上手門檻低;
  2. 跟 TiDB 官方一直保持比較好的技術溝通;
  3. TiDB 公司在北京,有問題能夠當面解決;
  4. TiDB 的設計架構更加優秀;
  5. 官方社區比較活躍,文檔豐富;
  6. 官方的技術人員常常到公司進行交流。

<center>TiDB 的研發同窗到之家進行技術交流</center>架構

<center>咱們去 TiDB 進行系統的課程培訓</center>併發

下面引用 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、遷移方案

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。

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

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

5、全量同步

首先咱們要感謝如下兩個開源項目,站在巨人的肩膀上使咱們節約了不少時間。

愚公是阿里巴巴推出的一款 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。

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

6、增量同步與實時校驗

在實現這部分需求的時候,咱們應用了 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 和消費者提升性能和可用性。

7、回滾方案

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

TiDB Binlog 使得這件事情垂手可得。咱們使用官方提供的 Pump 和 Drainer 將 Binlog 抽取到 Kafka 之中,解析數據變動的內容,根據業務 ID 計算出數據在 SQL Server 中本來屬於哪一個庫哪一個表,而後進行數據同步。

<center>解析 Binlog (Protobuf 協議)</center>

<center>經過業務 ID 決定數據寫到哪一個庫表</center>

8、汽車之家社區業務 TiDB 遷移改造

就業務的改造這一環節,因歷史積澱,需修改的地方不少,分佈於各個項目之中,咱們採起經過接口查找實現、搜索代碼、DBA 幫助抓取 SQL 的方式,保證涵蓋了 100% 的相關業務,只有這樣才能保障上線後無端障。

  • 數據訪問層增長對 MySQL 語法的支持。
  • 去掉 SQL Server 中的存儲過程。
  • SQL Server 和 TiDB(MySQL)的語句和函數支持不盡相同,逐個改造、測試並優化。
  • 根據 TiDB 索引的原理以及梳理出來的 SQL 語句,從新建索引。

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

9、TiDB 周邊體系建設

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

  • 咱們創建了完善的 TiDB 開發規範、運維規範、上線規範,並在公司內部對開發同窗進行相關的培訓。
  • 開發了實時慢 SQL 分析工具——TiSlowSQL,該工具能夠提供實時、多維度、全視角的 SQL 報告,幫助咱們快速定位慢 SQL 致使的集羣級故障。
  • 爲解決監控單點問題,咱們本身開發了一套監控工具,對 TiDB 核心組件進行監控,後續會將監控系通通一遷移到之家雲平臺。
  • 按期在汽車之家大學舉行技術培訓,按期在組內進行技術分享,經驗總結。
TiSlowSQL 也是汽車之家運維組參加 Hackathon 項目,具體內容敬請期待後續文章!

10、總結與展望

汽車之家社區已於 9 月底正式上線分佈式數據庫 TiDB,目前運行穩定。在其餘業務遷移完成以後,汽車之家社區的 SQL Server 服務會逐步下線。對於本次遷移的過程咱們作了如下幾點總結:

  • 經過不斷的優化 SQL,目前線上 TP99 穩定,與遷移以前並沒有太大差異,跟測試效果相符。對用戶和業務都無感知。
  • 隨着業務的不斷擴大,能夠更好的應對數據的暴增,再擴容集羣就不須要找昂貴的大存儲機器,並且能夠在線不停業務隨時擴容。
  • 本次遷移咱們積累了 SQL Server 轉 TiDB 的不少經驗,能夠爲其餘團隊使用分佈式數據庫 TiDB 提供技術支持,讓其餘團隊在遷移過程當中節省時間。
  • 目前正在與 TiDB 官方溝通,準備把遷移方案和與業務無關的遷移邏輯放到開源社區。

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

汽車之家有不少海量數據的應用場景,這一次從 SQL Server 到分佈式數據庫 TiDB 的遷移,爲咱們之後其餘業務遷移至 TiDB 打下了良好的基礎,也與 TiDB 官方創建了良好的按期溝通機制。但願 TiDB 官方一如既往的快速迭代,咱們也會和 TiDB 官方合做開發一些比較實用的功能。

關於 TiDB 使用上的疑惑或經驗,能夠登錄 http://www.asktug.com 和你們一塊兒交流~

相關文章
相關標籤/搜索