首頁>技術>

作者介紹:張億皓,小紅書基礎技術部資深開發工程師,負責資料庫相關的研發和落地工作。

TiDB 在小紅書業務場景的應用簡介

2017 年,小紅書已經開始在生產業務中使用 TiDB ,真正成體系的去做 TiDB 的落地是在 2018 年,為什麼要選擇使用 TiDB ?

當今很多公司的業務都是資料驅動,面對小紅書 APP 每天數以億計的資料,我們希望有一個數據庫能夠提供以下特性:

第一,資料使用的多樣性,有時候需要在資料庫做一個 TP 的短查詢,做一些很高的寫入,有時候又希望做一些聚合分析,能夠展現彙總統計的結果, TiDB 的 HTAP 架構正好滿足了多樣性的需求。

第二,更高的時效性,我們知道有很多資料分析的引擎雖然計算很快,但是對於實時分析的支援能力比較弱,TiDB 可以提供更高的時效性。

第三,TiDB 基於 Raft 的擴充套件性,小紅書 APP 每天的資料都是上億級別,單點的叢集總有一天會被打滿,會被打爆,我們就期望能有一個擴充套件性極佳且擴容方便的資料庫,TiDB 非常契合,所以我們選擇了 TiDB。

TiDB 目前在小紅書的應用涵蓋報表分析、大促實時大屏、物流倉儲、數倉應用、電商資料中臺、內容安全稽核等多個業務場景。6 月 6 日是小紅書的週年慶大促,需要展現一些實時的銷量、店家成交總額排名、總銷量等資訊,這個實時大屏的應用後面連線的就是 TiDB。

TiDB 在這些業務當中給我們解決了哪些問題?我從這些業務中挑選了三個非常典型的應用場景來跟大家分享。

資料報表:資料報表其實很好理解,分析師經常需要看一些資料,比如這周的走勢,看一些銷量情況,看一些使用者增長情況,看同比與環比資料。線上業務庫的實時查詢:比如 300 億行的一個表,MySQL 肯定存不下,需要走分庫分表的邏輯,而且希望在做查詢或者分析的時候不能對線上業務產生影響,解決線上分庫分表 MySQL 的查詢問題。反欺詐資料分析:所謂反欺詐舉個例子像黃牛薅羊毛,小紅書的電商平臺定期會發一些優惠券,黃牛就最喜歡薅這些優惠券,我們能否在短時間內抓到這些黑產行為,將他們捕捉下來進行分析和阻攔。傳統 MySQL 與數倉方案的侷限

在沒有 TiDB 的時候,我們怎麼做?如上圖所示,從業務邏輯上來劃分,從上到下是業務線上層、數倉離線層和資料服務層。

首先在資料報表場景,採用 Hadoop 數倉對資料做一些預聚合,然後把這些高維度的資料簡單聚合一下放到 MySQL 裡面再做查詢。對於資料報表,會把 Hadoop 裡面的資料通過 Hive 以 T+1 的形式每天做一些預聚合放到 MySQL 裡面,再搭建一些 BI 系統進行圖形展示化的報表查詢,分析師就可以看到他們定製化的一些報表。但是隨著業務的快速增長,報表的形式變得更加多種多樣,MySQL 的擴充套件性也是一個比較頭疼的問題,如果單純地增加一些 MySQL 的節點,到最後就會變成我們如何管理那麼多 MySQL 節點的問題,搞過運維的同學都知道,這是一件比較煩瑣的事情。

再來看線上的 MySQL 分庫分表場景,我們要在上面做資料查詢,又不能影響線上庫,所以只能去查從庫,這個從庫當然也是一個分庫分表的場景。這裡產生了一系列問題:首先還是運維的問題,分庫分表 MySQL 那麼多節點怎麼管?怎麼擴容?分片是不是要重新去做 Sharding?如何保證一致性?縮容怎麼縮?元資訊怎麼管理?這是運維上面的複雜度。除此之外,我覺得有必要提的一點,比如說線上的一個分庫分表 MySQL,我在上面想做一個事務,分庫分表的中介軟體方便做嗎?如果我還想做一個 JOIN,甚至我還想做一個 Group by 聚合查詢,分庫分表中介軟體方便做嗎?可能可以做,但都不會很簡單,所以我們需要有一個能夠方便地做比較複雜分散式查詢的方案。

第三在反欺詐資料分析場景,我們比較關注時效性。在 TiDB 之前對於後端的一些打點資料,我們這些資料寫到數倉裡面,等到 T+1 第二天的時候,業務方才能查到上面的資料,這樣 T+1 的時效性就比較差了。黃牛薅羊毛是一個很快的事情,到第二天可能直接薅完了你也沒辦法,所以非常希望最好能在半分鐘、十秒鐘,甚至秒級別,就能看到發出優惠券的詳細使用情況。

引入 TiDB HTAP 方案,提升全場景資料服務能力

基於以上場景的種種挑戰,我們引入了 TiDB 3.0 HTAP 方案,來看看新的業務架構,如下圖,我們看到資料服務層採用 TiDB 就可以提供業務所需的全部資料服務。

我們重新梳理一下引入 TiDB 之後的三個業務場景。

在資料報表場景,直接用 TiDB 直接替換 MySQL ,解決了隨著業務增長 MySQL 擴容複雜的問題。我覺得能實現無縫切換最重要的原因是 TiDB 一開始就支援 MySQL 協議,這是我覺得 TiDB 設計上非常牛的一點,很聰明的一點。前端的 BI 工具不用再開發一個所謂的 TiDB 驅動,直接用 MySQL 驅動就可以。在擴容層面,這是 TiDB 最擅長的事情,可以直接加個節點,資料自動做好重新均衡,非常方便。

在分庫分表的 MySQL 場景,分庫分表怎麼做查詢?我們造了一條實時流,把 MySQL 的資料通過 Binlog 實時寫到 TiDB 裡面,同步的延遲在一秒鐘以內。實時流不僅僅是一個簡單的資料同步,還做了一個事情就是合庫,什麼叫合庫?原來線上分了一萬個表,分表是因為 MySQL 存不下,現在一個 TiDB 叢集是能夠存下的,就沒有必要分表了。實時流寫到 TiDB 裡面的同時,還把這一萬張分表合成了一張大表,合的過程中可能還要處理一些特殊問題,比如說原來的自增主鍵怎麼搞?自增主鍵合起來的時候是不是有問題?可能要做一些資料轉換,有一些資料要做格式或者對映之類的資料處理,總之在實時流裡面都把這些事情處理好,最後我們看到一張大表,就沒有分庫分表這件事情。在 TiDB 上面再做一些查詢,不影響主庫,TiDB 實際上作為一個 MySQL 的大從庫,如果想做一個事務,也沒問題,TiDB 支援事務,想做一個 JOIN,想做一個聚合,TiDB 都能夠支援這類操作,最後就是一張大表呈現在 TiDB 裡面。

TiDB 4.0 HTAP 方案的應用效果

通過引入 TiDB,我們在以上三個典型業務場景上解決了遇到的各種問題。這個方案有沒有不足?其實也是有的,如果 3.0 沒有不足的話,可能就不會誕生今天的 4.0 。我們使用下來的感受主要是 TiDB 3.0 在 OLAP 分析這一塊能力稍有些不足,TiKV 是一個基於行存的資料庫,去跟一些專門做分析的列存引擎去比較,其實是沒有可比性的。TiDB 如何解決這個問題?是不是 TiDB 引入一個列存引擎就可以?到了 4.0 的時候,TiDB 帶著 TiFlash 這麼一個列存引擎來到了我們面前。

TiFlash 的設計有幾點我覺得非常棒:首先,作為一個列存引擎 TiFlash 能夠與 TiKV 共存,不是說只能選列存,只能選行存,兩個可以同時存在,既然能同時存在,中間這個行存到列存資料的複製和轉換怎麼做?是不是需要再搭一條複製流去做?不用,TiDB 都幫我們做好了,通過 Raft Learner 複製機制直接採用一個較低延遲的方式把資料全部同步到 TiFlash 裡面。從查詢端來看,是否需要做一些特殊的處理讓 TiFlash 走列存引擎呢?答案是都不需要,TiDB 有一個 CBO 執行計劃的自動路由,可以知道這條 SQL 是 TiFlash 掃全表比較好還是走 TiKV 的索引查詢比較快,可以幫我規劃好。引入 TiFlash 的運維成本是非常低的,我要做的事情就是申請機器把 TiFlash 部署上去,然後就結束了,資料自動同步過去,查詢自動路由過去,什麼事情都不用管。

我們也對 TiFlash 做了測試,拿物流場景作為例子,我們對其中的 393 條生產查詢進行評估,上圖的縱軸是 TiFlash 的效能提升,從聚合查詢來看,類似於 Group by、SUM 這些聚合查詢,大概有三到十倍的效能提升,平均時間減少 68% 左右。如果是非聚合查詢,平均時間減少 4% 左右,非聚合查詢基本上都命中了 TiKV 的索引,沒有走 TiFlash 的列存。

TiDB 4.0 還給我們帶來悲觀鎖,在物流場景很多表需要 JOIN ,JOIN 其實是代價比較高的一件事情。為了避免 JOIN,我們會把這些要 JOIN 的表提前給拼成一張大寬表。舉個例子,我把三張表拼成一張大寬表,那就有三個流就會同時更新大寬表,更新同一行,原來的 TiDB 3.0 是樂觀鎖的機制,就會產生事務衝突,對於客戶端的重試來說是不太友好。TiDB 4.0 有了悲觀鎖,很好地解決了這個問題。

TiFlash 與 ClickHouse 怎麼選?

最後說一下 TiFlash 跟其他方案的對比,拿大家比較熟悉的 ClickHouse 列存引擎做個比較,ClickHouse 其實單從計算效能來說,確實是比 TiFlash 要快一點。為什麼某一些場景我們還是選擇 TiFlash 呢?因為 ClickHouse 有一些問題,比如說 ClickHouse 的叢集模式運維起來比較複雜,對資料更新的支援也比較弱,因為很多業務是事務型的,有很多更新需求,而 ClickHouse 更新的效能比較差,如果要改成 Append、Insert 這個邏輯,業務側就要做大量的改動,例如資料要做去重之類的事情,很多場景下為了支援高頻率的更新我們就選擇了 TiFlash。

本文整理自張億皓在 TiDB DevCon 2020 上的演講。

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 在SpringBoot中驗證使用者上傳的圖片資源