網易互娛的數據庫選型和 TiDB 應用實踐

業務架構簡介

計費組是爲網易互娛產品提供統一登錄和支付高效解決方案的公共支持部門,對內是互娛的各個遊戲工作室,對外是國內外數百個渠道。由於業務場景的特殊性,我們爲各個遊戲產品部署了不同的應用服務,其中大產品環境獨立,小產品集中部署。

隨着部門業務量的激增,單機 MySQL 在容量、性能、擴展性等方面都遇到了瓶頸,我們開始對其他數據庫產品進行調研選型。本文將詳細介紹網易互娛計費組針對自己場景的數據庫選型對比方案,以及使用 TiDB 後解決的問題,並分享使用 TiDB 過程中集羣管理、監控和數據遷移等方面的最佳實踐,以供大家參考和交流。

MySQL 使用架構

網易互娛計費組線上 MySQL 的基本使用架構,如下圖所示,其中箭頭方向表示數據或請求的指向:

  • 線上應用 Application 通過 Keepalive + 多機部署,流量經過負載均衡,可以有效保障應用服務的高可用;
  • 數據庫層架構是 Keepalive + 主從結構,利用半同步複製特性可以有效解決延遲和數據一致性的問題;
  • Application 通過 VIP 訪問後端數據庫,在數據庫主節點宕機後通過 VIP 飄移到從節點,保證服務正常對外提供;
  • 通過 Slave 節點進行數據備份和線上數據採集,經過全量和增量同步方式導出數據到數據中心,然後進行在線和離線計算任務;
  • 類似這樣的架構組合線上大概有 50+ 套,涉及服務器 200~400 臺,日均新增數據 TB 級。

MySQL 使用的現狀與問題

隨着業務的發展,部門內各應用服務產生的數據量也在快速增長。業務落地數據量不斷激增,導致單機 MySQL 不可避免地會出現性能瓶頸。主要體現在以下幾個方面:

  • 容量

    單機 MySQL 實例存儲空間有限,想要維持現有架構就得刪除和輪轉舊數據,達到釋放空間的目的;
    網易互娛某些場景單表容量達到 700GB 以上,訂單數據需永久保存,同時也需要保持在線實時查詢,按照之前的存儲設計會出現明顯的瓶頸。

  • 性能

    最大單表 15 億行,行數過大,導致讀寫性能受到影響。

  • 擴展性

    MySQL 無法在線靈活擴展,無法解決存儲瓶頸。

  • SQL 複雜

    大表輪轉後出現多個分表,聯合查詢時需要 join 多個分表,SQL 非常複雜並難以維護;
    單機 MySQL 缺乏大規模數據分析的能力。

  • 數據壁壘

    不同產品的數據庫獨立部署;
    數據不互通,導致數據相關隔離,形成數據壁壘;
    當進行跨產品計算時,需要維護多個異構數據源,訪問方式複雜。數據分散在不同的數據孤島上會增加數據分析難度,不利於共性價值的挖掘。如下圖:

數據庫選型

調研目標

針對目前存儲架構存在的問題,有需要使用其他存儲方案的可能。考慮到目前的業務與 MySQL 高度耦合,對數據庫選型的主要要求有:

  • 必須兼容 MySQL 協議;
  • 支持事務,保證任務以事務爲維度來執行或遇錯回滾;
  • 支持索引,尤其是二級索引;
  • 擴展性,支持靈活在線擴展能力,包括性能擴展和容量擴展。

其他要求:

  • 穩定性和可靠性;
  • 備份和恢復;
  • 容災等。

可選方案

測試

基於 MySQL 的解決方案

一開始仍然是傾向使用基於 MySQL 的解決方案,比如 MySQL InnoDB Cluster 或 MySQL + 中間件的方案。

我們測試了 MySQL 集羣 5.7.25 版本對比 8.0.12 版本,在 128 併發寫各 1000 萬行的 10 個表,比較單節點、3 節點和 5 節點下的情況,如下圖所示:

在測試中發現,使用 MySQL InnoDB 集羣的方案寫性能比單機 MySQL 差約 30%,其他的讀寫測試結果也不甚滿意。之後陸續測試 MySQL InnoDB Cluster 或 MySQL + 中間件的方案,不是測試結果性能不達要求,就是需要修改大量代碼。

因此我們得出了基於 MySQL InnoDB Cluster 或 MySQL + 中間件的方案的不滿足我們的業務場景的結論。總結來說,我們不使用 MySQL 分庫分表、中間件或 MySQL 集羣,原因主要是以下兩點:

  • 方案過於複雜
  • 需要改業務代碼

仔細分析來看,其實基於 MySQL InnoDB Cluster 或 MySQL + 中間件的方案,本質上是 MySQL 主從結構的延伸,並非真正的分佈式拓展,像是以打“補丁”的方式來實現橫向擴展,很多功能特性自然也難以讓人滿意

CockroachDB VS TiDB

在開源的分佈式 NewSQL 領域,知名的有 TiDB 和 CockroachDB(簡稱 CRDB),二者都是基於 Google Spanner 論文的開源實現。我們對這兩種數據庫的功能和性能做了大量的調研和測試。

  • TiDB 天然兼容 MySQL 協議,而 CRDB 兼容 PostgreSQL ;
  • 如果業務以 MySQL 爲主,那 TiDB 可能是比較好的選擇;如果是 PostgreSQL,那CRDB 可能是優先的選擇。

測試方面,我們也進行了全面地對比和測試。這裏說其中一個測試案例:10 臺機器 5 存儲節點,160 併發訪問單表 2 億行,我們於 2018 年 7 月,對 CRDB-v2.1.0 版本和 TiDB-v2.0.5 版本進行了讀寫測試(CRDB 和 TiDB 集羣均使用默認配置,未進行調優)。

集羣拓撲

測試語句

  • 範圍查詢:
 SELECT c FROM sbtest%u WHERE id BETWEEN ? AND ? SELECT SUM(k) FROM sbtest%u WHERE id BETWEEN ? AND ? SELECT c FROM sbtest WHERE id BETWEEN ? AND ? ORDER BY c SELECT DISTINCT c FROM sbtest%u WHERE id BETWEEN ? AND ? ORDER BY c
  • 隨機 IN 查詢:
 SELECT id, k, c, pad FROM sbtest1 WHERE k IN (?)
  • 隨機範圍查詢:
 SELECT count(k) FROM sbtest1 WHERE k BETWEEN ? AND ? OR k BETWEEN ? AND ?
  • 更新索引列:
 UPDATE sbtest%u SET k=k+1 WHERE id=?
  • 更新非索引列:
 UPDATE sbtest%u SET c=? WHERE id=?
  • 讀寫混合:範圍查詢 + 更刪改混合

其中一個重要的測試結果如下:

結論

  1. CRDB 和 TiDB 在性能表現上不相上下;

注:上面是 2018 年 7 月的基於 TiDB 2.0.5 版本的測試結果,現在 TiDB 已發佈 3.0 GA 版本,在性能上有了質的提升。我們在近期進行了補充測試,大多數場景下 3.0 版本較 2.1 版本有數倍的性能提升,最新的測試結果圖如下:

  1. CRDB 兼容 PostgreSQL,如果需要遷移則需要轉協議,需 MySQL → PostgreSQL → CRDB。遷移過程複雜,成本高;
  2. TiDB 兼容 MySQL,代碼修改量不多,遷移成本低。

最終選型

綜合對比結果如下表:

經過謹慎的考量,我們選擇了 TiDB。

TiDB 在網易互娛計費組的使用

TiDB 使用架構

網易互娛使用 TiDB 的架構設計如下:

  • 整個集羣分爲 TiDB、TiKV 和 PD 3 個模塊分層部署;
  • 使用 Nginx 作爲前端負載均衡。

TiDB 解決了哪些需求

TiDB 使用現狀

  • 業務

    TiDB 作爲線上 MySQL 數據鏡像,負責線上數據的收集和集中管理,形成數據湖泊;
    應用於數據平臺服務,包括報表、監控、運營、用戶畫像、大數據計算等場景;
    HTAP:OLTP + OLAP。

  • 集羣

    測試集羣:v2.1.15,用於功能測試、特性嚐鮮;
    線上集羣:v2.1.15,80% 離線大數據計算任務 + 20% 線上業務。

  • 規模

    41 臺服務器,88 個實例節點,38 個 Syncer 實時同步流(將升級爲 DM);
    存儲:20TB/總 50TB,230 萬個 Region;
    QPS 均值 4k/s,高峯期萬級 QPS,讀寫比約 1:5;
    延遲時間:80% 在 8ms 以內,95% 在 125ms 以下,99.9% 在 500ms 以下。

最佳實踐分享

集羣管理

  • Ansible(推薦)
    • 一鍵部署彈性伸縮,可在線靈活擴縮容;
    • 升級,單節點輪轉平滑升級;
    • 集羣啓停和下線;
    • Prometheus 監控。
  • Docker
  • K8s
    • 使用 TiDB Operator 可以在私有云和公有云上一鍵管理。

運維實踐

Prometheus 監控

官方集成了 Prometheus + Grafana 的實時監控平臺,從集羣的各個方面進行了完善的監控,包括:

  • 服務器基礎資源的監控:內存、CPU、存儲空間、IO 等;
  • 集羣組件的監控:TiDB、PD、TiKV 等;
  • 數據監控:實時同步流、上下游數據一致性檢驗等。

PD 監控示意圖如下,集羣管理員可以很方便地掌握集羣的最新狀態,包括集羣的空間 Region 等所有情況。

如果集羣運行過程出錯,在監控面板上很容易就發現,下圖是使用過程中的一個案例:

應用訪問 TiDB 寫入數據時發現特別慢,讀請求正常。排查後,根據 TiKV 面板發現 Raft Store CPU 這項指標異常。深入瞭解原因是因爲數據庫副本複製是單線程操作,目前已經到了集羣的瓶頸。解決辦法有以下兩點:

  • Region 數量過多,Raft Store 還要處理 heartbeat message。

解決方法:刪除過期數據。

  • Raft Store 單線程處理速度跟不上集羣寫入速度。

解決方法:從 2.1.5 升級到 2.1.15,開啓自動 Region Merge 功能。

部分運維問題及解決方案

全網數據庫遍歷

以前部分業務遍歷全網數據庫獲取所需數據,需要維護多個源,而且是異構源,非常複雜和繁瑣。使用 TiDB 很好地解決了這個問題,只需要訪問一個源就可以獲取到所有想要的數據。

數據遷移

MySQL 到 TiDB

MySQL 數據庫遷移到 TiDB 分爲兩個部分:全量和增量。

  • 全量
    • 使用工具 (Mydumper 或 MySQL Dump 等)從 MySQL 導出數據,並且記錄當前數據的 binlog 位置;
    • 使用工具(Loader 或 Lightning 等)將數據導入到 TiDB 集羣;
    • 可以用作數據的備份和恢復操作。
  • 增量
    • TiDB 僞裝成爲上游 MySQL 的一個 Slave,通過工具(Syncer 或 DM)實時同步 binlog 到 TiDB 集羣;
    • 通常情況上游一旦有數據更新,下游就會實時同步過來。同步速度受網絡和數據量大小的影響。

數據遷出 TiDB

如果數據需要反向導入或同步,可以利用 TiDB Binlog 工具將 TiDB 集羣的 binlog 同步到 MySQL。TiDB Binlog 支持以下功能場景:

  • 數據同步:同步 TiDB 集羣數據到其他數據庫;
  • 實時備份和恢復:備份 TiDB 集羣數據,同時可以用於 TiDB 集羣故障時恢復。

導入的方式:

  • 全量:TiDB 兼容 MySQL 協議,在 MySQL 容量足夠大的情況下,也可用工具將數據從 TiDB 導出後再導入 MySQL。
  • 增量:打開 TiDB 的 binlog 開關,部署 binlog 收集組件(Pump+Drainer),可以將 binlog 數據同步到下游存儲架構(MySQL、TiDB、Kafka、S3 等)。

優雅地「去分庫分表」

舉例:一個超級大表按天分表,現在打算查詢某個賬號一年間的信息。

  • 上游 MySQL
 SELECT xx FROM HFeeall join HFee20190101 join ... join ...join ... join HFee20190917 WHERE xx;

需要連接 N 個 join 條件,查詢需要等待較長時間。

  • 下游 TiDB
 SELECT xx  FROM SuperHfeeall WHERE xx ;

應用此方案,最大單表 700+GB,13+ 億行,索引查詢秒返回。

業務遷移

目標:利用 TiDB 的水平擴展特性,解決容量瓶頸和系統吞吐量瓶頸。

遷移原則

  • 數據完整和準確:數據很重要,保證數據不錯、不丟;
  • 遷移平滑和迅速:服務敏感度高,停服時間要短;
  • 可回滾:遇到問題可隨時切回到 MySQL。

1)數據同步

使用 DM 或者 Syncer 將上游 MySQL 的數據同步到 TiDB 集羣。同步流搭建後注意需要檢查上下游數據一致性。

觀察一段時間,同步無誤後,可以根據業務需要遷移部分讀流量到 TiDB 集羣。

2)讀寫驗證

這一階段是驗證應用訪問 MySQL 和訪問 TiDB 可以得到相同的結果,驗證業務訪問的準確性問題。

停止數據同步,使用流量複製工具將線上流量完全拷貝出來,同時讀寫 MySQL 和 TiDB。將兩邊的訪問結果進行對比,覈查 TiDB 是否可靠和可信。根據需要,這個階段可以測試較長時間。

3)灰度切換

將步驟 2 的雙寫停止,即關雙寫,同時拉起上游的 DM 同步。

把訪問部分非核心業務的庫表寫操作遷移到 TiDB,打開 TiDB 的 Binlog 開關對線上 MySQL 進行反向同步。這個操作,保證只寫 MySQL 的數據同步到 TiDB ,只寫 TiDB 的數據也可以反向同步到 MySQL,保證出了問題,隨時可以回滾。當業務長時間訪問正常,可以增加切換流量,進行灰度切換。建議觀察一段時間,至少一個月

4)遷移完成

當流量完全遷移完成,保持 TiDB 反同步到 MySQL 過程,繼續觀察一段時間,確認無誤後,斷開反向同步,100% 遷移完成。

總結與展望

TiDB 兼容 MySQL 協議,支持 TP/AP 事務且擴展性好,能很好地解決網易互娛計費組業務大容量、高可用等問題。目前我們的業務在不斷深入和擴大規模使用 TiDB。因爲看好它,所以這裏提出一些使用中的問題以幫助原廠持續打磨產品:

  • 集羣數據備份:希望提供集羣更高效地備份和恢復 SST 文件的方式;
  • 事務限制:希望可以放寬大事務的限制,現在仍需要人工切分大事務,比較複雜;
  • 同步:希望 DM 支持上下游表結構不一致的同步;
  • 數據熱點問題:建議加強自動檢測和清除熱點功能;
  • 客戶端重試:目前客戶端代碼需要封裝重試邏輯,對用戶不友好,希望可以改進。

最後,根據網易互娛計費組已有的使用情況,我們計劃繼續加大、加深 TiDB 的使用場景,豐富業務類型和使用規模,期待 TiDB 給我們的業務帶來更多便利

作者介紹

李文傑,網易互娛計費組,高級數據庫管理工程師,TiDB User Group (TUG) 大使 。

本文轉載自 AskTUG

原文鏈接

https://asktug.com/t/tidb/1553/1

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