美團點評攜手 PingCAP 開啓新一代數據庫深度實踐之旅 原

一、背景和現狀

在美團,基於 MySQL 構建的傳統關係型數據庫服務已經難於支撐公司業務的爆發式增長,促使我們去探索更合理的數據存儲方案和實踐新的運維方式。隨着近一兩年來分佈式數據庫大放異彩,美團 DBA 團隊聯合架構存儲團隊,於 2018 年初啓動了分佈式數據庫項目。

圖 1 美團點評產品展示圖

圖 1 美團點評產品展示圖

立項之初,我們進行了大量解決方案的對比,深入瞭解了業界多種 scale-out、scale-up 方案,考慮到技術架構的前瞻性、發展潛力、社區活躍度、以及服務本身與 MySQL 的兼容性,最終敲定了基於 TiDB 數據庫進行二次開發的整體方案,並與 PingCAP 官方和開源社區進行深入合作的開發模式。

美團業務線衆多,我們根據業務特點及重要程度逐步推進上線,到截稿爲止,已經上線 10 個集羣,近 200 個物理節點,大部分是 OLTP 類型的應用,除了上線初期遇到了一些小問題,目前均已穩定運行。初期上線的集羣,已經分別服務於配送、出行、閃付、酒旅等業務。

TiDB 架構分層清晰,服務平穩流暢,但在美團當前的數據量規模和已有穩定的存儲體系的基礎上,推廣新的存儲服務體系,需要對周邊工具和系統進行一系列改造和適配,從初期探索到整合落地需要走很遠的路。下面從幾個方面分別介紹:

  • 一是從 0 到 1 的突破,重點考慮做哪些事情;
  • 二是如何規劃實施不同業務場景的接入和已有業務的遷移;
  • 三是上線後遇到的一些典型問題介紹;
  • 四是後續規劃和對未來的展望。

二、前期調研測試

2.1 對 TiDB 的定位

我們對於 TiDB 的定位,前期在於重點解決 MySQL 的單機性能和容量無法線性和靈活擴展的問題,與 MySQL 形成互補。業界分佈式方案很多,我們爲何選擇了 TiDB 呢?考慮到公司業務規模的快速增長,以及公司內關係數據庫以 MySQL 爲主的現狀,因此我們在調研階段,對以下技術特性進行了重點考慮:

  • 協議兼容 MySQL:這個是必要項。
  • 可在線擴展:數據通常要有分片,分片要支持分裂和自動遷移,並且遷移過程要儘量對業務無感知。
  • 強一致的分佈式事務:事務可以跨分片、跨節點執行,並且強一致。
  • 支持二級索引:爲兼容 MySQL 的業務,這個是必須的。
  • 性能:MySQL 的業務特性,高併發的 OLTP 性能必須滿足。
  • 跨機房服務:需要保證任何一個機房宕機,服務能自動切換。
  • 跨機房雙寫:支持跨機房雙寫是數據庫領域一大難題,是我們對分佈式數據庫的一個重要期待,也是美團下一階段重要的需求。

業界的一些傳統方案雖然支持分片,但無法自動分裂、遷移,不支持分佈式事務,還有一些在傳統 MySQL 上開發一致性協議的方案,但它無法實現線性擴展,最終我們選擇了與我們的需求最爲接近的 TiDB。與 MySQL 語法和特性高度兼容,具有靈活的在線擴容縮容特性,支持 ACID 的強一致性事務,可以跨機房部署實現跨機房容災,支持多節點寫入,對業務又能像單機 MySQL 一樣使用。

2.2 測試

針對官方聲稱的以上優點,我們進行了大量的研究、測試和驗證。

首先,我們需要知道擴容、Region 分裂轉移的細節、Schema 到 kv 的映射、分佈式事務的實現原理。而 TiDB 的方案,參考了較多的 Google 論文,我們進行了閱讀,這有助於我們理解 TiDB 的存儲結構、事務算法、安全性等,包括:

  • Spanner: Google’s Globally-Distributed Database
  • Large-scale Incremental Processing Using Distributed Transactions and Notifications
  • In Search of an Understandable Consensus Algorithm
  • Online, Asynchronous Schema Change in F1

我們也進行了常規的性能和功能測試,用來與 MySQL 的指標進行對比,其中一個比較特別的測試,是證明 3 副本跨機房部署,確實能保證每個機房分佈一個副本,從而保證任何一個機房宕機不會導致丟失超過半數副本。從以下幾個點進行測試:

  • Raft 擴容時是否支持 learner 節點,從而保證單機房宕機不會丟失 2/3 的副本。
  • TiKV 上的標籤優先級是否可靠,保證當機房的機器不平均時,能否保證每個機房的副本數依然是絕對平均的。
  • 實際測試,單機房宕機,TiDB 在高併發下,QPS、響應時間、報錯數量,以及最終數據是否有丟失。
  • 手動 Balance 一個 Region 到其他機房,是否會自動回來。

從測試結果來看,一切都符合預期。

三、存儲生態建設

美團的產品線豐富,業務體量大,業務對在線存儲的服務質量要求也非常高。因此,從早期做好服務體系的規劃非常重要。下面從業務接入層、監控報警、服務部署,來分別介紹一下我們所做的工作。

3.1 業務接入層

當前 MySQL 的業務接入方式主要有兩種,DNS 接入和 Zebra 客戶端接入。在前期調研階段,我們選擇了 DNS + 負載均衡組件的接入方式,TiDB-Server 節點宕機,15s 可以被負載均衡識別到,簡單有效。業務架構如圖 2。

圖 2 業務架構圖

圖 2 業務架構圖

後面我們會逐漸過渡到當前大量使用的 Zebra 接入方式來訪問 TiDB,從而保持與訪問 MySQL 的方式一致,一方面減少業務改造的成本,另一方面儘量實現從 MySQL 到 TiDB 的透明遷移。

3.2 監控報警

美團目前使用 Mt-Falcon 平臺負責監控報警,通過在 Mt-Falcon 上配置不同的插件,可以實現對多種組件的自定義監控。另外也會結合 Puppet 識別不同用戶的權限、文件的下發。這樣,只要我們編寫好插件腳本、需要的文件,裝機和權限控制就可以完成了。監控架構如圖 3。

圖 3 監控架構圖

圖 3 監控架構圖

而 TiDB 有豐富的監控指標,使用流行的 Prometheus + Grafana,一套集羣有 700+ 的 Metric。從官方的架構圖可以看出,每個組件會推送自己的 Metric 給 PushGateWay,Prometheus 會直接到 PushGateWay 去抓數據。

由於我們需要組件收斂,原生的 TiDB 每個集羣一套 Prometheus 的方式不利於監控的彙總、分析、配置,而報警已經在 Mt-Falcon 上實現的比較好了,在 AlertManager 上再造一個也沒有必要。因此我們需要想辦法把監控和報警彙總到 Mt-Falcon 上面,有如下幾種方式:

  • 方案一:修改源代碼,將 Metric 直接推送到 Falcon,由於 Metric 散落在代碼的不同位置,而且 TiDB 代碼迭代太快,把精力消耗在不停調整監控埋點上不太合適。
  • 方案二:在 PushGateWay 是彙總後的,可以直接抓取,但 PushGateWay 是個單點,不好維護。
  • 方案三:通過各個組件(TiDB、PD、TiKV)的本地 API 直接抓取,優點是組件宕機不會影響其他組件,實現也比較簡單。

我們最終選擇了方案三。該方案的難點是需要把 Prometheus 的數據格式轉化爲 Mt-Falcon 可識別的格式,因爲 Prometheus 支持 Counter、Gauge、Histogram、Summary 四種數據類型,而 Mt-Falcon 只支持基本的 Counter 和 Gauge,同時 Mt-Falcon 的計算表達式比較少,因此需要在監控腳本中進行轉換和計算。

3.3 批量部署

TiDB 使用 Ansible 實現自動化部署。迭代快,是 TiDB 的一個特點,有問題快速解決,但也造成 Ansible 工程、TiDB 版本更新過快,我們對 Ansible 的改動,也只會增加新的代碼,不會改動已有的代碼。因此線上可能同時需要部署、維護多個版本的集羣。如果每個集羣一個 Ansible 目錄,造成空間的浪費。我們採用的維護方式是,在中控機中,每個版本一個 Ansible 目錄,每個版本中通過不同 inventory 文件來維護。這裏需要跟 PingCAP 提出的是,Ansible 只考慮了單集羣部署,大量部署會有些麻煩,像一些依賴的配置文件,都不能根據集羣單獨配置(諮詢官方得知,PingCAP 目前正在基於 Cloud TiDB 打造一站式 HTAP 平臺,會提供批量部署、多租戶等功能,能比較好的解決這個問題)。

3.4 自動化運維平臺

隨着線上集羣數量的增加,打造運維平臺提上了日程,而美團對 TiDB 和 MySQL 的使用方式基本相同,因此 MySQL 平臺上具有的大部分組件,TiDB 平臺也需要建設。典型的底層組件和方案:SQL 審覈模塊、DTS、數據備份方案等。自動化運維平臺展示如圖 4。

圖 4 自動化運維平臺展示圖

3.5 上下游異構數據同步

TiDB 是在線存儲體系中的一環,它同時也需要融入到公司現有的數據流中,因此需要一些工具來做銜接。PingCAP 官方標配了相關的組件。

公司目前 MySQL 和 Hive 結合的比較重,而 TiDB 要代替 MySQL 的部分功能,需要解決 2 個問題:

  • MySQL to TiDB

    • MySQL 到 TiDB 的遷移,需要解決數據遷移以及增量的實時同步,也就是 DTS,Mydumper + Loader 解決存量數據的同步,官方提供了 DM 工具可以很好的解決增量同步問題。
    • MySQL 大量使用了自增 ID 作爲主鍵。分庫分表 MySQL 合併到 TiDB 時,需要解決自增 ID 衝突的問題。這個通過在 TiDB 端去掉自增 ID 建立自己的唯一主鍵來解決。新版 DM 也提供分表合併過程主鍵自動處理的功能。
  • Hive to TiDB & TiDB to Hive

    • Hive to TiDB 比較好解決,這體現了 TiDB 和 MySQL 高度兼容的好處,insert 語句可以不用調整,基於 Hive to MySQL 簡單改造即可。
    • TiDB to Hive 則需要基於官方 Pump + Drainer 組件,Drainer 可以消費到 Kafka、MySQL、TiDB,我們初步考慮用下圖 5 中的方案通過使用 Drainer 的 Kafka 輸出模式同步到 Hive。

圖 5 TiDB to Hive 方案圖

圖 5 TiDB to Hive 方案圖

四、線上使用磨合

對於初期上線的業務,我們比較謹慎,基本的原則是:離線業務 -> 非核心業務 -> 核心業務。TiDB 已經發布兩年多,且前期經歷了大量的測試,我們也深入瞭解了其它公司的測試和使用情況,可以預期的是 TiDB 上線會比較穩定,但依然遇到了一些小問題。總體來看,在安全性、數據一致性等關鍵點上沒有出現問題。其他一些性能抖動問題,參數調優的問題,也都得到了快速妥善的解決。這裏給 PingCAP 的同學點個大大的贊,問題響應速度非常快,與我們內部研發的合作也非常融洽。

4.1 寫入量大、讀 QPS 高的離線業務

我們上線的最大的一個業務,每天有數百 G 的寫入量,前期遇到了較多的問題,我們重點說說。

業務場景:

  • 穩定的寫入,每個事務操作 100~200 行不等,每秒 6w 的數據寫入。
  • 每天的寫入量超過 500G,以後會逐步提量到每天 3T。
  • 每 15 分鐘的定時讀 job,5000 QPS(高頻量小)。
  • 不定時的查詢(低頻量大)。

之前使用 MySQL 作爲存儲,但 MySQL 到達了容量和性能瓶頸,而業務的容量未來會 10 倍的增長。初期調研測試了 ClickHouse,滿足了容量的需求,測試發現運行低頻 SQL 沒有問題,但高頻 SQL 的大併發查詢無法滿足需求,只在 ClickHouse 跑全量的低頻 SQL 又會 overkill,最終選擇使用 TiDB。

測試期間模擬寫入了一天的真實數據,非常穩定,高頻低頻兩種查詢也都滿足需求,定向優化後 OLAP 的 SQL 比 MySQL 性能提高四倍。但上線後,陸續發現了一些問題,典型的如下:

4.1.1 TiKV 發生 Write Stall

TiKV 底層有 2 個 RocksDB 作爲存儲。新寫的數據寫入 L0 層,當 RocksDB 的 L0 層數量達到一定數量,就會發生減速,更高則發生 Stall,用來自我保護。TiKV 的默認配置:

  • level0-slowdown-writes-trigger = 20
  • level0-stop-writes-trigger = 36

遇到過的,發生 L0 文件過多可能的原因有 2 個:

  • 寫入量大,Compact 完不成。
  • Snapshot 一直創建不完,導致堆積的副本一下釋放,rocksdb-raft 創建大量的 L0 文件,監控展示如圖 6。

圖 6 TiKV 發生 Write Stall 監控展示圖

圖 6 TiKV 發生 Write Stall 監控展示圖

我們通過以下措施,解決了 Write Stall 的問題:

  • 減緩 Raft Log Compact 頻率(增大 raft-log-gc-size-limit、raft-log-gc-count-limit)
  • 加快 Snapshot 速度(整體性能、包括硬件性能)
  • max-sub-compactions 調整爲 3
  • max-background-jobs 調整爲 12
  • level 0 的 3 個 Trigger 調整爲 16、32、64

4.1.2 Delete 大量數據,GC 跟不上

現在 TiDB 的 GC 對於每個 kv-instance 是單線程的,當業務刪除數據的量非常大時,會導致 GC 速度較慢,很可能 GC 的速度跟不上寫入。

目前可以通過增多 TiKV 個數來解決,長期需要靠 GC 改爲多線程執行,官方對此已經實現,即將發佈。

4.1.3 Insert 響應時間越來越慢

業務上線初期,insert 的響應時間 80 線(Duration 80 By Instance)在 20ms 左右,隨着運行時間增加,發現響應時間逐步增加到 200ms+。期間排查了多種可能原因,定位在由於 Region 數量快速上漲,Raftstore 裏面要做的事情變多了,而它又是單線程工作,每個 Region 定期都要 heartbeat,帶來了性能消耗。tikv-raft propose wait duration 指標持續增長。

解決問題的辦法:

  • 臨時解決
    • 增加 Heartbeat 的週期,從 1s 改爲 2s,效果比較明顯,監控展示如圖 7。

圖 7 insert 響應時間優化前後對比圖

圖 7 insert 響應時間優化前後對比圖

  • 徹底解決
    • 需要減少 Region 個數,Merge 掉空 Region,官方在 2.1 版本中已經實現了 Region Merge 功能,我們在升級到 2.1 後,得到了徹底解決。
    • 另外,等待 Raftstore 改爲多線程,能進一步優化。(官方回複相關開發已基本接近尾聲,將於 2.1 的下一個版本發佈。)

4.1.4 Truncate Table 空間無法完全回收

DBA Truncate 一張大表後,發現 2 個現象,一是空間回收較慢,二是最終也沒有完全回收。

  • 由於底層 RocksDB 的機制,很多數據落在 level 6 上,有可能清不掉。這個需要打開 cdynamic-level-bytes 會優化 Compaction 的策略,提高 Compact 回收空間的速度。
  • 由於 Truncate 使用 delete_files_in_range 接口,發給 TiKV 去刪 SST 文件,這裏只刪除不相交的部分,而之前判斷是否相交的粒度是 Region,因此導致了大量 SST 無法及時刪除掉。
    • 考慮 Region 獨立 SST 可以解決交叉問題,但是隨之帶來的是磁盤佔用問題和 Split 延時問題。
    • 考慮使用 RocksDB 的 DeleteRange 接口,但需要等該接口穩定。
    • 目前最新的 2.1 版本優化爲直接使用 DeleteFilesInRange 接口刪除整個表佔用的空間,然後清理少量殘留數據,已經解決。

4.1.5 開啓 Region Merge 功能

爲了解決 region 過多的問題,我們在升級 2.1 版本後,開啓了 region merge 功能,但是 TiDB 的響應時間 80 線(Duration 80 By Instance)依然沒有恢復到當初,保持在 50ms 左右,排查發現 KV 層返回的響應時間還很快,和最初接近,那麼就定位了問題出現在 TiDB 層。研發人員和 PingCAP 定位在產生執行計劃時行爲和 2.0 版本不一致了,目前已經優化。

4.2 在線 OLTP,對響應時間敏感的業務

除了分析查詢量大的離線業務場景,美團還有很多分庫分表的場景,雖然業界有很多分庫分表的方案,解決了單機性能、存儲瓶頸,但是對於業務還是有些不友好的地方:

  • 業務無法友好的執行分佈式事務。
  • 跨庫的查詢,需要在中間層上組合,是比較重的方案。
  • 單庫如果容量不足,需要再次拆分,無論怎樣做,都很痛苦。
  • 業務需要關注數據分佈的規則,即使用了中間層,業務心裏還是沒底。

因此很多分庫分表的業務,以及即將無法在單機承載而正在設計分庫分表方案的業務,主動找到了我們,這和我們對於 TiDB 的定位是相符的。這些業務的特點是 SQL 語句小而頻繁,對一致性要求高,通常部分數據有時間屬性。在測試及上線後也遇到了一些問題,不過目前基本都有了解決辦法。

4.2.1 SQL 執行超時後,JDBC 報錯

業務偶爾報出 privilege check fail。

是由於業務在 JDBC 設置了 QueryTimeout,SQL 運行超過這個時間,會發行一個 “kill query” 命令,而 TiDB 執行這個命令需要 Super 權限,業務是沒有權限的。

其實 kill 自己的查詢,並不需要額外的權限,目前已經解決了這個問題,不再需要 Super 權限,已在 2.0.5 上線。

4.2.2 執行計劃偶爾不準

TiDB 的物理優化階段需要依靠統計信息。在 2.0 版本統計信息的收集從手動執行,優化爲在達到一定條件時可以自動觸發:

  • 數據修改比例達到 tidb_auto_analyze_ratio
  • 表一分鐘沒有變更(目前版本已經去掉這個條件)

但是在沒有達到這些條件之前統計信息是不準的,這樣就會導致物理優化出現偏差,在測試階段(2.0 版本)就出現了這樣一個案例:業務數據是有時間屬性的,業務的查詢有 2 個條件,比如:時間+商家 ID,但每天上午統計信息可能不準,當天的數據已經有了,但統計信息認爲沒有。這時優化器就會建議使用時間列的索引,但實際上商家 ID 列的索引更優化。這個問題可以通過增加 Hint 解決。

在 2.1 版本對統計信息和執行計劃的計算做了大量的優化,也穩定了基於 Query Feedback 更新統計信息,也用於更新直方圖和 Count-Min Sketch,非常期待 2.1 的 GA。

五、總結展望

經過前期的測試、各方的溝通協調,以及近半年對 TiDB 的使用,我們看好 TiDB 的發展,也對未來基於 TiDB 的合作充滿信心。

接下來,我們會加速推進 TiDB 在更多業務系統中的使用,同時也將 TiDB 納入了美團新一代數據庫的戰略選型中。當前,我們已經全職投入了 3 位 DBA 同學和多位存儲計算專家,從底層的存儲,中間層的計算,業務層的接入,到存儲方案的選型和佈道,進行全方位和更深入的合作。

長期來看,結合美團不斷增長的業務規模,我們將與 PingCAP 官方合作打造更強大的生態體系:

  • Titan:Titan 是 TiDB 下一步比較大的動作,也是我們非常期待的下一代存儲引擎,它對大 Value 支持會更友好,將解決我們單行大小受限,單機 TiKV 最大支持存儲容量的問題,大大提升大規模部署的性價比。

  • Cloud TiDB(based on Docker & K8s):雲計算大勢所趨,PingCAP 在這塊也佈局比較早,今年 8 月份開源了 TiDB Operator,Cloud TiDB 不僅實現了數據庫的高度自動化運維,而且基於 Docker 硬件隔離,實現了數據庫比較完美的多租戶架構。和官方同學溝通,目前他們的私有云方案在國內也有重要體量的 POC,這也是美團看重的一個方向。

  • TiDB HTAP Platform:PingCAP 在原有 TiDB Server 計算引擎的基礎上,還構建 TiSpark 計算引擎,和他們官方溝通,他們在研發了一個基於列的存儲引擎,這樣就形成了下層行、列兩個存儲引擎、上層兩個計算引擎的完整混合數據庫(HTAP),這個架構不僅大大的節省了核心業務數據在整個公司業務週期裏的副本數量,還通過收斂技術棧,節省了大量的人力成本、技術成本、機器成本,同時還解決了困擾多年的 OLAP 的實效性。後面我們也會考慮將一些有實時、準實時的分析查詢系統接入 TiDB。

圖 8 TiDB HTAP Platform 整體架構圖

圖 8 TiDB HTAP Platform 整體架構圖

後續的物理備份方案,跨機房多寫等也是我們接下來逐步推進的場景,總之我們堅信未來 TiDB 在美團的使用場景會越來越多,發展也會越來越好。

TiDB 在業務層面、技術合作層面都已經在美團揚帆起航,美團點評將攜手 PingCAP 開啓新一代數據庫深度實踐、探索之旅。後續,還有美團點評架構存儲團隊針對 TiDB 源碼研究和改進的系列文章,敬請期待!

作者介紹

趙應鋼,美團點評研究員

李坤,美團點評數據庫專家

樸昌俊,美團點評數據庫專家

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