天天看點

用于實時大資料處理的Lambda架構

1.lambda架構背景介紹

lambda架構是由storm的作者nathan marz提出的一個實時大資料處理架構。marz在twitter工作期間開發了著名的實時大資料處理架構storm,lambda架構是其根據多年進行分布式大資料系統的經驗總結提煉而成。

lambda架構的目标是設計出一個能滿足實時大資料系統關鍵特性的架構,包括有:高容錯、低延時和可擴充等。lambda架構整合離線計算和實時計算,融合不可變性(immunability),讀寫分離和複雜性隔離等一系列架構原則,可內建hadoop,kafka,storm,spark,hbase等各類大資料元件。

2.大資料系統的關鍵特性

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(易調試):當出問題時,系統需要有足夠的資訊來調試錯誤,找到問題的根源。其關鍵是能夠追根溯源到每個資料生成點。

3.資料系統的本質

為了設計出能滿足前述的大資料關鍵特性的系統,我們需要對資料系統有本質性的了解。我們可将資料系統簡化為:

資料系統 = 資料 + 查詢

進而從資料和查詢兩方面來認識大資料系統的本質。

3.1.資料的本質

3.1.1.資料的特性:when & what

我們先從“資料”的特性談起。資料是一個不可分割的機關,資料有兩個關鍵的性質:when和what。

when是指資料是與時間相關的,資料一定是在某個時間點産生的。比如log日志就隐含着按照時間先後順序産生的資料,log前面的日志資料一定先于log後面的日志資料産生;消息系統中消息的接受者一定是在消息的發送者發送消息後接收到的消息。相比于資料庫,資料庫中表的記錄就丢失了時間先後順序的資訊,中間某條記錄可能是在最後一條記錄産生後發生更新的。對于分布式系統,資料的時間特性尤其重要。分布式系統中資料可能産生于不同的系統中,時間決定了資料發生的全局先後順序。比如對一個值做算術運算,先+2,後3,與先3,後+2,得到的結果完全不同。資料的時間性質決定了資料的全局發生先後,也就決定了資料的結果。

what是指資料的本身。由于資料跟某個時間點相關,是以資料的本身是不可變的(immutable),過往的資料已經成為事實(fact),你不可能回到過去的某個時間點去改變資料事實。這也就意味着對資料的操作其實隻有兩種:讀取已存在的資料和添加更多的新資料。采用資料庫的記法,crud就變成了cr,update和delete本質上其實是新産生的資料資訊,用c來記錄。

3.1.2.資料的存儲:store everything rawly and immutably

根據上述對資料本質特性的分析,lamba架構中對資料的存儲采用的方式是:資料不可變,存儲所有資料。

通過采用不可變方式存儲所有的資料,可以有如下好處:

簡單。采用不可變的資料模型,存儲資料時隻需要簡單的往主資料集後追加資料即可。相比于采用可變的資料模型,為了update操作,資料通常需要被索引,進而能快速找到要更新的資料去做更新操作。

應對人為和機器的錯誤。前述中提到人和機器每天都可能會出錯,如何應對人和機器的錯誤,讓系統能夠從錯誤中快速恢複極其重要。不可變性(immutability)和重新計算(recomputation)則是應對人為和機器錯誤的常用方法。采用可變資料模型,引發錯誤的資料有可能被覆寫而丢失。相比于采用不可變的資料模型,因為所有的資料都在,引發錯誤的資料也在。修複的方法就可以簡單的是周遊資料集上存儲的所有的資料,丢棄錯誤的資料,重新計算得到views(view的概念參考4.1.2)。重新計算的關鍵點在于利用資料的時間特性決定的全局次序,依次順序重新執行,必然能得到正确的結果。

目前業界有很多采用不可變資料模型來存儲所有資料的例子。比如分布式資料庫datomic,基于不可變資料模型來存儲資料,進而簡化了設計。分布式消息中間件kafka,基于log日志,以追加append-only的方式來存儲消息。

3.2.查詢

查詢是個什麼概念?marz給查詢如下一個簡單的定義:

query = function(all data)

該等式的含義是:查詢是應用于資料集上的函數。該定義看似簡單,卻幾乎囊括了資料庫和資料系統的所有領域:rdbms、索引、olap、oltp、mapreduce、efl、分布式檔案系統、nosql等都可以用這個等式來表示。

讓我們進一步深入看一下函數的特性,進而挖掘函數自身的特點來執行查詢。

有一類稱為monoid特性的函數應用非常廣泛。monoid的概念來源于範疇學(category theory),其一個重要特性是滿足結合律。如整數的加法就滿足monoid特性:

(a+b)+c=a+(b+c)

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

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

lambda

4.lambda架構

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

最簡單的方法是,根據前述的查詢等式query = function(all data),在全體資料集上線上運作查詢函數得到結果。但如果資料量比較大,該方法的計算代價太大了,是以不現實。

lambda架構通過分解的三層架構來解決該問題:batch layer,speed layer和serving layer。

4.1.batch layer

batch layer的功能主要有兩點:

存儲資料集

在資料集上預先計算查詢函數,建構查詢所對應的view

4.1.1.儲存資料集

根據前述對資料when&what特性的讨論,batch layer采用不可變模型存儲所有的資料。因為資料量比較大,可以采用hdfs之類的大資料儲存方案。如果需要按照資料産生的時間先後順序存放資料,可以考慮如influxdb之類的時間序列資料庫(tsdb)存儲方案。

4.1.2.建構查詢view

上面說到根據等式query = function(all data),在全體資料集上線上運作查詢函數得到結果的代價太大。但如果我們預先在資料集上計算并儲存查詢函數的結果,查詢的時候就可以直接傳回結果(或通過簡單的加工運算就可得到結果)而無需重新進行完整費時的計算了。這兒可以把batch layer看成是一個資料預處理的過程。我們把針對查詢預先計算并儲存的結果稱為view,view是lamba架構的一個核心概念,它是針對查詢的優化,通過view即可以快速得到查詢結果。

如果采用hdfs來儲存資料,我們就可以使用mapreduce來在資料集上建構查詢的view。batch layer的工作可以簡單的用如下僞碼表示:

該工作看似簡單,實質非常強大。任何人為或機器發生的錯誤,都可以通過修正錯誤後重新計算來恢複得到正确結果。

對view的了解:

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

4.2.speed layer

batch layer可以很好的處理離線資料,但有很多場景資料不斷實時生成,并且需要實時查詢處理。speed layer正是用來處理增量的實時資料。

speed layer和batch layer比較類似,對資料進行計算并生成realtime view,其主要差別在于:

speed layer處理的資料是最近的增量資料流,batch layer處理的全體資料集

speed layer為了效率,接收到新資料時不斷更新realtime view,而batch layer根據全體離線資料集直接得到batch 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,可以很好的提高整個系統的魯棒性和可靠性。

4.3.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中的結果資料集合并。

5.big picture

上面分别讨論了lambda架構的三層:batch layer,speed layer和serving layer。下圖給出了lambda架構的一個完整視圖和流程。

資料流進入系統後,同時發往batch layer和speed layer處理。batch layer以不可變模型離線存儲所有資料集,通過在全體資料集上不斷重新計算建構查詢所對應的batch views。speed layer處理增量的實時資料流,不斷更新查詢所對應的realtime views。serving layer響應使用者的查詢請求,合并batch view和realtime view中的結果資料集到最終的資料集。

5.1.lambda架構元件選型

下圖給出了lambda架構中各個層常用的元件。資料流存儲可選用基于不可變日志的分布式消息系統kafka;batch layer資料集的存儲可選用hadoop的hdfs,或者是阿裡雲的odps;batch view的預計算可以選用mapreduce或spark;batch view自身結果資料的存儲可使用mysql(查詢少量的最近結果資料),或hbase(查詢大量的曆史結果資料)。speed layer增量資料的處理可選用storm或spark streaming;realtime view增量結果資料集為了滿足實時更新的效率,可選用redis等記憶體nosql。

5.2.lambda架構元件選型原則

lambda架構是個通用架構,各個層選型時不要局限時上面給出的元件,特别是對于view的選型。從我對lambda架構的實踐來看,因為view是個和業務關聯性非常大的概念,view選擇元件時關鍵是要根據業務的需求,來選擇最适合查詢的元件。不同的view元件的選擇要深入挖掘資料和計算自身的特點,進而選擇出最适合資料和計算自身特點的元件,同時不同的view可以選擇不同的元件。

6.lambda架構 vs. event sourcing vs. cqrs

在lambda架構身上可以看到很多現有設計思想和架構的影子,如event sourcing和cqrs,這兒我們把它們和lambda架構做一結合對比,進而去更深入的了解lambda架構。

6.1.事件溯源(event sourcing)vs. lambda架構

事件溯源(event sourcing)是由大名鼎鼎的martin flower大叔提出來的架構模式。event sourcing本質上是一種資料持久化的方式,它将引發變化的事件(event)本身存儲下來。相比于傳統資料是持久化方式,存儲的是事件引發的結果,而非事件本身,這樣我們在儲存結果的同時,實際上失去了追溯導緻結果原因的機會。

這兒可以看到lambda架構中資料集的存儲和event sourcing中的思想是完全一緻的,本質都是采用不可變的資料模型存儲引發變化的事件而非變化産生的結果。進而在發生錯誤的時候,能夠追本溯源,找到發生錯誤的根源,通過重新計算丢棄錯誤的資訊來恢複系統,達到系統的容錯性。

6.2.cqrs vs. lambda架構

cqrs (command query responsibility segregation)将對資料的修改操作和查詢操作分離,其本質和lambda架構一樣,也是一種形式的讀寫分離。在lambda架構中,資料以不可變的方式存儲下來(寫操作),轉換成查詢所對應的views,查詢從view中直接得到結果資料(讀操作)。

讀寫分離将讀和寫兩個視角進行分離,帶來的好處是複雜性的隔離,進而簡化系統的設計。相比于傳統做法中的将讀和寫操作放在一起的處理方式,對于讀寫操作業務非常複雜的系統,隻會使系統變得異常複雜,難以維護。

7.總結

本文介紹了lambda架構的基本概念。lambda架構通過對資料和查詢的本質認識,融合了不可變性(immunability),讀寫分離和複雜性隔離等一系列架構原則,将大資料處理系統劃分為batch layer, speed layer和serving layer三層,進而設計出一個能滿足實時大資料系統關鍵特性(如高容錯、低延時和可擴充等)的架構。lambda架構作為一個通用的大資料處理架構,可以很友善的內建hadoop,kafka,storm,spark,hbase等各類大資料元件。

本文作者:佚名

來源:51cto