一:大數據架構回顧-Lambda架構


“我們正在從IT時代走向DT時代(數據時代)。IT和DT之間,不僅僅是技術的變革,更是思想意識的變革,IT主要是為自我服務,用來更好地自我控制和管理,DT則是激活生產力,讓別人活得比你好”

——阿里巴巴董事局主席馬雲

   Lambda架構是由Storm的作者南森馬茲(Nathan Marz)提出的一個實時大數據處理框架。Marz在Twitter工作期間開發了著名的實時大數據處理框架Storm,Lambda架構是其根據多年進行分布式大數據系統的經驗總結提煉而成。Lambda架構的目標是設計出一個能滿足實時大數據系統關鍵特性的架構,包括有:高容錯、低延時和可擴展等。Lambda架構整合離線計算和實時計算,融合不可變性(Immunability),讀寫分離和復雜性隔離等一系列架構原則,可集成Hadoop生態各類大數據組件

傳統系統的問題


 數據量從M的級別到G的級別到現在T的級、P的級別。數據量的變化數據管理系統(DBMS)和數倉系統(DW)也在悄然的變化着。 傳統應用的數據系統架構設計時,應用直接訪問數據庫系統。當用戶訪問量增加時,數據庫無法支撐日益增長的用戶請求的負載時,從而導致數據庫服務器無法及時響應用戶請求,出現超時的錯誤。出現這種情況以后,在系統架構上就采用下圖的架構,在數據庫和應用中間過一層緩沖隔離,緩解數據庫的讀寫壓力

然而,當用戶訪問量持續增加時,就需要考慮讀寫分離技術(Master-Slave)架構則如下圖,分庫分表技術。現在,架構變得越來越復雜了,增加隊列、分區、復制等處理邏輯。應用程序需要了解數據庫的schema,才能訪問到正確的數據。

商業現實已經發生了變化,所以現在更快做出的決定更有價值。除此之外,技術也在不斷發展。Kafka,Storm,Trident,Samza,Spark,Flink,Parquet,Avro,Cloud providers等都是工程師和企業廣泛采用的流行語。因此,現代基於Hadoop的M/R管道(使用Kafka,Avro和數據倉庫等現代二進制格式,即Amazon Redshift,用於臨時查詢)可能采用以下方式:

這看起來相當不錯,但它仍然是一種傳統的批處理方式,具有所有已知的缺點,主要原因是客戶端的數據在批處理花費大量時間完成之前的數據處理時,新的數據已經進入而導致數據過時

Lambda架構簡介


對低成本規模化的需求促使人們開始使用分布式文件系統,例如 HDFS和基於批量數據的計算系統(MapReduce 作業)。但是這種系統很難做到低延遲。用 Storm 開發的實時流處理技術可以幫助解決延遲性的問題,但並不完美。其中的一個原因是,Storm 不支持 exactly-once 語義,因此不能保證狀態數據的正確性,另外它也不支持基於事件時間的處理。有以上需求的用戶不得不在自己的應用程序代碼中加入這些功能。后來出現了一種混合分析的方法,它將上述兩個方案結合起來,既保證低延遲,又保障正確性。這個方法被稱作 Lambda 架構,它通過批量 MapReduce作業提供了雖有些延遲但是結果准確的計算,同時通過Storm將最新數據的計算結果初步展示出來。 

exactly-once說明:流處理引擎通常允許用戶指定可靠性模式或處理語義,以指示它將為整個應用程序中的數據處理提供哪些保證。這些保證是有意義的,因為你始終會遇到由於網絡,機器等可能導致數據丟失的故障。流處理引擎通常為應用程序提供了三種數據處理語義:

最多一次(At-most-once)
至少一次(At-least-once)
精確一次(Exactly-once)

 

Lambda架構的目標是設計出一個能滿足實時大數據系統關鍵特性的架構,包括有:高容錯、低延時可擴展等。Lambda架構整合離線計算和實時計算,融合不可變性(Immunability),讀寫分離復雜性隔離等一系列架構原則,可集成大數據生態各類大數據組件。

 

Lambda架構關鍵特性


Marz認為大數據系統應具有以下的關鍵特性

  • Robust and fault-tolerant(容錯性和魯棒性):對大規模分布式系統來說,機器是不可靠的,可能會當機,但是系統需要是健壯、行為正確的,即使是遇到機器錯誤。除了機器錯誤,人更可能會犯錯誤。在軟件開發中難免會有一些Bug,系統必須對有Bug的程序寫入的錯誤數據有足夠的適應能力,所以比機器容錯性更加重要的容錯性是人為操作容錯性。對於大規模的分布式系統來說,人和機器的錯誤每天都可能會發生,如何應對人和機器的錯誤,讓系統能夠從錯誤中快速恢復尤其重要。
  • Low latency reads and updates(低延時):很多應用對於讀和寫操作的延時要求非常高,要求對更新和查詢的響應是低延時的。
  • Scalable(橫向擴容):當數據量/負載增大時,可擴展性的系統通過增加更多的機器資源來維持性能。也就是常說的系統需要線性可擴展,通常采用scale out(通過增加機器的個數)而不是scale up(通過增強機器的性能)
  • General(通用性):系統需要能夠適應廣泛的應用,包括金融領域、社交網絡、電子商務數據分析等。
  • Extensible(可擴展):需要增加新功能、新特性時,可擴展的系統能以最小的開發代價來增加新功能。
  • Allows ad hoc queries(方便查詢):數據中蘊含有價值,需要能夠方便、快速的查詢出所需要的數據。
  • Minimal maintenance(易於維護):系統要想做到易於維護,其關鍵是控制其復雜性,越是復雜的系統越容易出錯、越難維護。
  • Debuggable(易調試):當出問題時,系統需要有足夠的信息來調試錯誤,找到問題的根源。其關鍵是能夠追根溯源到每個數據生成點。

數據系統的本質


為了設計出能滿足前述的大數據關鍵特性的系統,我們需要對數據系統有本質性的理解。我們可將數據系統簡化為數據 + 查詢,從而從數據和查詢兩方面來認識大數據系統的本質

  • 數據系統 = 數據 + 查詢

數據的特性: when & what  

 --- 數據是一個不可分割的單位,數據有兩個關鍵的性質:When和What。

  • When 是指數據是與時間相關的,數據一定是在某個時間點產生的。比如Log日志就隱含着按照時間先后順序產生的數據,Log前面的日志數據一定先於Log后面的日志數據產生;消息系統中消息的接受者一定是在消息的發送者發送消息后接收到的消息。相比於數據庫,數據庫中表的記錄就丟失了時間先后順序的信息,中間某條記錄可能是在最后一條記錄產生后發生更新的。對於分布式系統,數據的時間特性尤其重要。分布式系統中數據可能產生於不同的系統中,時間決定了數據發生的全局先后順序。比如對一個值做算術運算,先+2,后3,與先3,后+2,得到的結果完全不同。數據的時間性質決定了數據的全局發生先后,也就決定了數據的結果。
  • What 是指數據的本身。由於數據跟某個時間點相關,所以數據的本身是不可變的(immutable),過往的數據已經成為事實(Fact),你不可能回到過去的某個時間點去改變數據事實。這也就意味着對數據的操作其實只有兩種:讀取已存在的數據和添加更多的新數據。采用數據庫的記法,CRUD就變成了CR,Update和Delete本質上其實是新產生的數據信息,用C來記錄。
  • 創建(Create)、更新(Update)、讀取(Retrieve)和刪除(Delete)

     

數據的存儲:Store Everything Rawly and Immutably

 --- 根據上述對數據本質特性的分析,Lamba架構中對數據的存儲采用的方式是:數據不可變,存儲所有數據。 通過采用不可變方式存儲所有的數據,可以有如下好處:

  • 簡單: 采用不可變的數據模型,存儲數據時只需要簡單的往主數據集后追加數據即可。相比於采用可變的數據模型,為了Update操作,數據通常需要被索引,從而能快速找到要更新的數據去做更新操作。
  • 應對人為和機器的錯誤: 前述中提到人和機器每天都可能會出錯,如何應對人和機器的錯誤,讓系統能夠從錯誤中快速恢復極其重要。不可變性(Immutability)和重新計算(Recomputation)則是應對人為和機器錯誤的常用方法。采用可變數據模型,引發錯誤的數據有可能被覆蓋而丟失。相比於采用不可變的數據模型,因為所有的數據都在,引發錯誤的數據也在。修復的方法就可以簡單的是遍歷數據集上存儲的所有的數據,丟棄錯誤的數據,重新計算得到Views。重新計算的關鍵點在於利用數據的時間特性決定的全局次序,依次順序重新執行,必然能得到正確的結果。

 --- 當前業界有很多采用不可變數據模型來存儲所有數據的例子。比如分布式數據庫 Datomic,基於不可變數據模型來存儲數據,從而簡化了設計。分布式消息中間件 Kafka,基於Log日志,以追加append-only的方式來存儲消息。

查詢的本質

 --- 查詢是個什么概念?Marz給查詢如下一個簡單的定義:

  • Query = Function(All Data)

  該等式的含義是:查詢是應用於數據集上的函數。該定義看似簡單,卻幾乎囊括了數據庫和數據系統的所有領域:RDBMS、索引、OLAP、OLTP、MapReduce、EFL、分布式文件系統、NoSQL等都可以用這個等式來表示

讓我們進一步深入看一下函數的特性,從而挖掘函數自身的特點來執行查詢。 有一類稱為Monoid特性的函數應用非常廣泛。Monoid的概念來源於范疇學(Category Theory),其一個重要特性是滿足結合律。如整數的加法就滿足Monoid特性

  • (a+b)+c=a+(b+c)
說明: Semigroup(半群):集合S和其上的二元運算·:S×S→S。若·滿足結合律,即:∀x,y,z∈S,有(x·y)·z=x·(y·z),則稱有序對(S,·)為半群,運算·稱為該半群的乘法。實際使用中,在上下文明確的情況下,可以簡略敘述為“半群S”。例: 1、 對於自然數1、2345、...而言,加法運算+可將兩個自然數相加,得到的結果仍然是一個自然數,並且加法是滿足結合律的:(2 + 3) + 4 = 2 + (3 + 4) = 9。如此一來我們就可以認為自然數和加法運算組成了一個半群。類似的還有自然數與乘法運算等。 Monoid(單位半群):Monoid本身也是一個Semigroup,額外的地方是它多了單位元,所以被稱作為單位半群。舉例: 1、在上面介紹Semigroup的時候提到,自然數跟加法運算組成了一個半群。顯而易見的是,自然數0跟其他任意自然數相加,結果都是等於原來的數:0 + x = x。所以我們可以把0作為單位元,加入到由自然數和加法運算組成的半群中,從而得到了一個單位半群。 2、可以看到,Monoid協議繼承自Semigroup,並且用empty靜態屬性來代表單位元。

 不滿足Monoid特性的函數很多時候可以轉化成多個滿足Monoid特性的函數的運算。如多個數的平均值Avg函數,多個平均值沒法直接通過結合來得到最終的平均值,但是可以拆成分母除以分子,分母和分子都是整數的加法,從而滿足Monoid特性。

 Monoid的結合律特性在分布式計算中極其重要,滿足Monoid特性意味着我們可以將計算分解到多台機器並行運算,然后再結合各自的部分運算結果得到最終結果。同時也意味着部分運算結果可以儲存下來被別的運算共享利用(如果該運算也包含相同的部分子運算),從而減少重復運算的工作量。

Lambda的三層架構


有了上面對數據系統本質的探討,下面我們來討論大數據系統的關鍵問題:如何實時地在任意大數據集上進行查詢?大數據再加上實時計算,問題的難度比較大。

最簡單的方法是,根據前述的查詢等式Query = Function(All Data),在全體數據集上在線運行查詢函數得到結果。但如果數據量比較大,該方法的計算代價太大了,所以不現實。

Lambda架構通過分解的三層架構來解決該問題:Batch Layer,Speed LayerServing Layer

Batch Layer

 --- 理想狀態下,任何數據訪問都可以從表達式 Query= function(all data) 開始,但是,若數據達到相當大的一個級別(例如PB),且還需要支持實時查詢時,就需要耗費非常龐大的資源。一個解決方式是預運算查詢函數(precomputed query function)。書中將這種預運算查詢函數稱之為Batch View(A),這樣當需要執行查詢時,可以從 Batch View 中讀取結果。這樣一個預先運算好的 View 是可以建立索引的,因而可以支持隨機讀取(B)。於是系統就變成:

  • (A)batch view = function(all data)
  • (B)query = function(batch view)

在Lambda架構中,實現(A)batch view = function(all data) 的部分稱之為 Batch Layer。Batch Layer的功能主要有兩點:

  • 存儲 master dataset, 這是一個不變的持續增長的數據集
  • 在 master dataset 上預先計算查詢函數,構建查詢所對應的 View

存儲數據集

  --- 根據前述對數據 When&What 特性的討論,Batch Layer 采用不可變模型存儲所有的數據。因為數據量比較大,可以采用 HDFS 之類的大數據儲存方案。如果需要按照數據產生的時間先后順序存放數據,可以考慮如InfluxDB之類的時間序列數據庫(TSDB)存儲方案。

構建查詢View

  --- 上面說到根據等式 Query = Function(All Data),在全體數據集上在線運行查詢函數得到結果的代價太大。但如果我們預先在數據集上計算並保存查詢函數的結果,查詢的時候就可以直接返回結果(或通過簡單的加工運算就可得到結果)而無需重新進行完整費時的計算了。這兒可以把 Batch Layer看成是一個數據預處理的過程。我們把針對查詢預先計算並保存的結果稱為View,View是Lambda架構的一個核心概念,它是針對查詢的優化,通過View即可以快速得到查詢結果。

 

 

 --- 顯然,batch view是一個批處理過程,如采用Hadoop或spark支持的map-reduce方式。采用這種方式計算得到的每個view都支持再次計算,且每次計算的結果都相同。該工作看似簡單,實質非常強大。任何人為或機器發生的錯誤,都可以通過修正錯誤后重新計算來恢復得到正確結果。

對View的理解 

 --- View是一個和業務關聯性比較大的概念,View的創建需要從業務自身的需求出發。一個通用的數據庫查詢系統,查詢對應的函數千變萬化,不可能窮舉。但是如果從業務自身的需求出發,可以發現業務所需要的查詢常常是有限的。Batch Layer需要做的一件重要的工作就是根據業務的需求,考察可能需要的各種查詢,根據查詢定義其在數據集上對應的Views

如下圖 agent id=50023 的人,在10:00:06分的時候,狀態是calling,在10:00:10的時候狀態為waiting。在傳統的數據庫設計中,直接后面的紀錄覆蓋前面的紀錄,而在Immutable數據模型中,不會對原有數據進行更改,而是采用插入修改紀錄的形式更改歷史紀錄。

 

上文所提及的View是上圖中預先計算得到的相關視圖,例如:2016-06-21當天所有上線的agent數,每條熱線、公司下上線的Agent數。根據業務需要,預先計算出結果。此過程相當於傳統數倉建模的應用層,應用層也是根據業務場景,預先加工出的view。

Speed Layer 


 Batch Layer可以很好的處理離線數據,但有很多場景數據不斷實時生成,並且需要實時查詢處理。Speed Layer正是用來處理增量的實時數據。Speed Layer和Batch Layer比較類似,對數據進行計算並生成Realtime View,其主要區別在於: 

  • Speed Layer 處理的數據是最近的增量數據流Batch Layer處理的全體數據集
  • Speed Layer 為了效率,接收到新數據時不斷更新Realtime View,而Batch Layer根據全體離線數據集直接得到Batch View。
  • Speed Layer 一種增量計算,而非重新計算(recomputation)
  • Speed Layer 因為采用增量計算,所以延遲小,而Batch Layer是全數據集的計算,耗時比較長

綜上所訴,Speed Layer是 Batch Layer在實時性上的一個補充。Speed Layer可總結為:

  • (C)realtime view=function(realtime view,new data)

注意,realtime view 是基於新數據和已有的realtime view。

Lambda架構將數據處理分解為Batch Layer和Speed Layer有如下優點:

  • 容錯性:Speed Layer中處理的數據也不斷寫入Batch Layer,當Batch Layer中重新計算的數據集包含Speed Layer處理的數據集后,當前的Realtime View就可以丟棄,這也就意味着Speed Layer處理中引入的錯誤,在Batch Layer重新計算時都可以得到修正。這點也可以看成是CAP理論中的最終一致性(Eventual Consistency)的體現。
  • 復雜性隔離:Batch Layer處理的是離線數據,可以很好的掌控。Speed Layer采用增量算法處理實時數據,復雜性比Batch Layer要高很多。通過分開Batch Layer和Speed Layer,把復雜性隔離到Speed Layer,可以很好的提高整個系統的魯棒性和可靠性。

 

如前所述,任何傳入查詢都必須通過合並來自批量視圖和實時視圖的結果來得到答案,因此這些視圖需要滿足Monoid的結合律特性。需要注意的一點是,實時視圖是以前的實時視圖和新數據增量的函數,因此可以使用增量算法。批處理視圖是所有數據的函數,因此應該在那里使用重算算法。 

Serving Layer


Lambda架構的Serving Layer用於響應用戶的查詢請求,合並Batch View和Realtime View中的結果數據集到最終的數據集。

這兒涉及到數據如何合並的問題。前面我們討論了查詢函數的Monoid性質,如果查詢函數滿足Monoid性質,即滿足結合律,只需要簡單的合並Batch View和Realtime View中的結果數據集即可。否則的話,可以把查詢函數轉換成多個滿足Monoid性質的查詢函數的運算,單獨對每個滿足Monoid性質的查詢函數進行Batch View和Realtime View中的結果數據集合並,然后再計算得到最終的結果數據集。另外也可以根據業務自身的特性,運用業務自身的規則來對Batch View和Realtime View中的結果數據集合並。

 

 綜上所訴,Serving Layer采用如下等式表示:

  • (D)query=function(batch view, realtime view)

Lambda架構組件選型


上面分別討論了Lambda架構的三層:Batch Layer,Speed Layer和Serving Layer。總結下來,Lambda架構就是如下的三個等式:

  • batch view = function(all data)
  • realtime view = function(realtime view, new data)
  • query = function(batch view, realtime view)

下圖給出了Lambda架構的一個完整視圖和流程。

  •   

     

     

數據流進入系統后,同時發往Batch Layer和Speed Layer處理。其中:

  • Batch Layer 以不可變模型離線存儲所有數據集,通過在全體數據集上不斷重新計算構建查詢所對應的 Batch Views。
  • Speed Layer 處理增量的實時數據流,不斷更新查詢所對應的 Realtime Views。
  • Serving Layer 響應用戶的查詢請求,合並Batch View和Realtime View中的結果數據集到最終的數據集。

組件選型

 --- 下圖給出了Lambda架構中各組件在大數據生態系統中和阿里集團的常用組件。

  • 數據流存儲選用不可變日志的分布式系統 Kafka、TT、Metaq;
  • BatchLayer 數據集的存儲選用 Hadoop 的 HDFS 或者阿里雲的ODPS;
  • BatchVie w的加工采用MapReduce;
  • BatchView 數據的存儲采用Mysql(查詢少量的最近結果數據)、Hbase(查詢大量的歷史結果數據)。
  • SpeedLayer采用增量數據處理Storm、Flink;
  • RealtimeVie w增量結果數據集采用內存數據庫Redis。

另一個實現版本:

示例三:

 

 

根據batch layer的特點,具備存儲(HDFS)和計算(MapReduce)的Hadoop顯然是第一人選,而batch view 可以是hadoop本身的hdfs 或者基於hdfs的所構建的類似hive那樣的倉庫,speed layer因為時效性的影響,采用實時流式處理系統,例如strom或者spark streaming, 而speed view 可以存在HBase 或者其他類似的Nosql數據庫。server layer 提供用戶查詢的方法,采用facebook 開源的Impala,統一入口查詢。這是比較老的文章,主要用來理解Lambda架構原理,隨着大數據新的框架和組件的出現,可替代的組件多得去了,如下一小節根據實際場景來做組件選型就好。

選型原則


 Lambda架構是個通用框架各個層選型時不要局限時上面給出的組件特別是對於View的選型。從我對Lambda架構的實踐來看,因為View是個和業務關聯性非常大的概念,View選擇組件時關鍵是要根據業務的需求,來選擇最適合查詢的組件。不同的View組件的選擇要深入挖掘數據和計算自身的特點,從而選擇出最適合數據和計算自身特點的組件,同時不同的View可以選擇不同的組件。 

總結


在過去Lambda數據架構成為每一個公司大數據平台必備的架構,它解決了一個公司大數據批量離線處理和實時數據處理的需求。一個典型的Lambda架構如下:

  數據從底層的數據源開始,經過各種各樣的格式進入大數據平台,在大數據平台中經過 Kafka、Flume 等數據組件進行收集,然后分成兩條線進行計算。一條線是進入流式計算平台(例如 Storm、Flink或者Spark Streaming),去計算實時的一些指標;另一條線進入批量數據處理離線計算平台(例如Mapreduce、Hive,Spark SQL),去計算T+1的相關業務指標,這些指標需要隔日才能看見。

Lambda架構經歷多年的發展,其優點是穩定,對於實時計算部分的計算成本可控,批量處理可以用晚上的時間來整體批量計算,這樣把實時計算和離線計算高峰分開,這種架構支撐了數據行業的早期發展,但是它也有一些致命缺點,並在大數據3.0時代越來越不適應數據分析業務的需求。缺點如下:

  • 實時與批量計算結果不一致引起的數據口徑問題:因為批量和實時計算走的是兩個計算框架和計算程序,算出的結果往往不同,經常看到一個數字當天看是一個數據,第二天看昨天的數據反而發生了變化。
  • 批量計算在計算窗口內無法完成:在IOT時代,數據量級越來越大,經常發現夜間只有4、5個小時的時間窗口,已經無法完成白天20多個小時累計的數據,保證早上上班前准時出數據已成為每個大數據團隊頭疼的問題。
  • 開發和維護的復雜性問題:Lambda 架構需要在兩個不同的 API(application programming interface,應用程序編程接口)中對同樣的業務邏輯進行兩次編程:一次為批量計算的ETL系統,一次為流式計算的Streaming系統。針對同一個業務問題產生了兩個代碼庫,各有不同的漏洞。這種系統實際上非常難維護
  • 服務器存儲大:數據倉庫的典型設計,會產生大量的中間結果表,造成數據急速膨脹,加大服務器存儲壓力。

也就是由於Lambda架構的以上局限性,Kappa應運而生,它比Lambda架構更加靈活和精簡。

 

原文參考:



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM