天天看點

TiDB 深度實踐之旅--真實“踩坑”經曆

美團點評 tidb 深度實踐之旅(9000 字長文 / 真實“踩坑”經曆)

這是一個建立于 154 天前的主題,其中的資訊可能已經有所發展或是發生改變。

原标題:美團點評攜手 pingcap 開啟新一代資料庫深度實踐之旅

在美團,基于 mysql 建構的傳統關系型資料庫服務已經難于支撐公司業務的爆發式增長,促使我們去探索更合理的資料存儲方案和實踐新的運維方式。随着近一兩年來分布式資料庫大放異彩,美團 dba 團隊聯合架構存儲團隊,于 2018 年初啟動了分布式資料庫項目。

TiDB 深度實踐之旅--真實“踩坑”經曆

圖 1 美團點評産品展示圖

立項之初,我們進行了大量解決方案的對比,深入了解了業界多種 scale-out、scale-up 方案,考慮到技術架構的前瞻性、發展潛力、社群活躍度、以及服務本身與 mysql 的相容性,最終敲定了基于 tidb 資料庫進行二次開發的整體方案,并與 pingcap 官方和開源社群進行深入合作的開發模式。

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

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

一是從 0 到 1 的突破,重點考慮做哪些事情;

二是如何規劃實施不同業務場景的接入和已有業務的遷移;

三是上線後遇到的一些典型問題介紹;

四是後續規劃和對未來的展望。

我們對于 tidb 的定位,前期在于重點解決 mysql 的單機性能和容量無法線性和靈活擴充的問題,與 mysql 形成互補。業界分布式方案很多,我們為何選擇了 tidb 呢?考慮到公司業務規模的快速增長,以及公司内關系資料庫以 mysql 為主的現狀,是以我們在調研階段,對以下技術特性進行了重點考慮:

協定相容 mysql:這個是必要項。

可線上擴充:資料通常要有分片,分片要支援分裂和自動遷移,并且遷移過程要盡量對業務無感覺。

強一緻的分布式事務:事務可以跨分片、跨節點執行,并且強一緻。

支援二級索引:為相容 mysql 的業務,這個是必須的。

性能:mysql 的業務特性,高并發的 oltp 性能必須滿足。

跨機房服務:需要保證任何一個機房當機,服務能自動切換。

跨機房雙寫:支援跨機房雙寫是資料庫領域一大難題,是我們對分布式資料庫的一個重要期待,也是美團下一階段重要的需求。

業界的一些傳統方案雖然支援分片,但無法自動分裂、遷移,不支援分布式事務,還有一些在傳統 mysql 上開發一緻性協定的方案,但它無法實作線性擴充,最終我們選擇了與我們的需求最為接近的 tidb。與 mysql 文法和特性高度相容,具有靈活的線上擴容縮容特性,支援 acid 的強一緻性事務,可以跨機房部署實作跨機房容災,支援多節點寫入,對業務又能像單機 mysql 一樣使用。

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

首先,我們需要知道擴容、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 到其他機房,是否會自動回來。

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

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

目前 mysql 的業務接入方式主要有兩種,dns 接入和 zebra 用戶端接入。在前期調研階段,我們選擇了 dns + 負載均衡元件的接入方式,tidb-server 節點當機,15s 可以被負載均衡識别到,簡單有效。業務架構如圖 2。

TiDB 深度實踐之旅--真實“踩坑”經曆

圖 2 業務架構圖

後面我們會逐漸過渡到目前大量使用的 zebra 接入方式來通路 tidb,進而保持與通路 mysql 的方式一緻,一方面減少業務改造的成本,另一方面盡量實作從 mysql 到 tidb 的透明遷移。

美團目前使用 mt-falcon 平台負責監控報警,通過在 mt-falcon 上配置不同的插件,可以實作對多種元件的自定義監控。另外也會結合 puppet 識别不同使用者的權限、檔案的下發。這樣,隻要我們編寫好插件腳本、需要的檔案,裝機和權限控制就可以完成了。監控架構如圖 3。

TiDB 深度實踐之旅--真實“踩坑”經曆

圖 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 的計算表達式比較少,是以需要在監控腳本中進行轉換和計算。

tidb 使用 ansible 實作自動化部署。疊代快,是 tidb 的一個特點,有問題快速解決,但也造成 ansible 工程、tidb 版本更新過快,我們對 ansible 的改動,也隻會增加新的代碼,不會改動已有的代碼。是以線上可能同時需要部署、維護多個版本的叢集。如果每個叢集一個 ansible 目錄,造成空間的浪費。我們采用的維護方式是,在中控機中,每個版本一個 ansible 目錄,每個版本中通過不同 inventory 檔案來維護。這裡需要跟 pingcap 提出的是,ansible 隻考慮了單叢集部署,大量部署會有些麻煩,像一些依賴的配置檔案,都不能根據叢集單獨配置(咨詢官方得知,pingcap 目前正在基于 cloud tidb 打造一站式 htap 平台,會提供批量部署、多租戶等功能,能比較好的解決這個問題)。

随着線上叢集數量的增加,打造運維平台提上了日程,而美團對 tidb 和 mysql 的使用方式基本相同,是以 mysql 平台上具有的大部分元件,tidb 平台也需要建設。典型的底層元件和方案:sql 稽核子產品、dts、資料備份方案等。自動化運維平台展示如圖 4。

TiDB 深度實踐之旅--真實“踩坑”經曆

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

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。

TiDB 深度實踐之旅--真實“踩坑”經曆

圖 5 tidb to hive 方案圖

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

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

業務場景:

穩定的寫入,每個事務操作 100~200 行不等,每秒 6w 的資料寫入。

每天的寫入量超過 500g,以後會逐漸提量到每天 3t。

每 15 分鐘的定時讀 job,5000 qps (高頻量小)。

不定時的查詢(低頻量大)。

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

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

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。

TiDB 深度實踐之旅--真實“踩坑”經曆

圖 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

現在 tidb 的 gc 對于每個 kv-instance 是單線程的,當業務删除資料的量非常大時,會導緻 gc 速度較慢,很可能 gc 的速度跟不上寫入。

目前可以通過增多 tikv 個數來解決,長期需要靠 gc 改為多線程執行,官方對此已經實作,即将釋出。

業務上線初期,insert 的響應時間 80 線( duration 80 by instance )在 20ms 左右,随着運作時間增加,發現響應時間逐漸增加到 200ms+。期間排查了多種可能原因,定位在由于 region 數量快速上漲,raftstore 裡面要做的事情變多了,而它又是單線程工作,每個 region 定期都要 heartbeat,帶來了性能消耗。tikv-raft propose wait duration 名額持續增長。

解決問題的辦法:

臨時解決

增加 heartbeat 的周期,從 1s 改為 2s,效果比較明顯,監控展示如圖 7。

TiDB 深度實踐之旅--真實“踩坑”經曆

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

徹底解決

需要減少 region 個數,merge 掉空 region,官方在 2.1 版本中已經實作了 region merge 功能,我們在更新到 2.1 後,得到了徹底解決。

另外,等待 raftstore 改為多線程,能進一步優化。(官方回複相關開發已基本接近尾聲,将于 2.1 的下一個版本釋出。)

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 接口删除整個表占用的空間,然後清理少量殘留資料,已經解決。

為了解決 region 過多的問題,我們在更新 2.1 版本後,開啟了 region merge 功能,但是 tidb 的響應時間 80 線( duration 80 by instance )依然沒有恢複到當初,保持在 50ms 左右,排查發現 kv 層傳回的響應時間還很快,和最初接近,那麼就定位了問題出現在 tidb 層。研發人員和 pingcap 定位在産生執行計劃時行為和 2.0 版本不一緻了,目前已經優化。

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

業務無法友好的執行分布式事務。

跨庫的查詢,需要在中間層上組合,是比較重的方案。

單庫如果容量不足,需要再次拆分,無論怎樣做,都很痛苦。

業務需要關注資料分布的規則,即使用了中間層,業務心裡還是沒底。

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

業務偶爾報出 privilege check fail。

是由于業務在 jdbc 設定了 querytimeout,sql 運作超過這個時間,會發行一個 “ kill query ” 指令,而 tidb 執行這個指令需要 super 權限,業務是沒有權限的。

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

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。

TiDB 深度實踐之旅--真實“踩坑”經曆

圖 8 tidb htap platform 整體架構圖

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

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