Linked大佬Jay Kreps曾發表過一篇 部落格 ,簡單闡述了他對資料倉庫架構設計的一些想法。從Lambda架構的缺點到提出基于實時資料流的Kappa架構。本文将在Kappa架構基礎上,進一步談數倉架構設計。
什麼是Lambda架構?

借用Jay Kreps的一張圖來看,Lambda架構主要由這幾部分構成:資料源(Kafka),資料處理(Storm,Hadoop),服務資料庫(Serving DB)。其中資料源和服務資料庫是整個架構資料的入口和出口。資料處理則是分為在線上處理和離線處理兩部分。
當資料通過kafka消息中間件,進入Lambda架構後,會同時進入離線處理(Hadoop)和實時處理(Storm)兩個處理子產品。離線處理進行批計算,将大量T+1的資料進行彙總。而實時處理則是進行流處理或者是微批處理,計算秒級、分鐘級的結果。最後都錄入到服務資料庫(Serving DB)中進行彙總,暴露給上層服務調用。
Lambda架構的好處是:架構簡單,很好的結合了離線批處理和實時流處理的優點,穩定且實時計算成本可控。
此外,它對資料訂正也很友好。如果後期資料統計口徑變更,重新運作離線任務,則可以很快的将曆史資料訂正為最新的口徑。
然而,Lambda也有很多問題。
其中Jay Kreps認為最突出的問題就是需要同時維護實時處理和離線處理兩套代碼的同時還要保證兩套處理結果保持一緻。這無疑是非常讓人頭疼的。
什麼是Kappa架構
Jay Kreps認為通過非常,非常快地增加并行度和重播曆史來處理重新處理實時資料,避免在實時資料處理系統上再“粘粘”一個離線資料處理系統。于是,他提出了這樣的架構:
Kafka或者其他消息中間件,具備保留多日資料的能力。正常情況下kafka都是吐出實時資料,經過實時處理系統,進入服務資料庫(Serving DB)。
當系統需要資料訂正時,重放消息,修正實時處理代碼,擴充實時處理系統的并發度,快速回溯過去曆史資料。
這樣的架構簡單,避免了維護兩套系統還需要保持結果一緻的問題,也很好解決了資料訂正問題。
但它也有它的問題:
1、消息中間件緩存的資料量和回溯資料有性能瓶頸。通常算法需要過去180天的資料,如果都存在消息中間件,無疑有非常大的壓力。同時,一次性回溯訂正180天級别的資料,對實時計算的資源消耗也非常大。
2、在實時資料處理時,遇到大量不同的實時流進行關聯時,非常依賴實時計算系統的能力,很可能因為資料流先後順序問題,導緻資料丢失。
例如:一個消費者在淘寶網上搜尋商品。正常來說,搜尋結果裡,商品曝光資料應該早于使用者點選資料産出。然而因為可能會因為系統延遲,導緻相同商品的曝光資料晚于點選資料進入實時處理系統。如果開發人員沒意識到這樣的問題,很可能會代碼設計成曝光資料等待點選資料進行關聯。關聯不上曝光資料的點選資料就很容易被一些簡單的條件判斷語句抛棄。
對于離線處理來說,消息都是批處理,不存在關聯不上的情況。在Lambda架構下,即使實時部分資料處理存在一定丢失,但因為離線資料占絕對優勢,是以對整體結果影響很小。即使當天的實時處理結果存在問題,也會在第二天被離線處理的正确結果進行覆寫。保證了最終結果正确。
Flink(Blink)的解法
先整理一下Lambda架構和Kappa架構的優缺點:
優點 | 缺點 | |
Lambda | 1、架構簡單 2、很好的結合了離線批處理和實時流處理的優點 4、穩定且實時計算成本可控 5、離線資料易于訂正 | 1、實時、離線資料很難保持一緻結果 2、需要維護兩套系統 |
Kappa | 1、隻需要維護實時處理子產品 2、可以通過消息重放 3、無需離線實時資料合并 | 1、強依賴消息中間件緩存能力 2、實時資料處理時存在丢失資料可能。 |
Kappa在抛棄了離線資料處理子產品的時候,同時抛棄了離線計算更加穩定可靠的特點。Lambda雖然保證了離線計算的穩定性,但雙系統的維護成本高且兩套代碼帶來後期運維困難。
為了實作流批處理一體化,Blink采用的将流處理視為批處理的一種特殊形式。是以在内部維持了若幹張張流表。通過緩存時間進行限制,限定在一個時間段内的資料組成的表,進而将實時流轉為微批處理。
理論上隻要把時間視窗開的足夠大,Flink的流表可以存下上百日的資料,進而保證微批處理的“微”足夠大可以替換掉離線處理資料。
但這樣做存在幾個問題:
1.Flink的流表是放在記憶體中,不做持久化處理的。一旦任務發生異常,記憶體資料丢失,Flink是需要回溯上遊消息流,進而轉為Kappa的結構。
2.資料視窗開的越大,記憶體成本越高。受限于成本,對大量資料處理仍然有可支援的實體空間上限。
3.下遊接收的通常都是處理結果,對于記憶體中的流表資料是無法直接通路的。這樣無形中增加了開發成本。
結合以上幾個問題,我們提出了混合數倉架構。試圖在綜合實時數倉和離線數倉的優點,盡量規避各自的缺點。
混合數倉(Omega架構)的解法
什麼是ECS設計模式
在談我們的解法的時候,必須要先提ECS的設計模式。
簡單的說,Entity、Component、System分别代表了三類模型。
實體(Entity):實體是一個普通的對象。通常,它隻包含了一個獨一無二的ID值,用來标記它是一個獨立的對象。
元件(Component):對象一個方面的資料,以及對象如何和世界進行互動。用來标記實體是否需要進行這一方面的處理,通常使用結構體,類或關聯數組實作。
系統(System):每個系統不間斷地運作(就像每個系統運作在自己的私有線程上),處理标記使用了該系統處理的元件的每個實體。
Entity對應于數倉中的Table,Component對應Schema,System對應數倉中SQL邏輯。
對于數倉來說,每張表的意義是由一群schema決定的。而每一個schema隻代表一個含義。SQL代碼的作用是組裝schema到對應的table中,實作它的業務意義。對于一個OLAP系統,我們喜歡大寬表的意義就是因為OLAP分析的是schema之間的關系,用大寬表可以很輕易的提取所需要的schema,組裝一個業務所需的表。
ECS設計模式的核心思想就是,所有shcema都獨立出來,整個數倉就是一個大寬表。當需要使用的時候,把對應的schema組裝成具有業務含義的table。這就像一個個Component組裝成一個Entity一樣。而SQL在其中起到的作用是就是産出對應的schema群組裝schema。
将ECS設計模式引入數倉設計,希望開發者可以更加關注于邏輯,關注資料如何處理,也就是S的部分。業務則由從列建構表的時候産生。将表結構和資料處理邏輯進行拆分,進而希望能提升SQL代碼的可讀性和結構性。
傳統數倉的資料處理流程
數倉通常是分為三層:ODS(原始資料),DW(資料倉庫層),ADS(應用資料層)。ODS是從消息中間件中拿到的最原始的資料。DW層則是對資料進行加工後的資料,通常還是分為:DWS和DWD。DWD層中是對ODS層的資料進行清洗後提取的出來的。而DWS層是經過了一些輕度彙總後的資料。使用者可以基于此層直接加工出ADS層所需的資料。ADS層則是産出應用最終所需的資料。
是以我們一般的數倉資料處理流程是:
基于ECS設計模式設計的混合數倉
在ECS的設計模式下,核心考慮的是Component是産出。産出具有業務含義的component,組裝出具體的業務表(Entity)。
Schema的注冊和Table注冊
對應在數倉模型中,可以這麼了解:數倉裡的表,任何一個schema都是獨立的。它們不具有業務含義,隻是業務的一個屬性。組合起來構成一個具有業務含義的表。
是以,我們需要一個專門管理schema的系統。這裡包含了schema注冊和shcema使用。schema注冊系統主要負責對schema唯一性作保證,避免schema重複進而影響使用。同時規定好Schema從中繼資料中提取的規則(正規表達式或者拆分字元串),保證不論在什麼系統中都可以得到唯一的提取結果。
schema的使用則依賴table注冊系統。通過table注冊系統,将一些具有相關含義的schema串聯起來,形成table提供給業務使用。
如下圖:
Schema開發與混合數倉架構
有了schema注冊,就要提到schema産出的問題了。在上文提到過,在Lambda架構下,離線實時數倉需要同時維護兩份代碼,其實就是需要維護兩份schema的注冊和産出過程。在Kappa架構中,雖然隻需要在實時數倉中做資料處理,但面對大量曆史資料處理時需要消耗非常多的資源,而且中間結果複用能力有限,不适合複雜的業務。
由于我們将schema 注冊抽離出來,在ECS的設計模式下,資料加工過程隻有schema之間的互動,是以隻需要關心資料加工部分代碼。而對于Flink(Blink)與MaxCompute(ODPS)來說,資料處理部分的sql代碼都遵循相近的SQL規範(這裡沒查到對應的SQL版本,但使用過程中感受是幾乎一緻,差别在于一些函數上。這一點可以通過UDF等方式解決。),是以可以保證很好的複用性。如果實時數倉和離線數倉資料處理層面的代碼差異較大的話,可以引入編譯器的形式解決。在任務送出的時候對代碼進行差異化的編譯,适用于對應的數倉。
進而我們可以畫出以下的架構圖:
Kafka傳入的消息是這套架構的ODS層,這一點上跟Lambda和Kappa架構是保持一緻的。
資料進入數倉後,資料會被Schema Register中注冊的規則提取出來,産出一個個對應的schema。即對應DWD層。
有了schema後,資料進入處理加工邏輯。即System部分。這裡需要針對實時和離線數倉分别産出對應的加工代碼,并執行具體的加工。此處對應的是DWS層。
最後,将加工後産出的schema和table Register系統結合,産出最終的ADS層的資料。
這套架構的好處是通過ECS設計模式的思想,将資料處理過程拆分成:資料聲明(Schema Register,Table Register),資料處理(System)和結果拼接(Table Creater)三個流程。在這三個過程中,将Flink、Max Compute視為計算資源,将整體資料加工處理的邏輯獨立在底層中間件之上,與開發環境解耦。進而實作工程化的管理資料倉庫裡的資料和加工過程。
但這套架構也存在一定的問題。例如,實時資料和離線資料是不互通的。如果統計過去180天UV總數時,需要離線和實時資料合并去重的處理就會遇到麻煩。
總結
我将這個架構命名為Omega架構,對應希臘字母中的Omega,含義是“終結”。我希望這套架構能解決目前實時數倉和離線數倉比較混亂的局面,可以讓大資料開發、管理的能力更上一個台階,讓更多小夥伴可以更加友善的取數,加工,進而更好的服務于業務。