用于實時大數(shù)據(jù)處理的Lambda架構 - 51CTO.COM
http://developer.51cto.com/art/201511/496529.htm
3.數(shù)據(jù)系統(tǒng)的本質
為了設計出能滿足前述的大數(shù)據(jù)關鍵特性的系統(tǒng)的榛,我們需要對數(shù)據(jù)系統(tǒng)有本質性的理解豪硅。我們可將數(shù)據(jù)系統(tǒng)簡化為:
【數(shù)據(jù)系統(tǒng) = 數(shù)據(jù) + 查詢】
從而從數(shù)據(jù)和查詢兩方面來認識大數(shù)據(jù)系統(tǒng)的本質俱尼。
Lambda架構的目標是設計出一個能滿足實時大數(shù)據(jù)系統(tǒng)關鍵特性的架構,包括有:高容錯、低延時和可擴展等河胎。Lambda架構整合離線計算和實時計算勃刨,融合不可變性(Immunability),讀寫分離和復雜性隔離等一系列架構原則谒养,可集成Hadoop挺狰,Kafka,Storm买窟,Spark丰泊,Hbase等各類大數(shù)據(jù)組件。
作者:來源:36大數(shù)據(jù)|2015-11-09 09:58
收藏
分享
1.Lambda架構背景介紹
Lambda架構是由Storm的作者Nathan Marz提出的一個實時大數(shù)據(jù)處理框架始绍。Marz在Twitter工作期間開發(fā)了著名的實時大數(shù)據(jù)處理框架Storm瞳购,Lambda架構是其根據(jù)多年進行分布式大數(shù)據(jù)系統(tǒng)的經(jīng)驗總結提煉而成。
Lambda架構的目標是設計出一個能滿足實時大數(shù)據(jù)系統(tǒng)關鍵特性的架構亏推,包括有:高容錯学赛、低延時和可擴展等年堆。Lambda架構整合離線計算和實時計算,融合不可變性(Immunability)罢屈,讀寫分離和復雜性隔離等一系列架構原則嘀韧,可集成Hadoop,Kafka缠捌,Storm锄贷,Spark,Hbase等各類大數(shù)據(jù)組件曼月。
2.大數(shù)據(jù)系統(tǒng)的關鍵特性
Marz認為大數(shù)據(jù)系統(tǒng)應具有以下的關鍵特性:
Robust and fault-tolerant(容錯性和魯棒性):對大規(guī)模分布式系統(tǒng)來說谊却,機器是不可靠的,可能會當機哑芹,但是系統(tǒng)需要是健壯炎辨、行為正確的,即使是遇到機器錯誤聪姿。除了機器錯誤碴萧,人更可能會犯錯誤。在軟件開發(fā)中難免會有一些Bug末购,系統(tǒng)必須對有Bug的程序寫入的錯誤數(shù)據(jù)有足夠的適應能力破喻,所以比機器容錯性更加重要的容錯性是人為操作容錯性。對于大規(guī)模的分布式系統(tǒng)來說盟榴,人和機器的錯誤每天都可能會發(fā)生曹质,如何應對人和機器的錯誤,讓系統(tǒng)能夠從錯誤中快速恢復尤其重要擎场。
Low latency reads and updates(低延時):很多應用對于讀和寫操作的延時要求非常高羽德,要求對更新和查詢的響應是低延時的。
Scalable(橫向擴容):當數(shù)據(jù)量/負載增大時迅办,可擴展性的系統(tǒng)通過增加更多的機器資源來維持性能宅静。也就是常說的系統(tǒng)需要線性可擴展,通常采用scale out(通過增加機器的個數(shù))而不是scale up(通過增強機器的性能)站欺。
General(通用性):系統(tǒng)需要能夠適應廣泛的應用坏为,包括金融領域、社交網(wǎng)絡镊绪、電子商務數(shù)據(jù)分析等匀伏。
Extensible(可擴展):需要增加新功能、新特性時蝴韭,可擴展的系統(tǒng)能以最小的開發(fā)代價來增加新功能够颠。
Allows ad hoc queries(方便查詢):數(shù)據(jù)中蘊含有價值,需要能夠方便榄鉴、快速的查詢出所需要的數(shù)據(jù)履磨。
Minimal maintenance(易于維護):系統(tǒng)要想做到易于維護蛉抓,其關鍵是控制其復雜性,越是復雜的系統(tǒng)越容易出錯剃诅、越難維護巷送。
Debuggable(易調試):當出問題時,系統(tǒng)需要有足夠的信息來調試錯誤矛辕,找到問題的根源笑跛。其關鍵是能夠追根溯源到每個數(shù)據(jù)生成點。
3.數(shù)據(jù)系統(tǒng)的本質
為了設計出能滿足前述的大數(shù)據(jù)關鍵特性的系統(tǒng)聊品,我們需要對數(shù)據(jù)系統(tǒng)有本質性的理解飞蹂。我們可將數(shù)據(jù)系統(tǒng)簡化為:
數(shù)據(jù)系統(tǒng) = 數(shù)據(jù) + 查詢
從而從數(shù)據(jù)和查詢兩方面來認識大數(shù)據(jù)系統(tǒng)的本質。
3.1.數(shù)據(jù)的本質
3.1.1.數(shù)據(jù)的特性:When & What
我們先從“數(shù)據(jù)”的特性談起翻屈。數(shù)據(jù)是一個不可分割的單位陈哑,數(shù)據(jù)有兩個關鍵的性質:When和What。
When是指數(shù)據(jù)是與時間相關的伸眶,數(shù)據(jù)一定是在某個時間點產(chǎn)生的咧纠。比如Log日志就隱含著按照時間先后順序產(chǎn)生的數(shù)據(jù)事哭,Log前面的日志數(shù)據(jù)一定先于Log后面的日志數(shù)據(jù)產(chǎn)生顿苇;消息系統(tǒng)中消息的接受者一定是在消息的發(fā)送者發(fā)送消息后接收到的消息呻澜。相比于數(shù)據(jù)庫,數(shù)據(jù)庫中表的記錄就丟失了時間先后順序的信息涂臣,中間某條記錄可能是在最后一條記錄產(chǎn)生后發(fā)生更新的。對于分布式系統(tǒng)售担,數(shù)據(jù)的時間特性尤其重要赁遗。分布式系統(tǒng)中數(shù)據(jù)可能產(chǎn)生于不同的系統(tǒng)中,時間決定了數(shù)據(jù)發(fā)生的全局先后順序族铆。比如對一個值做算術運算岩四,先+2,后3哥攘,與先3剖煌,后+2,得到的結果完全不同逝淹。數(shù)據(jù)的時間性質決定了數(shù)據(jù)的全局發(fā)生先后耕姊,也就決定了數(shù)據(jù)的結果。
What是指數(shù)據(jù)的本身栅葡。由于數(shù)據(jù)跟某個時間點相關茉兰,所以數(shù)據(jù)的本身是不可變的(immutable),過往的數(shù)據(jù)已經(jīng)成為事實(Fact)欣簇,你不可能回到過去的某個時間點去改變數(shù)據(jù)事實规脸。這也就意味著對數(shù)據(jù)的操作其實只有兩種:讀取已存在的數(shù)據(jù)和添加更多的新數(shù)據(jù)坯约。采用數(shù)據(jù)庫的記法,CRUD就變成了CR莫鸭,Update和Delete本質上其實是新產(chǎn)生的數(shù)據(jù)信息闹丐,用C來記錄。
3.1.2.數(shù)據(jù)的存儲:Store Everything Rawly and Immutably
根據(jù)上述對數(shù)據(jù)本質特性的分析被因,Lamba架構中對數(shù)據(jù)的存儲采用的方式是:數(shù)據(jù)不可變卿拴,存儲所有數(shù)據(jù)。
通過采用不可變方式存儲所有的數(shù)據(jù)氏身,可以有如下好處:
簡單巍棱。采用不可變的數(shù)據(jù)模型,存儲數(shù)據(jù)時只需要簡單的往主數(shù)據(jù)集后追加數(shù)據(jù)即可蛋欣。相比于采用可變的數(shù)據(jù)模型航徙,為了Update操作,數(shù)據(jù)通常需要被索引陷虎,從而能快速找到要更新的數(shù)據(jù)去做更新操作到踏。
應對人為和機器的錯誤。前述中提到人和機器每天都可能會出錯尚猿,如何應對人和機器的錯誤窝稿,讓系統(tǒng)能夠從錯誤中快速恢復極其重要。不可變性(Immutability)和重新計算(Recomputation)則是應對人為和機器錯誤的常用方法凿掂。采用可變數(shù)據(jù)模型伴榔,引發(fā)錯誤的數(shù)據(jù)有可能被覆蓋而丟失。相比于采用不可變的數(shù)據(jù)模型庄萎,因為所有的數(shù)據(jù)都在踪少,引發(fā)錯誤的數(shù)據(jù)也在。修復的方法就可以簡單的是遍歷數(shù)據(jù)集上存儲的所有的數(shù)據(jù)糠涛,丟棄錯誤的數(shù)據(jù)援奢,重新計算得到Views(View的概念參考4.1.2)。重新計算的關鍵點在于利用數(shù)據(jù)的時間特性決定的全局次序忍捡,依次順序重新執(zhí)行集漾,必然能得到正確的結果。
當前業(yè)界有很多采用不可變數(shù)據(jù)模型來存儲所有數(shù)據(jù)的例子砸脊。比如分布式數(shù)據(jù)庫Datomic具篇,基于不可變數(shù)據(jù)模型來存儲數(shù)據(jù),從而簡化了設計凌埂。分布式消息中間件Kafka栽连,基于Log日志,以追加append-only的方式來存儲消息。
3.2.查詢
查詢是個什么概念秒紧?Marz給查詢如下一個簡單的定義:
Query = Function(All Data)
該等式的含義是:查詢是應用于數(shù)據(jù)集上的函數(shù)绢陌。該定義看似簡單,卻幾乎囊括了數(shù)據(jù)庫和數(shù)據(jù)系統(tǒng)的所有領域:RDBMS熔恢、索引脐湾、OLAP、OLTP叙淌、MapReduce秤掌、EFL、分布式文件系統(tǒng)鹰霍、NoSQL等都可以用這個等式來表示闻鉴。
讓我們進一步深入看一下函數(shù)的特性,從而挖掘函數(shù)自身的特點來執(zhí)行查詢茂洒。
有一類稱為Monoid特性的函數(shù)應用非常廣泛孟岛。Monoid的概念來源于范疇學(Category Theory),其一個重要特性是滿足結合律督勺。如整數(shù)的加法就滿足Monoid特性:
(a+b)+c=a+(b+c)
不滿足Monoid特性的函數(shù)很多時候可以轉化成多個滿足Monoid特性的函數(shù)的運算渠羞。如多個數(shù)的平均值Avg函數(shù),多個平均值沒法直接通過結合來得到最終的平均值智哀,但是可以拆成分母除以分子次询,分母和分子都是整數(shù)的加法,從而滿足Monoid特性瓷叫。
Monoid的結合律特性在分布式計算中極其重要屯吊,滿足Monoid特性意味著我們可以將計算分解到多臺機器并行運算,然后再結合各自的部分運算結果得到最終結果摹菠。同時也意味著部分運算結果可以儲存下來被別的運算共享利用(如果該運算也包含相同的部分子運算)盒卸,從而減少重復運算的工作量。
4.Lambda架構
有了上面對數(shù)據(jù)系統(tǒng)本質的探討辨嗽,下面我們來討論大數(shù)據(jù)系統(tǒng)的關鍵問題:如何實時地在任意大數(shù)據(jù)集上進行查詢世落?大數(shù)據(jù)再加上實時計算淮腾,問題的難度比較大糟需。
最簡單的方法是,根據(jù)前述的查詢等式Query = Function(All Data)谷朝,在全體數(shù)據(jù)集上在線運行查詢函數(shù)得到結果洲押。但如果數(shù)據(jù)量比較大,該方法的計算代價太大了圆凰,所以不現(xiàn)實杈帐。
Lambda架構通過分解的三層架構來解決該問題:Batch Layer,Speed Layer和Serving Layer。
4.1.Batch Layer
Batch Layer的功能主要有兩點:
存儲數(shù)據(jù)集
在數(shù)據(jù)集上預先計算查詢函數(shù)挑童,構建查詢所對應的View
4.1.1.儲存數(shù)據(jù)集
根據(jù)前述對數(shù)據(jù)When&What特性的討論累铅,Batch Layer采用不可變模型存儲所有的數(shù)據(jù)。因為數(shù)據(jù)量比較大站叼,可以采用HDFS之類的大數(shù)據(jù)儲存方案娃兽。如果需要按照數(shù)據(jù)產(chǎn)生的時間先后順序存放數(shù)據(jù),可以考慮如InfluxDB之類的時間序列數(shù)據(jù)庫(TSDB)存儲方案尽楔。
4.1.2.構建查詢View
上面說到根據(jù)等式Query = Function(All Data)投储,在全體數(shù)據(jù)集上在線運行查詢函數(shù)得到結果的代價太大。但如果我們預先在數(shù)據(jù)集上計算并保存查詢函數(shù)的結果阔馋,查詢的時候就可以直接返回結果(或通過簡單的加工運算就可得到結果)而無需重新進行完整費時的計算了玛荞。這兒可以把Batch Layer看成是一個數(shù)據(jù)預處理的過程。我們把針對查詢預先計算并保存的結果稱為View呕寝,View是Lamba架構的一個核心概念勋眯,它是針對查詢的優(yōu)化,通過View即可以快速得到查詢結果壁涎。
如果采用HDFS來儲存數(shù)據(jù)凡恍,我們就可以使用MapReduce來在數(shù)據(jù)集上構建查詢的View。Batch Layer的工作可以簡單的用如下偽碼表示:
該工作看似簡單怔球,實質非常強大嚼酝。任何人為或機器發(fā)生的錯誤,都可以通過修正錯誤后重新計算來恢復得到正確結果竟坛。
對View的理解:View是一個和業(yè)務關聯(lián)性比較大的概念闽巩,View的創(chuàng)建需要從業(yè)務自身的需求出發(fā)。一個通用的數(shù)據(jù)庫查詢系統(tǒng)担汤,查詢對應的函數(shù)千變萬化涎跨,不可能窮舉。但是如果從業(yè)務自身的需求出發(fā)崭歧,可以發(fā)現(xiàn)業(yè)務所需要的查詢常常是有限的隅很。Batch Layer需要做的一件重要的工作就是根據(jù)業(yè)務的需求,考察可能需要的各種查詢率碾,根據(jù)查詢定義其在數(shù)據(jù)集上對應的Views叔营。
4.2.Speed Layer
Batch Layer可以很好的處理離線數(shù)據(jù),但有很多場景數(shù)據(jù)不斷實時生成所宰,并且需要實時查詢處理绒尊。Speed Layer正是用來處理增量的實時數(shù)據(jù)。
Speed Layer和Batch Layer比較類似仔粥,對數(shù)據(jù)進行計算并生成Realtime View婴谱,其主要區(qū)別在于:
Speed Layer處理的數(shù)據(jù)是最近的增量數(shù)據(jù)流蟹但,Batch Layer處理的全體數(shù)據(jù)集
Speed Layer為了效率,接收到新數(shù)據(jù)時不斷更新Realtime View谭羔,而Batch Layer根據(jù)全體離線數(shù)據(jù)集直接得到Batch View华糖。
Lambda架構將數(shù)據(jù)處理分解為Batch Layer和Speed Layer有如下優(yōu)點:
容錯性。Speed Layer中處理的數(shù)據(jù)也不斷寫入Batch Layer瘟裸,當Batch Layer中重新計算的數(shù)據(jù)集包含Speed Layer處理的數(shù)據(jù)集后缅阳,當前的Realtime View就可以丟棄,這也就意味著Speed Layer處理中引入的錯誤景描,在Batch Layer重新計算時都可以得到修正十办。這點也可以看成是CAP理論中的最終一致性(Eventual Consistency)的體現(xiàn)。
復雜性隔離超棺。Batch Layer處理的是離線數(shù)據(jù)向族,可以很好的掌控。Speed Layer采用增量算法處理實時數(shù)據(jù)棠绘,復雜性比Batch Layer要高很多件相。通過分開Batch Layer和Speed Layer,把復雜性隔離到Speed Layer氧苍,可以很好的提高整個系統(tǒng)的魯棒性和可靠性夜矗。
4.3.Serving Layer
Lambda架構的Serving Layer用于響應用戶的查詢請求,合并Batch View和Realtime View中的結果數(shù)據(jù)集到最終的數(shù)據(jù)集让虐。
這兒涉及到數(shù)據(jù)如何合并的問題紊撕。前面我們討論了查詢函數(shù)的Monoid性質,如果查詢函數(shù)滿足Monoid性質赡突,即滿足結合率对扶,只需要簡單的合并Batch View和Realtime View中的結果數(shù)據(jù)集即可。否則的話惭缰,可以把查詢函數(shù)轉換成多個滿足Monoid性質的查詢函數(shù)的運算浪南,單獨對每個滿足Monoid性質的查詢函數(shù)進行Batch View和Realtime View中的結果數(shù)據(jù)集合并,然后再計算得到最終的結果數(shù)據(jù)集漱受。另外也可以根據(jù)業(yè)務自身的特性络凿,運用業(yè)務自身的規(guī)則來對Batch View和Realtime View中的結果數(shù)據(jù)集合并。
5.Big Picture
上面分別討論了Lambda架構的三層:Batch Layer昂羡,Speed Layer和Serving Layer絮记。下圖給出了Lambda架構的一個完整視圖和流程。
數(shù)據(jù)流進入系統(tǒng)后紧憾,同時發(fā)往Batch Layer和Speed Layer處理到千。Batch Layer以不可變模型離線存儲所有數(shù)據(jù)集昌渤,通過在全體數(shù)據(jù)集上不斷重新計算構建查詢所對應的Batch Views赴穗。Speed Layer處理增量的實時數(shù)據(jù)流,不斷更新查詢所對應的Realtime Views。Serving Layer響應用戶的查詢請求般眉,合并Batch View和Realtime View中的結果數(shù)據(jù)集到最終的數(shù)據(jù)集了赵。
5.1.Lambda架構組件選型
下圖給出了Lambda架構中各個層常用的組件。數(shù)據(jù)流存儲可選用基于不可變日志的分布式消息系統(tǒng)Kafka甸赃;Batch Layer數(shù)據(jù)集的存儲可選用Hadoop的HDFS柿汛,或者是阿里云的ODPS;Batch View的預計算可以選用MapReduce或Spark埠对;Batch View自身結果數(shù)據(jù)的存儲可使用MySQL(查詢少量的最近結果數(shù)據(jù))络断,或HBase(查詢大量的歷史結果數(shù)據(jù))。Speed Layer增量數(shù)據(jù)的處理可選用Storm或Spark Streaming项玛;Realtime View增量結果數(shù)據(jù)集為了滿足實時更新的效率貌笨,可選用Redis等內存NoSQL。
5.2.Lambda架構組件選型原則
Lambda架構是個通用框架襟沮,各個層選型時不要局限時上面給出的組件锥惋,特別是對于View的選型。從我對Lambda架構的實踐來看开伏,因為View是個和業(yè)務關聯(lián)性非常大的概念膀跌,View選擇組件時關鍵是要根據(jù)業(yè)務的需求,來選擇最適合查詢的組件固灵。不同的View組件的選擇要深入挖掘數(shù)據(jù)和計算自身的特點捅伤,從而選擇出最適合數(shù)據(jù)和計算自身特點的組件,同時不同的View可以選擇不同的組件巫玻。
6.Lambda架構 vs. Event Sourcing vs. CQRS
在Lambda架構身上可以看到很多現(xiàn)有設計思想和架構的影子暑认,如Event Sourcing和CQRS,這兒我們把它們和Lambda架構做一結合對比大审,從而去更深入的理解Lambda架構蘸际。
6.1.事件溯源(Event Sourcing)vs. Lambda架構
事件溯源(Event Sourcing)是由大名鼎鼎的Martin Flower大叔提出來的架構模式。Event Sourcing本質上是一種數(shù)據(jù)持久化的方式徒扶,它將引發(fā)變化的事件(Event)本身存儲下來粮彤。相比于傳統(tǒng)數(shù)據(jù)是持久化方式,存儲的是事件引發(fā)的結果姜骡,而非事件本身导坟,這樣我們在保存結果的同時,實際上失去了追溯導致結果原因的機會圈澈。
這兒可以看到Lambda架構中數(shù)據(jù)集的存儲和Event Sourcing中的思想是完全一致的惫周,本質都是采用不可變的數(shù)據(jù)模型存儲引發(fā)變化的事件而非變化產(chǎn)生的結果。從而在發(fā)生錯誤的時候康栈,能夠追本溯源递递,找到發(fā)生錯誤的根源喷橙,通過重新計算丟棄錯誤的信息來恢復系統(tǒng),達到系統(tǒng)的容錯性登舞。
6.2.CQRS vs. Lambda架構
CQRS (Command Query Responsibility Segregation)將對數(shù)據(jù)的修改操作和查詢操作分離贰逾,其本質和Lambda架構一樣,也是一種形式的讀寫分離菠秒。在Lambda架構中疙剑,數(shù)據(jù)以不可變的方式存儲下來(寫操作),轉換成查詢所對應的Views践叠,查詢從View中直接得到結果數(shù)據(jù)(讀操作)言缤。
讀寫分離將讀和寫兩個視角進行分離,帶來的好處是復雜性的隔離禁灼,從而簡化系統(tǒng)的設計轧简。相比于傳統(tǒng)做法中的將讀和寫操作放在一起的處理方式,對于讀寫操作業(yè)務非常復雜的系統(tǒng)匾二,只會使系統(tǒng)變得異常復雜哮独,難以維護。
7.總結
本文介紹了Lambda架構的基本概念察藐。Lambda架構通過對數(shù)據(jù)和查詢的本質認識皮璧,融合了不可變性(Immunability),讀寫分離和復雜性隔離等一系列架構原則分飞,將大數(shù)據(jù)處理系統(tǒng)劃分為Batch Layer, Speed Layer和Serving Layer三層悴务,從而設計出一個能滿足實時大數(shù)據(jù)系統(tǒng)關鍵特性(如高容錯、低延時和可擴展等)的架構譬猫。Lambda架構作為一個通用的大數(shù)據(jù)處理框架讯檐,可以很方便的集成Hadoop,Kafka染服,Storm别洪,Spark,Hbase等各類大數(shù)據(jù)組件柳刮。