TiDB 4.0 在 VIPKID 的應用實踐

做者介紹:許超,VIPKID 資深 DBA 工程師。

本文主要分享 TiDB 4.0 版本在 VIPKID 的一個應用實踐。主要涉及兩個部分,第一部分是如今 TiDB 在 VIPKID 的一些應用場景,第二部分是介紹一下 TiDB 4.0 給咱們帶來哪些驚喜和收益。算法

TiDB 在 VIPKID 的應用場景

首先簡單介紹一下 VIPKID,VIPKID 是一家在線少兒英語教育公司,專一於服務 4-15 歲的青少兒和他們家長們,主要提供北美外教一對一授課服務,目前已經有超過 70 萬的付費用戶。微信

場景一:大數據量及高併發寫入

迴歸主題, TiDB 在 VIPKID 的第一個應用場景是一些大數據量和高併發寫入的場景,以下圖所示:架構

舉其中一個例子,咱們如今有一套教室排障的系統,這套系統會實時收集教室內的一些事件信息,好比進出教室還有教室內服務初始化的信息,這些信息是經過家長端還有教師端統一上報的,業務同窗能夠根據這些信息快速定位到教室內的故障,而且作一些排障手段,好比說切換線路之類的來保證一些上課質量。併發

這套系統目前 TPS 峯值在 1 萬左右,天天的新增數據量大概有 1800 萬,這張表只保留最近兩個月的數據,目前單表有 12 億左右,數據量其實相對來講已經比較大了,這種數據量若是如今放在 MySQL 裏維護成本比較高,因此咱們把這套系統的數據整個遷移到 TiDB。app

在遷移過程咱們作了一些小的變更,在原有表的基礎上把原來的自增 ID 去掉了,在建表的時候經過指定配置作一下預先打散,避免高寫入量的時候出現寫熱點問題。關於熱點定位,其實 TiDB 自己以前就提供了不少方式了,好比 3.0 版本其實通 information_schema.TIDB_HOT_REGIONS 這張表就能夠定位,或者直接能夠在 PD 裏獲取相應的熱點 Region 信息,可是經過這種方式拿到的其實只是一個 Region ID,還須要調用具體的 TiDB server 的 API 來獲取定位到具體的表或者索引。在 4.0 裏,TiDB Dashboard 讓熱點直觀地呈如今咱們面前,咱們能夠直接看到熱點寫入量、讀取量等等熱點信息。異步

場景二:核心模塊分庫分表後的多維度查詢

第二個場景是如今咱們的不少核心業務在早期就已經作了分庫分表,好比約課表。對分庫分表比較瞭解的同窗其實知道,通常分庫分表的狀況下只會以一個業務列做爲 Sharding Key 作拆分,可是約課表這種狀況下可能涉及到的維度比較多,既有教室、老師、學生還有課程;另外可能其餘端也會訪問這部分數據,好比教師端來訪問這部分數據的時候他可能會以教師的維度來訪問,若是作拆分的時候是以學生的維度拆分的,那麼教師的訪問請求會廣播到全部分片上,這在線上是並不容許的。針對這個問題,咱們最開始有兩種解決方案,一種是咱們把全部的數據匯聚完放在 ES,還有一種方式是業務雙寫,寫兩套集羣,兩套集羣以各自的維度拆分。不管哪一種方案,不管是對 RD 來講仍是對咱們 DBA 來講維護成本都比較高。分佈式

因此咱們就藉助 DM,經過 DM 將上游全部分片的表實時同步到下游,而且合併成一張全局表,全部的跨維度的查詢,不管是管理端運營平臺,仍是業務指標監控的系統都走 TiDB 這套系統,查這張全局表,以下圖所示:函數

再簡單介紹一下 DM 分庫分表的邏輯,其實邏輯相對比較簡單,DM 其實會拉取線上全部分片的 Binlog 日誌,而後根據黑白名單過濾匹配出須要同步的那部分 binlog event,再去匹配製定的路由規則,經過改寫而後應用到下游的全局表裏,這裏也區分兩種狀況:一種狀況是上游的分庫分表包含全局 ID,這種狀況其實自然的避免了合併以後的主鍵衝突的問題。還有一種是沒有全局 ID 的狀況,這種狀況以前官方提供了一個解決方案是經過 Column mapping 的方式,其實就至關於對 ID 列在同步以前作一些預處理,處理以後至關於在底層同步的時候就不會有主鍵衝突的問題了。可是咱們和 PingCAP 同窗溝通了一下,其實他們如今已經不建議用這種方式了。因此咱們換了另一種方式,由於咱們的業務對於這種自增 ID、主鍵 ID 是沒有業務依賴的,因此在下游 TiDB 這塊我其實提早建了下圖所示的這樣一張表,而後把對應 ID 的主鍵屬性和自增屬性去掉,而且將這個 ID 加入我原先僅有的一個聯合的惟一索引裏就解決這個問題了:高併發

在 DM 這塊咱們簡單地作了兩件事。第一是 DM 的延遲監控,其實 DM 自己支持延遲監控,也是經過寫心跳的方式去作的,但在咱們線上把 DM 並非掛在 MySQL 集羣的主節點下,而是掛在一個只讀存庫上,因此咱們不太容許 DM 直接去寫存庫的心跳。咱們線上有一套心跳機制來監控延遲,因此在實際 DM 這塊延遲監控實際複用的是線上的那套心跳錶,至關於把線上的那套心跳直接同步下來,也是經過路由規則匹配一下,而後改寫。這樣的話雖然在 TiDB 裏可能涉及到多個集羣,但其實每一個集羣對應單獨的一個心跳錶,這樣就能夠作 DM 的延遲監控。在下圖裏你們能夠看到,大部分狀況下分庫分表合併的場景同步延遲基本都在 200 毫秒之內:工具

第二件事就是解決 DM 高可用問題,因爲 DM 自己並不具備高可用性,可能一個 DM worker down 的時候可以支持自動拉起,但若是出現整個節點 down 的狀況下實際上是一籌莫展的。以下圖所示,咱們作了一個簡單的嘗試:

至關於把 DM-master、DM-worker 的全部的持久化的數據全放在共享存儲上,DM-worker 是經過容器啓動的,若是發生節點宕機的狀況下,只須要在備用機上把對應的 worker 提起來,而且關聯到本身指定的 DM-worker 的共享存儲上 DM 的路徑就行。這裏有一個問題是 IP 是固化不了的,因此在這個過程當中還須要去變動 DM-master 的配置文件,以後作一次 Rolling Update。

場景三:數據生命週期管理

TiDB 在 VIPKID 的第三個場景其實就是在數據生命週期管理。若是用過 MySQL 的都知道,其實大表在 MySQL 裏維護起來成本是比較高的,因此通常不少公司會作逐級的數據歸檔。咱們如今是根據具體業務,按照讀寫狀況將數據劃分紅多個等級,並把其中溫數據、冷數據,其實還有線上讀流量的放在 TiDB 裏。

這個場景裏引入 TiDB 的考慮是要把數據的流轉、運轉起來的一個前提要保證冷熱數據的表結構一致,但實際狀況是,冷數據大部分狀況下比熱數據體量大不少,好比線上熱數據作了一次表結構變動,好比加一列,同時若是冷數據一樣要作這個操做,成本實際上是很高的,多是熱表的十幾倍或者幾十倍都有可能,所以咱們想借助 TiDB 來作這個事情。自己一方面 TiDB 的 DDL 有一些特性,加字段、減字段都是秒級的,另外一方面就是藉助 TiDB 自己的水平擴展的能力,咱們能夠每一個業務端複用一套 TiDB 歸檔集羣。下面再簡單總結一下咱們在使用 TiDB DDL 的相關經驗,以下圖所示:

左半部分我列了幾個相對比較常見的 DDL 操做,好比刪表、刪索引,其實在 TiDB 裏分了兩步作,第一步只變動元數據,這時候就已經秒級返回給用戶了,剩下實際數據的清理,是放在後臺經過 GC 異步來處理的。而添加索引操做由於涉及到數據的填充和重組,因此這個操做的時間是依賴於數據量,可是並不會阻塞線上業務,我以前看了一下官方的介紹,TiDB 中數據填充的過程被拆分爲多個單元,每一個單元內部併發進行讀寫操做。線上更常見的是刪列和減列,在 TiDB 裏跟 MySQL 的實現就不同了,也只是變動元數據就好了,並不須要作底層的數據的 rebuild,好比增長一個列,並不須要對原始數據再作一個回填,這裏分兩種狀況,一種是默認值是空的,一種是有一個指定的默認值,其實只須要把這個默認值記錄到 TiKV 裏跟表結構記錄在一塊,當你查詢這個數據對列值作 decode 的時候,若是是空的,直接返回空;若是是有指定的默認值的,直接返回指定默認值,並不須要對歷史數據作變動。

場景四:實時數據分析的場景

還有一個場景就是作實時數據分析的場景,下圖實際上是最先 TiDB 在 VIPKID 引入的一個場景:

這個場景主要是 BI 分析師還有一些 BI 平臺在用,架構上,至關於經過 DM 把線上的數據所有同步到 TiDB 裏,藉助 TiDB 的水平擴展能力,還有一些計算下推的能力,作一些實時數據分析。

TiDB 4.0 給咱們帶來哪些驚喜和收益?

TiFlash 列式存儲引擎

TiFlash是一個列式存儲引擎,相對來講對 AP 場景更友好一些,而且他自己本身有計算能力,支持一些算子下推、計算加速。另外,TiFlash 能夠實時複製 TiKV 中的數據,而且沒有打破以前 TiKV 的運行模式,它把本身做爲一個 Learner 角色加入以前的 Raft Group 裏能夠支持表粒度的同步;還有一個就是智能選擇,TiFlash 能夠自動選擇使用 TiFlash 列存或者 TiKV 行存,甚至在同一查詢內混合使用以提供最佳查詢速度,它已經不只僅是單純的一個 SQL 選擇哪一種存儲引擎,粒度能夠細化到同一個 SQL 裏具體某個算子,好比一個 SQL 打過來,一部分能夠走索引的其實走行存更快,還有一部分涉及到全表掃描的走列存,經過這種方式總體提升 SQL 查詢速度。最後,TiFlash 支持獨立部署,能夠跟 TiKV 獨立分開,某種程度上作到了硬件資源的隔離。

下面談談 TiFlash 給咱們帶來的收益。

首先是性能提高,我這裏作了一個簡單測試,測試環境如今是有五個 TiKV 節點,一個 TiFlash 節點,有一個單表 2.5 億數據,而後我對這個單表作 count,在 TiKV 裏走了索引的狀況下跑了 40 多秒。而在單個 TiFlash 場景下 10 秒就跑出來了,這只是單個 TiFlash 節點,若是我再新添一些 TiFlash 節點,這個速度應該還能夠進一步提升。

<div class=」caption-center」>TiFlash</div>

<div class=」caption-center」>TiKV</div>

第二是成本的降低,咱們原來有一套給 BI 用的集羣,如今用新的 TiDB 4.0 的集羣替換了,能夠看一下下圖左邊的表格是新的 4.0 的集羣各個組件資源分配比例,左邊是新、老集羣一樣負載狀況下的資源分配狀況。能夠看到,部署新集羣讓咱們總體成本降低了 35%。

第三 TiFlash 上線解決了一些穩定性的問題。以前在 TiKV 這一層若是跑了一些 TP 業務,這時候有一個  SQL  涉及到一個全表掃描,整個 TiKV 的集羣負載就會變大,可能致使 TP 查詢總體響應時間變長。如今我能夠加入一個 TiFlash 節點,把對應集羣裏的大表自動添加一個 TiFlash 的副本,在這種狀況下若是有一些相似的狀況,能夠優先會走 TiFlash,而保證 TiKV 儘可能不受影響。

再說兩點咱們在使用 TiFlash 過程當中遇到的一些「限制」。

第一,若是你的 SQL 中涉及到一些 TiFlash 尚未實現的函數,實際上是沒法作到計算下推的,只是利用到了 TiFlash 自己做爲列存的一個加速能力(注:若是有還沒有實現的下推需求,能夠與 PingCAP 官方聯繫技術支持,添加微信號XXX,備註「TiFlash 技術諮詢」便可)。

第二,如今 TiFlash 對大表和大表之間的 JOIN 場景其實覆蓋的還不夠好,只針對小表和大表之間的 Join 作了一些優化(固然後來咱們經過 PingCAP 同窗瞭解到他們 7 月會發佈一個優化大小表 JOIN 的功能,可讓若干小表 JOIN 大表比現有方案數量級提高的優化,而且他們今年也會開始陸續優化剩下的 JOIN 場景)。若是你們對 Spark 比較瞭解的話,可能知道 Hash Join 其實有幾種算法,其中一種至關於把一張小表廣播到各個數據節點,而後在數據節點本地作 Hash Join 操做,能夠看到下圖左邊的截圖,是咱們一個教師招募相關的一個大屏統計:

這個查詢執行了大概 17 分鐘,實際過程當中也訪問了 TiFlash,但總體的時間其實都耗費在 Hash Join 了,在 TiFlash 上消耗的時候並很少,圖上能夠看到 TiDB server 這一側總體負載很高,因此瓶頸是在 TiDB server 這塊。

所以咱們就考慮怎麼把 Hash Join  這塊打散,而後咱們引入了 TiSpark。以下圖所示:

通過對比測試(單個 TiDB server 是 8C 64G 的),分配一樣的計算資源給一個小的 TiSpark 集羣跑了一個一樣的查詢,耗時差很少是原來的大概三分之一。下圖是改造後給 BI 用的一個 TiDB server 的集羣:

這裏主要添加了 TiSpark 的組件和 TiFlash 的組件,因爲大屏展現 SQL 能夠明確,因此不少直接走了 TiSpark,而 BI 分析師和 BI 平臺的查詢統計,直接走 TiDB,而後智能選擇讓它走 TiKV 仍是 TiFlash。

TiDB Dashboard

TiDB 4.0 中內置的 Dashboard 在個人理解裏,實際上是 TiDB 在產品易用性、「開箱即用」層面作了一次很大的提高。

在 3.0 版本像熱點的問題也是有方式能夠查的,可是相對來講可能有必定的學習成本,另外可信息比較零散。如今 4.0 版本把這些都放在了 Dashboard 裏,以一個更直觀的方式展示給用戶。而後就是 Dashboard 裏好比說像日誌蒐集還有慢日誌這塊,這塊其實跟剛纔的邏輯同樣其實就是爲了讓用戶能夠更簡單的使用 TiDB,若是沒有這些東西的話,用戶集羣小的話能夠去具體節點上去查,若是集羣規模比較大,可能用戶要本身準備一套日誌提取、日誌上報的東西,實際上是存在必定的落地成本的。還有一塊是在集羣診斷這一塊,集羣診斷這塊像咱們的業務其實每週有一個按期的活動,有時候研發會說我這周和上週的量並無明顯的變化,但其實感受到下邊的響應時間變長了,其實能夠生成指定的診斷報告,裏邊我能夠明確一個基準的區間作對比:

Backup & Restore 

以前 TiDB 在備份這塊相對來講相對空白了一點,只支持邏輯備份,但說大數據量的狀況下邏輯備份效率是很低的,因此如今 4.0 中的 BR 工具偏物理備份,仍是讓人很受鼓舞的。

BR 自己的程序去跟 PD 通訊,來獲取當前的時間戳,還有目前 TiKV 的分佈狀況,而且 BR 本身在內部啓動一個臨時的 TiDB 實例,去構建一個備份相關的請求信息,而且將請求信息發給各個 TiKV 節點,因此這個過程當中備份實際上是一個分佈式的備份,指定的 TiKV 節點會只備份本身當前實例上的主節點,作相似於物理備份,當他把  Region Leader 備份完了以後會把對應的元數據返回給 BR,BR 會把這些元數據保存在一個單獨的文件裏,而後待恢復的時候使用。

咱們簡單試用了一下,以下圖所示:

咱們按官方的建議,以共享存儲的方式來作備份,至關於在 BR 那臺機器還有全部 TiKV 的機器上都掛了相同的共享存儲作了一次備份,一個 2.4T 左右的 TiDB 實例備份了大概幾個小時,這個時間還能夠進一步優化的,由於我看平均速度才 80 多兆,多是受限於如今 SAS 盤帶寬的問題,後期作一下調整會更快。你們從上圖也能看到 BR 備份的各個目錄的大小,總體備份大小能夠看到大概有 700 多 G。

以上就是所有分享,謝謝你們。

本文整理自許超在  TiDB DevCon 2020 上的演講。
相關文章
相關標籤/搜索