基於 Lambda 架構的實時電商數倉建設經驗分享

導讀 文章分享了某電商平臺離線數倉、實時數倉、數據應用等方面的實踐經驗。

分享嘉賓|王春波 高級數倉工程師 《Doris 實時數倉實戰》作者

文字校對|志明與數據

出品社區|DataFun


01

背景介紹

電商平臺以 APP 作爲載體,最重要的數據就是以訂單爲核心的結構化數據和以日誌流爲核心的半結構化數據,這也互聯網業務最典型的應用場景。

訂單業務包括下單、支付、發貨、物流、評價、退貨等業務流程,但是都可以通過 order_id 串聯起來,數據保存在關係型數據庫中。我們這邊通過 MySQL 分庫分表方案承載訂單相關的業務數據,目前積累了自系統上線以來的 1.5 億訂單,目前日增長訂單數爲 10 萬左右。

點擊流數據則是 APP 上所有用戶的操作行爲埋點記錄數據,是源源不斷產生的半結構化數據。由於前期對 APP 埋點和日誌流數據做過治理,所以目前數據格式比較規範,數據輸出也比較穩定。點擊流數據包括 30 + 固定字段和一個擴展 json 字段組成,固定字段包括設備信息、會話信息、用戶信息、網絡信息、埋點編碼等,擴展 json 字段內容則根據實際的頁面情況生成,不同的頁面或者埋點對應的擴展信息不同。點擊流數據每日增量在 10 億左右,ORC 格式佔用存儲在 1.16T 左右。

筆者接手電商數倉項目時,恰逢公司推進數據治理項目,準備重建電商數倉。在我接手之前,公司數倉按照不同的業務模塊劃分不同的數據集市,電商業務有專門的電商集市,但是內部數據加工邏輯比較複雜、沒有明確的數據分層和清晰的數據處理邏輯,基本上是面向需求開發,重複邏輯比較多,數據一致性差。我接手電商數倉以後,按照標準的數倉分層重構了電商數倉,同步產出實時數據,滿足了實時數據看板、自助分析數據集、雙十一大屏、每日業績播報等多個數據應用。恰逢最近經歷了新一輪 618 大促的考驗,因此予以總結,形成經驗分享給其他數倉開發的同行。

02

技術選型

數據中臺作爲公司統一的數據平臺,承載着全公司大數據集羣平臺的基礎能力,包括離線集羣 Hive、Hdfs、Yarn、Spark 和 Presto,實時集羣 Flink、ClickHouse,以及相關工具如自助分析工具 QuickBI、調度系統、畫像系統、監控告警系統、基於 Zepplin 的統一數據查詢平臺等。

公司的離線大數據有 400 多臺服務器,基於 Yarn 框架進行統一的資源管理,計算資源分爲離線計算、實時計算、實時查詢等不同的資源隊列,其中離線計算目前以 Spark 爲主,部分高優先級的任務或者時效性較高的任務已經切換到內部改造過的 Presto 計算引擎。目前公司大數據平臺上運行的離線數據處理任務主要分爲 MySQL2Hive 數據採集、Hive2Hive 數據加工、Hive2MySQL 數據分發和 Hive2CK 數據分發四種類型,任務數分別是 1.0W、1.2W、6K、500。

實時數據處理分爲實時數據採集、實時數據計算和實時數據查詢三個方面。實時數據採集通過自動化配置,直接寫入 Hive 數倉的 rt_ods 庫,目前有接近 1000 張表;實時數據計算目前主要是交給 Flink 完成,目前線上運行的大約 500 個任務;實時數據查詢包括 MySQL 和 Clickhouse,接入數據量不確定。

早期的數據結果查詢都是基於 MySQL 分庫分表來實現,2021 年底開始引入 ClickHouse 作爲交互式查詢引擎。選擇 ClickHouse 的原因主要是由於查詢性能快、查詢穩定,只要設置合理的分區,單表數據量可以達到百億甚至千億級別。目前公司在多個業務線引入了 ClickHouse 集羣,在大數據線,ClickHouse 集羣主要替代 MySQL 分庫分表方案,來實現數據的快速實時查詢。大數據線的 ClickHouse 集羣由 28 臺節點組成 14 主 * 2 副本集羣,每臺節點 84 核 CPU+256G 內存。

03

電商離線數倉

離線數倉總體上分爲三層,即 ODS、DW 和 DM 層。

ODS 層也叫數據採集層,數據來源於源系統,保留源系統概貌,爲上游邏輯層提供原始數據,隔離對源系統的影響。我們這邊分爲 SNAP、ODS、History 三個數據庫,分別存放快照數據、增量追加數據和全量歷史快照數據。對於全量採集的數據,直接抽取到 SNAP 庫;對於增量採集的數據默認會按照修改日期抽取最近一天新增或者修改的數據,按日分區存入 ODS 庫,然後按照庫表主鍵合併去重寫入 SNAP 庫;對於有保存歷史快照數據需求的表,我們還會將歷史快照複製一份按日保存到 History 庫。

DW 層也叫數據倉庫層,我們分爲 DIM、DWD 和 DWS 三個庫。

DIM 庫用於保存公共維度數據,例如商品、商戶、供應商、用戶基礎信息等。

DWD 層也叫明細模型層,數據來源於 ODS 層,根據上游提供原始數據,劃分數據主題,對 ODS 層數據進行關聯整合。DWD 層用於保存業務明細數據,只做簡單的數據加工和多表關聯,得到按照主題域和數據域劃分的明細數據表。

DWS 層也叫輕度彙總層,數據主要來源於 DWD 層,以指標加工爲核心,按照維度建模的思路,加工一致性指標和一致性維度。DWS 層也包括寬表層,所以 DWS 通常可以劃分爲兩步進行數據加工,第一步聚焦於指標計算,統一加工業務指標,第二步關聯維度信息,形成大寬表。有時候會把大寬表叫做 DWT 層,但是我們這邊沒有嚴格的區分。DWS 層的寬表通常都是同步到 ClickHouse,用於自助分析或者固定報表查詢。

DM 層也叫集市層或者數據應用層,數據來源主要來自 DWS 層,可按業務和應用主題分類,滿足特定應用查詢。DM 數據主要保存在 Hive 數倉的 DM 庫和對接數據應用的 MySQL 庫、ClickHouse 庫。對於數據量超過千萬的明細數據分析,數據會直接同步到 ClickHouse 庫;對於百萬級以下的數據,則直接保存到 MySQL 數據庫。此外,還有應用層的用戶畫像數據保存在 HBase。DM 層的大部分數據直接來源於 DWS,也有有些數據是在 DWS 層的基礎上進行二次加工,包括簡單彙總、計算同環比、多維彙總等,先寫入 DM 層,再同步到外部數據庫。

具體到電商數倉模塊,我們主要構建了以下幾個模型表:

當然,實際項目上設計和建設的模型遠不止這幾張表,我們還針對售後訂單創建單獨的表、根據埋點業務的運營位曝光和點擊計算下單成交率、根據商品的推薦計算推薦模型的有效性,根據搜索的結果及點擊計算不同入口的搜索成交情況等等。但是項目主要的核心的訂單和點擊數據流就是這 10 張表,其中商品標籤表和用戶標籤表還作爲電商業務商品畫像和用戶畫像的基礎數據來源表,提供畫像標籤的統一出口。

04

電商實時數倉

在離線數據加工的基礎上,業務用戶提出來實時數據的需求,主要包括企業微信業績播報機器人和實時交易看板、實時成交監控、雙十一大屏等。

最開始開發的是企業微信業績播報機器人需求,每小時彙總一次當日成交數據,並和歷史成交進行對比,將數據寫入 MySQL,再由 Java 程序讀取數據,按照指定的數據格式播報到企業微信羣。

針對這個業務場景,我們按照典型的 Lambda 架構設計,複用公司的 Kafka 寫入 Hive 數據組件,通過配置化實現關鍵業務數據自動同步到 Hive 的 rt_ods 數據庫。然後我們通過 Presto 計算引擎簡化訂單業務的加工邏輯,只計算關鍵成交指標,加工到 DWS,並和離線數據加工的 DWS 層數據進行合併去重,保留最近 13 個月的訂單明細。點擊流數據不需去重,只保留當日、上月環期和去年同期三個日期的明細數據,並加工好關鍵指標,保留明細數據。最後一步是加工計算本期、同期、環期的不同指標,並分別按照商品維度和用戶維度進行數據彙總,寫入 MySQL 供 JAVA 應用查詢。

第一代實時數倉架構

將實時播報任務串聯成工作流,按照一小時一次的頻率執行,截圖如下:

實時播報滿足了業務用戶跟蹤業績進展的需求,但是時效性比較差,無法滿足實時成交監控、實時看板和大促大屏的需求,於是我們又進一步開發了新的實時鏈路,即 Flink 實時鏈路。

第二代實時數倉架構

Flink 實時鏈路主要由兩個 FlinkSQL 任務組成,分別讀取訂單 CDC 日誌流數據和點擊埋點日誌流數據,在進行簡單的數據轉換以後關聯離線加工的商品信息表(定時同步到 HBase,全量 1600 萬)獲取商品維度然後寫入 Clickhouse。在電商業務的多維分析中,最主要的維度就是商品維度和用戶維度,其中商品維度包括商戶信息、商品層級信息、商品規格信息、商品業務歸屬、商品價格和進貨渠道等,用戶維度包括用戶註冊信息、用戶基本屬性、用戶成交記錄和用戶衍生標籤。在我們的業務場景中,商品維度是千萬級別,用戶維度是億級別,經過測試,在實時點擊流中,由於數據流量比較大,關聯用戶信息會出現查詢超時導致關聯不上的場景,因爲我們砍掉了實時數據的用戶維度,而選擇在 ClickHouse 進行結果數據查詢時再利用 Local Join 的優勢來關聯用戶維度。實時加工數據在 ClickHouse 中設置的 TTL 時間是 3 天,即僅保留最近三天的實時數據。

Flink 實時鏈路的關鍵在於 ClickHouse, 我們首先將離線加工好的訂單寬表、點擊流寬表和用戶維度信息表在每天跑批完成以後同步到 Clickhouse(其中訂單寬表是每日全量同步最近三個自然年的數據,點擊流每日增量同步昨日數據),然後通過一個視圖來合併離線數據和實時數據,對外提供純實時的一致性數據結果。

在 ClickHouse 這邊主要處理邏輯有以下幾點:

  1. 離線數據取下單(點擊)日期小於當日的數據,實時數據取離線數據沒有的下單(點擊)日期對應的數據。這是爲了避免在凌晨時離線數據還沒有跑出來,導致查詢昨日沒有數據的情況。

  2. 實時數據關聯用戶維度,取用戶註冊時間和用戶引流渠道等信息。基於 ClickHouse 的特性,我們將所有接入的數據默認按照 fuid 的 hash 值進行數據分片,確保同一個用戶的訂單、點擊數據和用戶維度數據在同一個數據分片上,既可以實現 Join 的本地化,又能減少用戶數去重計算的資源消耗。爲了強制 join 在本地進行,我們會直接在 SQL 中使用右表的 local 表進行關聯。

  3. 根據訂單和點擊流的不同特點,承接訂單實時數據的表我們採用 ReplicatedReplacingMergeTree 引擎表,點擊流實時數據表則採用 ReplicatedMergeTree 引擎表。在使用訂單實時數據時,我們會在表名後增加 final 關鍵字,確保讀取到最新的數據。

Flink 實時數據由於實時性高、數據完整度高並且基本上都是明細數據,可以滿足各種業務場景,因此在這個數據集基礎上我們創建實時成交看板、實時監控預警和大促大屏等應用需求。下一部分,我們將具體展開數據應用場景的方案解讀。

05

數據應用

在電商數倉的基礎上,我們構建了自助分析、固定報表、企業微信播報、標籤畫像、大促大屏等多個數據應用。其中,自助分析和固定報表都是基於 QuickBI 實現的,企業微信播報是 Java 程序,標籤畫像是自研系統,大促大屏是基於 VUE 開發的 Web 應用。

首先是自助分析,我們基於訂單數據和點擊流數據各自構建了一個寬表並同步到 ClickHouse,不同的類目運營用戶和數據產品都可以基於這兩個自主數據構建自己的看板,並分享給其他同事。自助分析數據集根據用戶的需求還在不停的追加字段,完成各種實驗場景分析、用戶成交分析和經營利潤分析。訂單寬表已經擴充到了 256 個字段,還有不少的用戶標籤和商品標籤封裝在 fuser_label_json 和 fsku_label_json 兩個 json 字段中。目前,訂單自助數據集是使用用戶最多,應用最廣泛的數據集。

其次是固定報表。在自助分析數據集的基礎上,我們構建了業務經營日報、KPI 進度監控等固定報表,滿足管理層經營數據分析需求。這些報表主要在同環比、日周月年等維度上有一些特殊處理,導致需要做一些定製化開發,所以由我們數倉完成。

第三個應用是前面提到的企業微信播報,這裏只截取其中一部分內容展現。企業微信從早上 9 點到晚上 24 點,每小時播報一次。其中最難的是 24 點以後的那次播報,需要做很多特殊處理,才能實現。

第四個應用是標籤畫像。我們的標籤畫像系統支持用戶和商品兩個維度,在標籤系統定義的基礎標籤都會換成成 SparkSQL,加工以後同步到 HBase。衍生標籤在基礎標籤的基礎上組合定義,結果數據也會加工到 HBase。

標籤系統提供單個用戶查詢標籤值和標籤組合圈選用戶兩個功能,前者用於在線接口調用,後者用於導出用戶進行分析或者廣告投放。

第五個應用是大促大屏。我們參照阿里雙十一大屏,構建了實時大促大屏,包括實時成交額、大促期間累計成交額、用戶分類成交金額及本同期對比、商品分類成交金額及本同期對比。

06

後續演進和流批一體探索

目前第二代實時架構已經穩定運行了接近一年時間,做過一些修修補補的微調,但是整體架構沒有變動過。這中間遇到的痛點主要有:

①離線數據跑完以後,昨日的實時成交數據會提高,但是第三天又會下降。這是因爲離線數據是以 12 點作爲快照時間點計算的,後面的成交或者退款數據在實時裏面可以體現,但是離線需要到第三天才能體現。這個問題在大促期間暴露比較明顯。

②商品維度數據一天只更新一次,導致當日上線的商品在統計時丟失,或者商品層級調整不能實時體現到看板中。

③流處理 SQL 封裝在 Flink 管理平臺中,批處理 SQL 封裝在調度平臺,導致兩邊容易出現邏輯不一致的情況。

④點擊流數據積累過多以後,ClickHouse 存儲和查詢性能出現瓶頸,但是集羣擴容又比較困難,導致我們點擊流數據只保留最近半年數據並且一次最多查詢一個月的數據,用戶滿意度降低。

⑤維度變更導致點擊流數據統計出現異常,比如商品類目、用戶分類等。

面對以上這些問題,我們開啓了第三代實時架構的設計和驗證之路。第三代實時架構我們引入了基於數據湖的流批一體模式和基於 OLAP 數據庫的多維實時數據查詢模式。在數據湖方面,經過多方對比,最終選擇 Hudi 作爲數據湖底座,繼續沿用 Flink 進行流式數據加工,選擇 Doris 作爲查詢引擎。

選擇 Hudi 的原因是:

①數據湖技術中 Hudi 目前最成熟,並且有很多案例分享;

②Hudi 支持流式數據寫入和流式數據讀取,可以滿足我們保存中間過程數據的需求;

③Hudi 支持索引,可以更快的檢索數據。

④Hudi 和當前的 HDFS 存儲底座結合更好。

選擇 Doris 的原因有很多,例如支持多表關聯、方便擴展、支持多種數據模型、支持多種索引機制和查詢優化,還支持存算分離遷移歷史數據到對象存儲,直接查詢外部數據源。更詳細的關於 Doris 的特點和使用方法,歡迎購買筆者撰寫的《Doris 實時數倉實戰》一書。有了 Doris,最大的好處是我們可以做到維度解耦,可以在查詢的時候才進行關聯,一方面減少了數據存儲空間佔用,另一方面避免了歷史維度不一致的情況。

總體來說,我們的第三代實時數倉架構如下:

採用這種流批一體的架構,可以解決流數據和實時數據切換時成交金額回退的情況;同時保留中間過程數據,可以邏輯變更導致需要回溯歷史重算的情況;引入獨立的 OLAP 查詢引擎,可以解決查詢的性能問題和多表關聯問題。

雖然理想狀態下,所有數據都通過 Flink 流式進行加工,但是經過調研,我們還是有一些數據的邏輯無法做到純流處理,比如用戶下單時是新用戶還是老用戶,所以我們還是保留了批處理的鏈路,批處理的數據通過 Spark 加工完成以後,直接寫入 Doris 更新主鍵模型的部分列。

目前這個方案已經驗證完成,正在進行配套平臺的搭建和持續運行監控,預計 Q4 會全面鋪開應用。

相比第一代架構和第二代架構,我們最大的特點就是用 Doris 代替了 ClickHouse。雖然 ClickHouse 快並且穩定,但是其使用門檻較高、擴展性較差,元數據用 ZooKeeper 管理,在我們這邊已經達到瓶頸,並且在實時數據高頻寫入的場景容易出現元數據管理異常導致數據寫入失敗的情況。

Apache Doris 作爲一款國產開源數據庫軟件,不僅實現了向量化引擎、存算分離、Merge on Write 等前沿功能,還開創性的融合了數據分桶、行列混合存儲、多種索引支持、多種數據模型等功能到 MPP 數據庫中,是 OLAP 和數據倉庫領域冉冉升起的新星。《Doris 實時數倉實戰》一書囊括 Doris 的基本操作、架構設計、進階使用、運維管理、拓展應用等各方面的內容,還有大量的具體項目實踐經驗分析,非常適合想使用 Doris 進行數倉開發的小夥伴學習。目前 Doris 社區非常活躍,功能還在不斷迭代和演化中,Doris 背後的商業公司飛輪科技也給予了 Doris 發展非常大的助力,Apache Doris 一定能成爲一款具有全球影響力的開源產品。

分享嘉賓

王春波

某互聯網公司 高級數倉工程師

現就職於一家互聯網公司,任高級數倉工程師,負責電商數倉項目;在銀行業、零售行業深耕多年,參與和負責過多家銀行、頭部零售服裝企業數據倉庫實施項目。《數據中臺研習社》號主,《高效使用 Greenplum:入門、進階與數據中臺》和《Doris 實時數倉實戰》作者。

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