實時數倉方案五花八門,實際落地如何選型和構建
01為何需要實時數倉架構
最初企業存儲數據都在數倉中存儲,但是隨著數據量的增大,傳統數據的方案在時效性上和數據維護上變得越來越困難。實時數倉架構應運而生。
然而問題并不是這么簡單,在具體方案落地上實時數倉有很多方案可以選擇,那么面對不同的業務和應用場景我們到底應該選擇哪種技術方案呢?這是困擾好多大數據架構師的問題。
圖1
02數倉如何分層&各層用途
介紹實時數倉前,我們先回顧下離線數倉的分層架構,這將對我們后面理解實時數倉架構設計具有很大幫助。
數倉一般分為:ODS層、DWD層、DWS層和ADS層。這里我會分別展開說一下。這部分內容大家了解數倉中每層數據的特點即可,具體研發中同學們可以根據項目再做深入體會。
圖2
1)ODS層:ODS是數據接入層,所有進入數據的數據首先會接入ODS層。一般來說ODS層的數據是多復雜多樣的。從數據粒度上看ODS層是粒度最細的數據層。
2)DWD層:為數據倉庫層,數據明細層的數據應是經過ODS清洗,轉后的一致的、準確的、干凈的數據。DWD層數據粒度通常和ODS的粒度相同,不同的是該層的數據質量更高,字段更全面等。在數據明細層會保存BI系統中所有的歷史數據,例如保存近10年來的數據。
3)DWS層:數據集市層,該層數據是面向主題來組織數據的,通常是星形或雪花結構的數據。從數據粒度來說,這層的數據是輕度匯總級的數據,已經不存在明細數據了。
4)ADS層:數據應用層,它是完全為了滿足具體的分析需求而構建的數據,也是星形或雪花結構的數據。從數據粒度來說是高度匯總的數據。其匯總的目標主要是按照應用需求進行的。
03數倉分層的必要性
那么數倉為什么要分層,數倉分層后有哪些好處呢?數倉分層是一個比較麻煩且耗費工作成本的一個事情,只有理解了數倉分層到底有哪些好處,我們才能理解數倉分層的必要性。
數倉分層的總體思路是用空間換時間,其目的是通過數倉分層,使得數倉能夠更好地應對需求的變更,和提高數據的穩定性。
1)用空間換時間:通過大量的預處理來提升應用系統的用戶體驗(效率),因此數據倉庫會存在大量冗余的數據。
2)能更好地應對需求的變更:如果不分層的話,如果源業務系統的業務規則發生變化,將會影響整個數據清洗過程,工作量巨大。
3)提高數據處理過程的穩定性:通過數據分層管理可以簡化數據清洗的過程,因為把原來一步的工作分到了多個步驟去完成,相當于把一個復雜的工作拆成了多個簡單的工作,每一層的處理邏輯都相對簡單和容易理解。
這樣我們比較容易保證每一個步驟的正確性,當數據發生錯誤的時候,往往我們只需要局部調整某個步驟即可。
圖3
前面介紹了數倉分層的一些基本理論,這將對我們后面理解實時數倉的各種架構打下一些理論知識基礎。下面為大家梳理下市場上常見的實時數倉方案和對應的應用場景。
04從Lambda架構說起
大部分實時數倉,其實是從Lambda架構演化而來的,因此在介紹實時數倉方案前我們先回顧下Lambda架構。
Lambda架構將數據分為實時數據和離線數據。
針對實時數據使用流式計算引擎進行計算(例如Flink),針對離線數據使用批量計算引擎(例如Spark)計算。然后分別將計算結果存儲在不同的存儲引擎上對外提供數據服務。
圖4
這種架構的優點是離線數據和實時數據各自計算,既能保障實時為業務提供服務,又能保障歷史數據的快速分析。它分別結合了離線計算引擎與流式計算引擎二者的優勢。
但是有一個缺點是離線數據和實時數據的一致性比較難保障,一般在離線數據產生后會使用離線數據清洗實時數據來保障數據的強一致性。
05Kappa架構解決哪些問題
接下來要講的這種架構,它是基于Lambda架構上的優化版本,Kappa架構。這種架構將數據源的數據全部轉換為流式數據,并將計算統一到流式計算引擎上。
這種方式的特點使架構變得更加簡單,但是不足之處是需要保障數據都是實時的數據,如果數據是離線的話也需要轉化為流式數據的架構進行數據處理,具體架構可結合這張圖來看。
圖5
06深入實時數倉架構
實時數倉的查詢需求
在正式討論實時數倉前,我們先看下行業對實時數倉的主要需求,這有助于我們理解實時數倉各種方案設計的初衷,了解它是基于哪些需求應運而生的。
這也將幫助我們從更多維度上思考需求、條件、落地難點等等一些關鍵要素之間如何評估和權衡,最終實現是基于現有條件下的功能如何將其價值最大化。
傳統意義上我們通常將數據處理分為離線的和實時的。對于實時處理場景,我們一般又可以分為兩類:
一類諸如監控報警類、大屏展示類場景要求秒級甚至毫秒級;另一類諸如大部分實時報表的需求通常沒有非常高的時效性要求,一般分鐘級別,比如10分鐘甚至30分鐘以內都可接受。
圖6
基于以上查詢需求,業界常見的實時數倉方案有這幾種。
圖7
目前老的項目大部分還在使用的標準分層體現+流計算+批量計算的方案。未來大家可能都會遷移到標準分層體系+流計算+數據湖,和基于全場景MPP數據庫實現的方案上,我也會重點介紹這兩個方案,也希望大家能夠多花點時間加以理解。
方案 1:Kappa 架構
首先咱們看下Kappa架構,Kappa架構將多源數據(用戶日志,系統日志,BinLog日志)實時地發送到Kafka。
然后通過Flink集群,按照不同的業務構建不同的流式計算任務,對數據進行數據分析和處理,并將計算結果輸出到MySQL/ElasticSearch/HBase/Druid/KUDU等對應的數據源中,最終提供應用進行數據查詢或者多維分析。
圖8
這種方案的好處有二,方案簡單;數據實時。不過有兩個缺點:
一個是用戶每產生一個新的報表需求,都需要開發一個Flink流式計算任務,數據開發的人力成本和時間成本都較高。
第二個是對于每天需要接入近百億的數據平臺,如果要分析近一個月的數據,則需要的Flink集群規模要求很大,且需要將很多計算的中間數據存儲在內存中以便多流Join。
圖9
方案 2:基于標準分層 + 流計算
為了解決方案1中將所有數據放在一個層出現的開發維護成本高等問題,于是出現了基于標準分層+流計算的方案。
接下來咱們看下這種方案,在傳統數倉的分層標準上構建實時數倉,將數據分為ODS、DWD、DWS、ADS層。首先將各種來源的數據接入ODS貼源數據層,再對ODS層的數據使用Flink的實時計算進行過濾、清洗、轉化、關聯等操作,形成針對不同業務主題的DWD數據明細層,并將數據發送到Kafka集群。
之后在DWD基礎上,再使用Flink實時計算進行輕度的匯總操作,形成一定程度上方便查詢的DWS輕度匯總層。最后再面向業務需求,在DWS層基礎上進一步對數據進行組織進入ADS數據應用層,業務在數據應用層的基礎上支持用戶畫像、用戶報表等業務場景。
圖10
這種方案的優點是:各層數據職責清晰。缺點是多個Flink集群維護起來復雜,并且過多的數據駐留在Flink集群內也會增大集群的負載,不支持upset操作,同時Schema維護麻煩。
圖11
方案 3:標準分層體現 + 流計算 + 批量計算
為了解決方案2不支持upset和schema維護復雜等問題。我們在方案2的基礎上加入基于HDFS加 Spark離線的方案。也就是離線數倉和實時數倉并行流轉的方案。
圖12
這種方案帶來的優點是:既支持實時的OLAP查詢,也支持離線的大規模數據分析。但是帶來了問題這樣的幾個問題。
數據質量管理復雜:需要構建一套兼容離線數據和實時數據血緣關系的數據管理體系,本身就是一個復雜的工程問題。離線數據和實時數據Schema統一困難。架構不支持upset。
圖13
方案 4:標準分層體系 + 流計算 + 數據湖
隨著技術的發展,為了解決數據質量管理和upset 問題。出現了流批一體架構,這種架構基于數據湖三劍客 Delta Lake / Hudi / Iceberg 實現 + Spark 實現。
圖14
我們以Iceberg為例介紹下這種方案的架構,從下圖可以看到這方案和前面的方案2很相似,只是在數據存儲層將Kafka換為了Iceberg。
圖15
它有這樣的幾個特點,其中第2、3點,尤為重要,需要特別關注下,這也是這個方案和其他方案的重要差別。
1、在編程上將流計算和批計算統一到同一個SQL引擎上,基于同一個Flink SQL既可以進行流計算,也可以進行批計算。
2、將流計算和批計算的存儲進行了統一,也就是統一到Iceberg/HDFS上,這樣數據的血緣關系的和數據質量體系的建立也變得簡單了。
3、由于存儲層統一,數據的Schema也自然統一起來了,這樣相對流批單獨兩條計算邏輯來說,處理邏輯和元數據管理的邏輯都得到了統一。
4、數據中間的各層(ODS、DWD、DWS、ADS)數據,都支持OLAP的實時查詢。
圖16
那么為什么 Iceberg 能承擔起實時數倉的方案呢,主要原因是它解決了長久以來流批統一時的這些難題:
1、同時支持流式寫入和增量拉取。
2、解決小文件多的問題。數據湖實現了相關合并小文件的接口,Spark / Flink上層引擎可以周期性地調用接口進行小文件合并。
3、支持批量以及流式的 Upsert(Delete) 功能。批量Upsert / Delete功能主要用于離線數據修正。流式upsert場景前面介紹了,主要是流處理場景下經過窗口時間聚合之后有延遲數據到來的話會有更新的需求。這類需求是需要一個可以支持更新的存儲系統的,而離線數倉做更新的話需要全量數據覆蓋,這也是離線數倉做不到實時的關鍵原因之一,數據湖是需要解決掉這個問題的。
4、同時 Iceberg 還支持比較完整的OLAP生態。比如支持Hive / Spark / Presto / Impala 等 OLAP 查詢引擎,提供高效的多維聚合查詢性能。
圖17
Iceberg 實戰
上面介紹了基于Iceberg的標準分層體系+流計算+數據湖的架構,下面咱們從實戰角度看下Iceberg如何使用。
iceberg寫入流式數據代碼實現如下:
data.writeStream.format("iceberg") .outputMode("append") .trigger(Trigger.ProcessingTime(1, TimeUnit.MINUTES)).option("data_path", tableIdentifier) .option("checkpointLocation", checkpointPath) .start()br
上述代碼會將data_path下的數據以流的形式,實時加入到系統中進行計算。
iceberg數據過濾代碼實現如下:
Table table = Actions.forTable(table).rewriteDataFiles() .filter(Expressions.equal("date", "2022-03-18")) .targetSizeInBytes(500 * 1024 * 1024) // 500 MB .execute();br
上述代碼過濾出date為2022-03-18的數據。
方案 5:基于全場景MPP數據庫實現
前面的四種方案,是基于數倉方案的優化。方案仍然屬于比較復雜的,如果我能提供一個數據庫既能滿足海量數據的存儲,也能實現快速分析,那豈不是很方便。這時候便出現了以StartRocks和ClickHouse為代表的全場景MPP數據庫。
1、基于Darios或者ClickHouse構建實時數倉。來看下具體的實現方式:將數據源上的實時數據直接寫入消費服務。
2、對于數據源為離線文件的情況有兩種處理方式,一種是將文件轉為流式數據寫入Kafka,另外一種情況是直接將文件通過SQL導入ClickHouse集群。
3、ClickHouse接入Kafka消息并將數據寫入對應的原始表,基于原始表可以構建物化視圖、Project等實現數據聚合和統計分析。
4、應用服務基于ClickHouse數據對外提供BI、統計報表、告警規則等服務。
圖18
07具體選型建議
對于這5種方案,在具體選型中,我們要根據具體業務需求、團隊規模等進行技術方案選型。
說到這兒,我有這樣的幾點具體建議,希望或多或少可以給你提供一些可供參考、借鑒的新視角或者新思路。
(1)對于業務簡單,且以流式數據為主數據流的大數據架構可以采用Kappa架構。
(2)如果業務以流計算為主,對數據分層,數據權限,多主題數據要求比較高,建議使用方案2的基于標準分層+流計算。
(3)如果業務的流數據是批數據都比較多,且流數據和批數據直接的關聯性不大,建議使用方案3的標準分層體現+流計算+批量計算。這種情況下分別能發揮流式計算和批量計算各自的優勢。
圖19
(4)方案4是一個比較完善的數倉方案,要支持更大規模的和復雜的應用場景,建議大數據研發人員在20以上的團隊,可以重點考慮。
(5)對于大數據研發組團隊為10人左右,要維護像方案2、3、4那樣以ODS、DWD、DWS、ADS數據分層的方式進行實時數倉建設的話,就需要投入更多的資源。建議使用方案5一站式實現簡單的實時數倉。
08大廠方案分享
介紹了這么多實時數倉方案,那么很多小伙伴會問了,大廠到底用的那種方案呢?其實每個大廠根據自己業務特點的不同,也會選擇不同的解決方案。下面為大家簡要分享下OPPO、滴滴和比特大陸的方案,以便大家能夠更好地理解這篇分享中五種架構的具體落地。
不過具體架構細節我不會進行過多的介紹,有了前面的內容基礎,相信大家再通過架構圖就能很快了解每個架構的特點。這里只是希望大家能夠通過大廠的經驗,明白他們架構設計的初衷和要解決的具體問題,同時也給我們的架構設計提供一些思路。
舉例來說,OPPO的實時計算平臺架構,其方案其實類似于方案2的基于標準分層+流計算。
圖20
滴滴的大數據平臺架構是這樣的,它的方案其實類似于方案2的基于標準分層+流計算。
圖21
再結合比特大陸的方案看下,其方案類型方案3的標準分層體現+流計算+批量計算,同時也引入了ClickHouse,可以看到比特大陸的數據方案是很復雜的。
圖22
09結語&延伸思考
本文介紹了市面上常見實時數倉方案,并對不同方案的優缺點進行了介紹。在使用過程中我們需要根據自己的業務場景選擇合適的架構。
另外想說明的是實時數倉方案并不是“搬過來”,而是根據業務“演化來”的,具體設計的時候需要根據自身業務情況,找到最適合自己當下的實時數倉架構。
關于作者,王磊,阿里云 MVP,華院計算技術總監。