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

SQL Server + .Net 是很多早期互聯網企業的標配技術棧,但是隨着業務的不斷擴大,這種技術棧會遇到很多挑戰,我們可能需要換個數據庫。本文從業務背景、遷移方案、同步、業務改造、上線效果、周邊建設等多個角度,詳細介紹瞭如何從 SQL Server 數據庫遷移至 TiDB 數據庫。

項目背景

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

使用 SQL Server 遇到的瓶頸

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

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

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

分佈式數據庫調研

確定方向

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

  • 兼容 MySQL 協議與生態,上手門檻低;

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

  • 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 應用,我們也已經在實踐的路上。

實踐出真知

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

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 異常宕機情況下的表現,對業務影響很小,可實現自動故障恢復。

遷移方案

遷移前需要解決的問題

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

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

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

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

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

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

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

整體遷移架構圖

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

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

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

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

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

整個遷移流程中,應用的讀數據場景不受影響,寫入場景受影響週期爲停機(關寫權限)到寫流量指向 TiDB。

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

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

全量同步

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

https://github.com/alibaba/yugong 1

https://github.com/alswl/yugong

愚公是阿里巴巴推出的一款 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 核心組件進行監控,後續會將監控系統統一遷移到之家雲平臺。

總結與展望

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

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

隨着業務的不斷擴大,可以更好的應對數據的暴增,再擴容集羣就不需要找昂貴的大存儲機器,而且可以在線不停業務隨時擴容。

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

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

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

汽車之家有很多海量數據的應用場景,這一次從 SQL Server 到分佈式數據庫 TiDB 的遷移,爲我們以後其他業務遷移至 TiDB 打下了良好的基礎,也與 TiDB 官方建立了良好的定期溝通機制。

作者介紹:

汽車之家技術架構組,由各技術團隊核心成員組成,成立跨部門的橫向溝通機制(開發、測試、運維等),主要負責分佈式數據庫、服務網格等前沿技術的研究、測試、落地實施等工作,其目的是用於解決團隊在實際生產過程中遇到的技術問題,推進現有系統架構升級,建立學習型社羣,最佳實踐傳播分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章