使用 TiDB 構建實時應用

作者介紹

雷宇,TiFlash 研發工程師,畢業於中山大學軟件工程專業。目前主要在 PingCAP 從事 TiDB SQL MPP 的相關研發工作。

**本文由 PingCAP 研發工程師雷宇分享,主要從宏觀角度分析 TiDB 究竟能做什麼,創造什麼樣的價值,以及研發過程中的一些設計立足點。**文章將從四個部分分享:

數據管理技術的演進

首先,簡單的回顧一下數據管理技術的演進。

整體來看,從 2000 年開始,大數據的技術就邁入了互聯網生態,使用大數據技術來建立數據倉庫已較爲普遍。儘管數據倉庫的理念在 90 年代就已經出現了,但各個數據倉庫的產品都尚未開源,業界缺乏共識。而 Hadoop 開源之後,基於 Hadoop 的數倉架構逐漸成爲主流,也即傳統的數倉架構。

傳統數倉架構

如上圖所示,左邊是 OLTP 在線業務所使用的數據庫,因爲無法直接在上面進行分析,所以一般會通過 MySQL 的 Binlog CDC 或直接讀寫數據庫 ETL 的方式,將數據變更或全量的數據導至 Hadoop 平臺,然後在 Hadoop 中使用 Hive 等軟件進行數據分析,並且生成報表,將結果寫入到另一個 OLTP 的數據庫中,也就是右邊用來做離線分析的結果呈現的 Data Serving 層。最後再由 Data Serving 層將數據展現給應用。

由於這一整套鏈路非常長,還有 Hadoop 中各種各樣實現的原因,所以這一架構在最開始只能做到 T+1 的程度,即當天的數據寫入後第二天才能計算出來。

雖然解決了海量存儲與計算的問題,但是失去了數據處理的實時性。近年來,隨着實時性的需求越來越多,爲了保證數據處理的實時性,出現了一種新的架構:Lambda 架構。

Lambda 實時數倉

Lambda 架構的特點在於爲離線的 Hadoop 加了一個實時計算層,一般稱之爲 Speed Layer,早期主要使用 Spark Streaming 或 Storm 流式計算引擎來直接採集 OLTP 的數據,將其計算爲實時的數據,然後和離線的 T+1 的數據混合在一起,提供給應用。如此,應用即可得到一個相對來說比較實時的數據。

傳統數倉時代只能做到 T+1,有了 Lambda 的架構後,就可以實現 T 加零點幾,昨天的數據和今天半天的數據合併在一起處理。不過,在此基礎上能否實現更實時的數據分析?

Kappa 實時數倉

Kappa 架構應運而生。之前 Lambda 架構的痛點在於需要做非常複雜的維護,因爲同時要把數據寫到 T+0,也要把數據寫到實時的部分,然後再將兩部分的結果整合起來。有了 Kappa 架構之後,只要通過實時的計算層,按需拉取 OLTP 業務的變更,然後將計算結果數據呈現出來即可。但是這一套體系因爲性能方面的原因,暫時還沒有得到特別廣泛的應用。

可以看到,在數倉架構演講的過程中,數據實時性已經變成了大家普遍的需求,同時海量的數據處理能力也必不可少。在這種情況下,我們來看看 TiDB 能做什麼。

TiDB 能做什麼?

TiDB 4.0 之前

TiDB 1.0 發佈時,架構圖如下,這也是所有很多人對 TiDB 的第一印象。

TiDB 的架構非常簡單,首先是 Load Balancer,可以將用戶的 SQL 請求打散,發送到 TiDB Server 中。TiDB Server 是一個無狀態的計算層,可以隨意擴展,實際的數據存儲在分佈式 KV 存儲 TiKV 中。此外,還有一個 PD 組件來對這些數據進行調度以及規整。

這一套架構最突出的部分是擴容,以擴容作爲第一要義。擴容體現在兩個方面,一是存儲擴容,傳統的單機數據庫無法承載的數據量,TiDB 可以將其存儲到分佈式存儲中。二是計算上,傳統數據庫單機無法承受較高的 QPS, 通過這種擴容的方式,QPS 可以打散到不同的計算節點上。

在 TiDB 4.0 之前,我們一直延續這套架構。以下是 TiDB 4.0 之前我們能做到什麼的總結:

首先,TiDB 的立足點是一個兼容 MySQL 協議以及 MySQL 特性的關係型數據庫,具備水平擴展能力,包括存儲和計算都可以進行水平擴展,並且不需要分庫分表。在此基礎上,因爲支持計算的水平擴展,所以能承載高 QPS 的在線業務,並且存儲、計算分離,爲彈性資源配置提供了基礎。

但超乎我們想象的是,許多開源社區用戶將 TiDB 作爲數倉的優質載體。TiDB 可以接受海量數據的存儲,同時也可以提供比較方便的訪問接口,所以很多用戶自然地將其作爲數倉的中間層。

在 TiDB 4.0 之前,設計上完全沒有考慮到這種用法,所以存在很多問題,比如計算是單節點,無法進行分佈式擴容,一些比較重的計算任務也不支持。同時,TiDB 的存儲引擎 TiKV 使用的是行存的存儲格式,行存的優勢在於 OLTP 場景下可以較好的處理併發事務,但是在 OLAP 場景下的性能不太理想。

因爲收到了各種各樣的用戶需求,所以我們專門研發了 TiDB 的列存引擎 TiFlash,來承載 TiDB 的 OLAP 負載。在 TiDB 4.0 中,TiFlash 正式成爲了 TiDB 家族的一名成員。

TiDB 4.0 之後

在 4.0 之前,社區已經提供了一套 TiSpark。TiSpark 本質上是一個 Spark 插件,通過 TiSpark,我們可以在 Spark 中訪問 TiDB 集羣中的數據,並對其進行讀寫。但是使用 Spark 訪問 TiDB 的數據會存在一定問題,因爲它是一個高併發的掃表請求,會導致 TiKV 本身 OLTP 的負載受到影響。

在有了 TiFlash 之後,就可以完全隔離到 OLAP 和 OLTP 的負載,也能保證一致性。TiFlash 的一致性是通過 Raft 的同步協議來做的,熟悉 Raft 的同學應該知道,它是一個同步複製協議,所有的數據都是以 log 的形式來呈現。每一條 log 都有一個全局一致的 ID,也是其位置的 index。假如兩條 log,一個是 4,一個是 5,那麼 Raft 協議可以保證 5 一定是在 4 之後纔會寫入,當 5 進行寫入時所有的 Client(TiDB) 均能讀到 4,從而滿足線性一致性。

一般來說,在 Raft 中只有 leader 可以進行讀寫操作,但如果對此進行優化,實現一個 learner 或者 follower 的狀態即可滿足讀取 leader 上同樣一個 index 的條件,就可以直接從 learner 上讀取數據。TiFlash 就是利用這樣一種機制從 TiKV 集羣中同步數據,並且達到線性一致性的。這樣做的優點在於:

首先,假設用 binlog 等方式來將數據同步到列式分析引擎中,中間會有額外的傳輸開銷或者類似於中間件的處理開銷。而直接通過 Raft 協議來進行寫入,在一條數據寫到 leader 時,會走 Raft 的 quorum 確認流程,此時數據已經被髮送到 TiFlash 進行寫入了。另外,雖然 TiFlash 的寫入確認不需要同步,但是它的數據和 TiKV 內部的高可用優先級是一樣的,這是達到一致性的關鍵。

總體而言,在有了 TiDB 4.0 之後,分析能力上了一個臺階。此時,我們可以自豪說 TiDB 是一個真正意義上的 HTAP 數據庫了。TiDB 的特點如下:

TiDB 5.0 HTAP

在 5.0 的時候,爲了解決上述痛點,我們研發了 TiDB 的 MPP。先了解一下 MPP 究竟是什麼。

在執行 SQL 時,使用的是一套  Volcano 的模型,其優勢在於算子之間是可以解耦的,缺點在於上下游之間的調用有耦合,即必須是上游找下游要數據,然後下游纔會將數據算出來提供給上游。每一個算子之間的消費能力和生產能力非常不匹配。儘管 TiDB 本身也做了非常多的優化,在算子內部通過並行計算來加快其計算速度。但歸根結底它也只是一個單機的計算引擎,上限非常低。爲了解決這個問題,我們充分利用了 TiFlash 節點。

首先,看看如何實現。

一條 SQL 從 TiDB 進來,經過 Parser 和 Planner 生成一個 TiDB Logical Plan,然後 Logical Plan 經過 TiDB 的優化器之後,會判斷是否是 OLAP 請求。

如果是 OLAP 的請求,需要根據代價估算來選擇從 TiKV 進行讀寫,還是 TiFlash 進行讀寫。在此過程中,我們還會爲這些 join 的算子加上 exchange,也就是  Volcano 論文中提到的並行化的方式,生成一個並行的執行計劃,再將這些執行計劃的片段給推送到對應的 TiFlash 節點執行。

來看一個實際的例子。

上述是來自於 TPCH 數據集的數據。TPCH 數據集中有一個叫做 lineitem 的表,lineitem 的表中存取的是所有的商品的信息,一般來說是 6 億行左右。此外,還有 orders 表,orders 表是商品訂單的事實表,我們在做簡單的 Join 之後,加上一個 Count Star 的聚合。此時的 Plan 在 MPP 架構下則有所不同。以前,通常情況下 Join 下面是兩個 Table Scan,如果是在 TiDB 中進行計算,兩個 Table Scan 之後可以直接放到 Join 的算子中。但在 MPP 之後,我們會先對 Scan 出來的 Table 進行一個根據 Join Key 的 Shuffle,然後將數據推送到對應的計算節點,整體計算完成之後,再推到 TiDB 中返回給用戶。

這樣的好處有兩點,一方面如果使用單個 TiDB 節點來進行計算,需要在內存中放大量數據,甚至數據可能是 TiDB 容納不下的,此時就必須將其落到磁盤上,計算效率非常低。但是通過 shuffle 分區之後,每個計算節點上需要計算的數據量變小,可以全部容納在內存中,可以實現加速的效果。另外,MPP 可以同時利用多臺機器的 CP,理論上可以實現非常強的擴展性。

爲了驗證 TiDB MPP 的性能,我們對比了其他產品,集羣是三個節點的集羣,每個節點上面使用的都是 NVMe 的 SSD,可以儘可能的排除存儲上讀取對於整個計算速度的影響。

如上圖,可以看到藍色的是 TiFlash MPP 的性能,長短代表它的執行時間,這項指標越短越好。從上圖可以看出,對比 Greenplum 和 Apache Spark,MPP 在絕大多數的查詢下都處於優勢地位。原因在於:一方面,TiDB 5.0 本身集成了一套列式計算引擎,性能非常強大;另外一方面,MPP 架構相對於批處理引擎的優勢在於所有的任務是平行的,不會存在互相依賴的情況,所以它可以用更好的方式進行併發。但缺點在於,相較於批處理,無法支持過於龐大的數據量,不過在絕大多數的場景下, MPP 架構已經非常夠用了。

總結一下 TiDB 的 MPP

有了 MPP 架構之後,TiDB 5.0 新引入的幾個 Feature,使 TiDB 的 HTAP 能力得到了極大的提升:

以上分享了 TiDB 不同階段的功能特性和產品能力,下面將具體說明大家是怎麼用 TiDB 的。

大家是怎麼用 TiDB 的?

根據用戶反饋以及我們自己的整理,發現了當前 TiDB 最常用的幾個場景。

交易 / 分析一體化

首先,交易分析的一體化,這種場景下數據量級一般處於中等程度,即 TB 級別。

如果單純使用 MySQL,無法比較好地進行數據計算,所以一般需要將這些數據導入到分析型數據庫中進行計算,比如 ClickHouse、GreenPlum 等,再將計算出來的報表呈現出來。有了 TiDB 之後,可以將這兩部分相結合,TP 直接寫 TiDB,AP 也直接在 TiDB 上進行計算,然後呈現結果,這樣可以極大節省了運維成本,並且可能實現性能上的提升

交易分析一體化的場景比較常見的,如:CRM 系統、ERP 系統等,也是我們非常推崇的最完整的 HTAP 的場景。但是互聯網公司一般無法使用,必須也有離線的部分來處理海量的數據。

因此,在這套體系中,TiDB 主要被用於實時分析。

實時分析

業務數據通過 Kafka + Flink 的方式,在 Flink 中做預聚合或拼寬表,然後再將這個結果寫入到 TiDB 中,供應用查詢。這是常見的實時分析架構。而如果應用的線上業務已經用了 TiDB,整套架構就更自然了,可以直接使用 TiDB 的 CDC 功能,將數據導入到 Flink 中進行處理。

由於整套架構非常實用,目前已廣泛應用於多個業務場景,後面將舉例說明。

實時分析:Flink 架構

實時分析中使用 Flink 也有幾種常見的架構。

第一種架構,前端業務使用的是 MySQL,比如分庫分表方案,通過 Flink MySQL Connector 獲取 MySQL 的數據變更,然後再將數據寫入 TiDB。

第二種架構,通過 MySQL binlog 處理的中間件,比如 Canal 等處理數據,然後寫入到 Kafka 供 Flink 消費,最後再寫進 TiDB,這種方式比較常見。

第三種架構,用戶前端已經使用了 TiDB,通過 TiDB 的 CDC 功能,輸出 Canal JSON 格式到 Kafka 中供消費,Flink 再將數據寫入到 TiDB 類似的數據庫或者其他 sink 中。

還有一種常見的方案,數據倉庫的加速層或者說 ODS 層。

最常見的用法一般數據倉庫會將加速層分開,有了 TiDB 之後,兩部分是可以合起來的,用戶的數據可以通過各種各樣的方式寫進 TiDB,在 TiDB 裏面在進行一些 ETL 之類的操作然後寫入到離線計算中,最後再將結果反饋到 TiDB。TiDB 可以直接對外提供實時數據分析的服務,這也是非常流行的架構之一。

應用案例

接下來,將分享一些現實中公司的案例。

🌟 中通快遞物流

首先是大家都比較熟悉的中通快遞,中通快遞現在應該是全球業務規模最大快遞企業之一。近幾年,他們開始嘗試使用 TiDB 來做包裹追蹤管理工作。早期,他們使用 TiSpark 進行計算,然後將數據拼成寬表寫到 TiDB 中,再進行一些聚合。最近,他們已經在測 5.0 的 MPP 架構,看看 TiDB 5.0 能否提供更多幫助。

中通快遞的架構如上。首先,包裹追蹤是線上業務,通過 Spark Streaming 訓練方式寫入到 TiDB 中,同時進行實時分析,然後 TiDB 的歸檔數據將發送到中通的大數據平臺進行計算,最後大數據平臺的計算的結果再寫回到 TiDB。在這個結構中,TiDB 是整個實時計算的整合層。

🌟 小紅書

小紅書是一個內容同時做垂直電商相關的平臺,目前用戶量和訪問量都也非常大。

小紅書的早期架構是業務使用 MySQL 分庫分表的方案,業務數據通過 ETL 寫入到離線產品,進行 T+1 的計算後,再寫回到另一個 MySQL 的分庫分表集羣中,對外提供數據服務。同時,也會利用離線數倉來做風控相關的業務。

上述架構的痛點在於 T+1,業務和運維都非常難受。在嘗試 TiDB 之後,將架構進行了升級。

目前業務在線層仍然使用分庫分表,但業務數據會直接通過一些簡單的方式寫到 TiDB 中,同時 TiDB 將數據反饋給離線層,做完離線數據的處理再寫回到 TiDB。

上述結構直接使用 TiDB 進行數據分析或風控服務,整體架構從 T+1 變成了 T+0,並且據小紅書工程師反饋,用了 TiDB 之後,節省了很多 MySQL 分庫分表的運維精力,這也是 TiDB 的優點之一。

🌟 智慧芽

智慧芽是提供 SaaS 服務的廠商,爲全球 50 多個國家超 10000 家科技公司、高校、科研與金融機構提供大數據情報服務。

智慧芽的所有業務都部署在 AWS 之上。早期,智慧芽通過 AWS 的 Redshift 來進行數據分析,但是 Redshift 本身的速度並不特別理想,因此爲了獲得更好的實時性,智慧芽開始嘗試使用 TiDB 構建實時數倉。在數倉架構上跟其他公司非常相似,也是使用 Flink 進行實時數據處理,然後將各種各樣的數據寫入到 TiDB,最後直接呈現給數據應用。

以上幾個案例是非常典型的使用 TiDB 來做實時數據分析的場景,其中也有相對偏向於 HTAP 的業務如小紅書的架構,其線上業務數據會直接寫到 TiDB 中,可以充分利用 TiDB 的 OLTP 能力。

看了這麼多案例之後,我們也可以想象一下 TiDB HTAP 的未來。

TiDB HTAP 的未來

首先,最重要的一點,5.0 之後,TiDB 已經可以用來做複雜計算了,同時我們可以提供更加實時的場景來驗證

SQL MPP 意味着什麼?

有了 SQL 和 MPP 之後,我們有了更快的計算速度,同時可以承載更復雜的計算任務,再加上強實時性的數據,以及強一致性保證。有了這些之後,我們可以做到什麼?

直播場景

首先,直播場景。在某個大主播開播時,用戶會直接就湧進來,此時用戶的信息會插入到訪問的事實表中,主播的直播間也會對其維度表進行更新。這一套架構如果按照傳統的方式來,可能會使用 Flink 對數據進行處理,但同時也存在一個問題,操作的併發度將會非常高,並且需要在短時間內完成。因此,如果要 Flink 進行處理,需要維護一些比較複雜的 Watermark 等,並且在進行預處理後,可能也會帶來一些延遲。

如果直接使用 TiDB 來承載這些負載,當數據寫進來時可以馬上對它進行分析,生成分析報表,及時反饋到平臺或主播,以便及時進行業務上的調整。當然,直播場景的應用目前還是假設,我們期待着 TiDB 在直播場景的落地。

實時風控場景

另外一個場景,以實時風控爲例。部分在線平臺經常會產生交易和轉賬類業務,但新聞中經常報道的詐騙事件也與此相關。事實上,金融或其他交易平臺一般存在風控業務來檢測和規避類似事件的發生。

之前的風控可能存在的問題之一是作案過程非常迅速,以至於風控規則還未觸發但詐騙的流程已經結束了。不僅造成用戶的經濟損失,也影響警察辦案效率。

如果將 TiDB 應用於風控業務中,在違規交易發生的瞬間,可以直接進行分析,觸發風控策略。整個鏈路延遲將極大降低,也有助於相關部門能更快破案。

其他更多 TiDB HTAP 的應用場景也歡迎大家來幫助我們想象,共同暢想 TiDB 的未來。

💡 更多 TiDB、TiKV、TiSpark、TiFlash 技術問題或生態應用可點擊「閱讀原文」,登錄 AskTUG.com ,與更多 TiDB User 隨時隨地交流使用心得~

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/GwMFeKd61TDb7Urqffcauw