HTAP:從小紅書的案例學習NewSQL

在講解小紅書導入HTAP的過程之前我們先來簡單介紹一下小紅書。

小紅書號稱是中國版的Instagram,但除了一般的影音圖文分享等社群功能外,還包含電商營運平台等。根據小紅書的官網,截至2019年為止,活躍用戶已經破億了。

既是社交平台又是電商平台,每天產生的資料量是億級。為了要支援資料驅動決策,這些海量資料必須經過多層的清洗、轉換和聚合,更重要的是,決策的實時性也需要關注。

除此之外,小紅書的應用場景和用戶數都持續增長,因此整個資料基礎建設的擴充性也是一大挑戰。

最終,小紅書採用了TiDB作為他們實時串流的存儲。

為什麼小紅書選擇TiDB?

其實小紅書在2017年就已經在部分專案上採用TiDB了,但直到2018年才開始廣泛使用。

最主要有三個理由如下。

  1. 因應數據驅動決策,會有各種OLAP需求的ad hoc查詢,所以傳統的OLTP資料庫無法支撐這種使用。
  2. 有許多OLAP資料庫雖然能夠很有效率的處理查詢,但是寫入的效能不佳,而TiDB寫入也有優秀的表現。
  3. 在資料集群水平擴充的場景,新實體必須要能夠盡可能快的上線,TiDB透過Raft多數決機制讓所有實體的資料集保持一致。

現在TiDB已經廣泛應用在小紅書的各個領域,包含:

  • 數據倉庫應用
  • 報表分析
  • 大促銷實時dashboard
  • 反欺詐

痛點

一般來說,整個資料架構如下。

flowchart TD
    subgraph Production
        m1[Middleware] --> a1[(MySQL)] & a2[(MySQL)] & a3[(MySQL)]
    end
    subgraph Warehouse
        hadoop[Hadoop Data Lake]
    end
    subgraph Replica
        m2[Middleware] --> a4[(MySQL)] & a5[(MySQL)] & a6[(MySQL)]
    end
    subgraph Application[Applications]
        db[(MySQLs)]
    end
    Production --Ingestion--> Warehouse --> Replica
    Application --T+1 Ingestion--> Warehouse --Pre-aggregation--> Report[(Report MySQL)]

有三個典型的使用案例在這樣的架構下成效不彰。

第一,在生產環境的資料庫上進行ad hoc查詢。為了避免對生產環境資料庫產生負擔,因此必須將生產環境資料庫完整拷貝一份,所有的ad hoc查詢都運行在副本上。

但是生產環境使用的MySQL是有分庫分表的,這在運維上產生極高的複雜度。除了運維難度外,在分庫分表的中間件上要實作聚合,例如group by、join等也會帶來實作上的複雜度,另一方面,在分片MySQL上執行交易也是一大挑戰。

第二,為了能夠更有效率的查詢報表,報表分析會透過預聚合產生,並統一存放在獨立的MySQL以避免直接在Hadoop上查詢的延遲。但正因為是預聚合,無法有效的反應需求變更。更有甚者,一座獨立的MySQL也少了分庫分表的支持,造成擴充性侷限。

最後,在各種應用場景上要做反欺詐,必須要仰賴資料湖中存放的資料,而這些資料並不是實時的,而是T+1寫入。這就讓反欺詐無法在時效內發揮功能,即便偵測到詐欺行為,但損失已經造成了。

解法

要能解決這三個情境的答案就是TiDB。

flowchart TD
    subgraph Production
        m1[Middleware] --> a1[(MySQL)] & a2[(MySQL)] & a3[(MySQL)]
    end
    subgraph Application[Applications]
        db[(MySQLs)]
    end
    subgraph Warehouse
        hadoop[Hadoop Data Lake]
    end
    tidb[(TiDB)]
    Production --Binlog--> tidb 
    Application --> Flink --> tidb
    Warehouse --Pre-aggregation--> tidb

在ad hoc查詢的使用案例,必須要處理兩個痛點,其一是運維難度,另一個是實作複雜度。那麼,只需要把所有的資料都輸入TiDB,維護一個TiDB就好。因為TiDB完全支援MySQL 5.7,所以可以透過MySQL binlog進行同步。

當然,並沒有這麼單純,要把分庫分表的資料倒入TiDB還需要把資料稍微加工過,也就是合併成一張大寬表。所以在同步的串流上需要處理合併和自增主鍵等議題。但最終,所有生產環境資料庫都會與TiDB同步,即使是小紅書的資料量級,這同步延遲也是在1秒內。

接著,同樣的作法也可以套用在報表分析和反欺詐上。

因為有了實時流,所以反欺詐不再會需要T + 1的時間才能反應,可以直接透過Flink SQL處理實時串流。另一方面,報表分析因為有了全部的數據並且可以在單一資料庫上操作而變得更加容易。

新的問題

剛導入TiDB時,小紅書使用的TiDB版本是3.x。

TiDB 3.x還是基於行的儲存引擎,雖然能夠在OLAP達成不錯的成效,但對於大資料量體還是不夠好。更有甚者,所有的場景都使用同一個TiDB集群無法隔離ad hoc查詢和生產環境的實時應用。

但這些問題在升級到TiDB 4.x版後迎刃而解。

原因在於TiDB 4.x版導入了HTAP架構,能夠讓行存引擎以及列存引擎同時存在。新加入的列存引擎稱為TiFlash,與原本的行存引擎TiKV是獨立的且不會互相干擾。當應用程式在對TiKV寫入資料時,透過Raft learner的機制很夠很快將資料同步給TiFlash,藉此讓行存與列存保持一致。

另外,TiDB藉由內部的CBO,能夠在查詢進來的當下就知道這個查詢該使用行存引擎還是列存引擎並自動路由,這大幅減少應用程式的複雜度。

TiDB 4.x版還有一個新機制也對整個數據架構的性能提昇起到幫助:悲觀鎖。在TiDB 3.x版時,只有樂觀鎖,在巨大資料量持續寫入的情境下,很容易發生交易間的衝突。一旦發生交易衝突,就只能在客戶端進行重試,這顯著增加應用程式的開發複雜度。但悲觀鎖可以有效解決這個問題,應用程式的錯誤處理變得更加單純。

結論

事實上,小紅書在做技術選型時也有參考過ClickHouse,而ClickHouse的性能有比TiDB更好一些。但是,ClickHouse相對難以運維。更有甚者,ClickHouse是列存引擎,在資料更新的場景下效能不佳。若是要將「更新」改寫成「添加」,一方面需要大量修改成本,另一方面需要額外的去重邏輯。

因此,最終還是選擇TiDB。

從我的觀點來看,HTAP是未來趨勢,透過合併行存引擎和列存引擎可以覆蓋各種使用場景。僅僅使用一個資料庫,就能處理大資料下的各種需求是很划算的。過去為了能夠支援各種資料產品,必須要在眾多資料庫中不斷技術選型,並仔細考量各種使用案例,一旦有了HTAP,這些複雜度都不再存在。

我個人是很期待看到資料工程能夠逐漸化繁為簡。