大數據系統(tǒng)的Lambda架構 | 36大數據 http://www.36dsj.com/archives/36384
在大數據處理系統(tǒng)中碾牌,如何有效地將real time與batch job結合起來缆蝉,既發(fā)揮前者對響應的實時性迁霎,又能解決對海量數據的分析與處理懈息?答案就是Lambda架構思想。
Mathan Marz的大作Big Data: Principles and best practices of scalable real-time data systems介紹了Labmda Architecture的概念基茵,用于在大數據架構中,如何讓real-time與batch job更好地結合起來壳影,以達成對大數據的實時處理拱层。
用于實時大數據處理的Lambda架構
傳統(tǒng)系統(tǒng)的問題
在傳統(tǒng)數據庫的設計中,無法很好地支持系統(tǒng)的可伸縮性宴咧。當用戶訪問量增加時根灯,數據庫無法滿足日益增長的用戶請求負載,從而導致數據庫服務器無法及時響應用戶請求掺栅,出現超時錯誤烙肺。
解決的辦法是在Web服務器與數據庫之間增加一個異步處理的隊列。如下圖所示:
當Web Server收到頁面請求時氧卧,會將消息添加到隊列中桃笙。在DB端,創(chuàng)建一個Worker定期從隊列中取出消息進行處理沙绝,例如每次讀取100條消息搏明。這相當于在兩者之間建立了一個緩沖鼠锈。
但是,這一方案并沒有從本質上解決數據庫overload的問題星著,且當worker無法跟上writer的請求時购笆,就需要增加多個worker并發(fā)執(zhí)行,數據庫又將再次成為響應請求的瓶頸虚循。一個解決辦法是對數據庫進行分區(qū)(horizontal partitioning或者sharding)同欠。分區(qū)的方式通常以Hash值作為key。這樣就需要應用程序端知道如何去尋找每個key所在的分區(qū)横缔。
問題仍然會隨著用戶請求的增加接踵而來铺遂。當之前的分區(qū)無法滿足負載時,就需要增加更多分區(qū)茎刚,這時就需要對數據庫進行reshard娃循。resharding的工作非常耗時而痛苦,因為需要協調很多工作斗蒋,例如數據的遷移捌斧、更新客戶端訪問的分區(qū)地址,更新應用程序代碼泉沾。如果系統(tǒng)本身還提供了在線訪問服務捞蚂,對運維的要求就更高。稍有不慎跷究,就可能導致數據寫到錯誤的分區(qū)姓迅,因此必須要編寫腳本來自動完成,且需要充分的測試俊马。
即使分區(qū)能夠解決數據庫負載問題丁存,卻還存在容錯性(Fault-Tolerance)的問題。解決辦法:
改變queue/worker的實現柴我。當消息發(fā)送給不可用的分區(qū)時解寝,將消息放到“pending”隊列,然后每隔一段時間對pending隊列中的消息進行處理艘儒。
使用數據庫的replication功能聋伦,為每個分區(qū)增加slave。
問題并沒有得到完美地解決界睁。假設系統(tǒng)出現問題觉增,例如在應用系統(tǒng)代碼端不小心引入了一個bug,使得對頁面的請求重復提交了一次翻斟,這就導致了重復的請求數據逾礁。糟糕的是,直到24小時之后才發(fā)現了該問題访惜,此時對數據的破壞已經造成了嘹履。即使每周的數據備份也無法解決此問題腻扇,因為它不知道到底是哪些數據受到了破壞(corrupiton)。由于人為錯誤總是不可避免的植捎,我們在架構時應該如何規(guī)避此問題衙解?
現在阳柔,架構變得越來越復雜焰枢,增加了隊列、分區(qū)舌剂、復制济锄、重分區(qū)腳本(resharding scripts)。應用程序還需要了解數據庫的schema霍转,并能訪問到正確的分區(qū)荐绝。問題在于:數據庫對于分區(qū)是不了解的,無法幫助你應對分區(qū)避消、復制與分布式查詢低滩。最糟糕的問題是系統(tǒng)并沒有為人為錯誤進行工程設計,僅靠備份是不能治本的岩喷。歸根結底恕沫,系統(tǒng)還需要限制因為人為錯誤導致的破壞。
數據系統(tǒng)的概念
大數據處理技術需要解決這種可伸縮性與復雜性纱意。首先要認識到這種分布式的本質婶溯,要很好地處理分區(qū)與復制,不會導致錯誤分區(qū)引起查詢失敗偷霉,而是要將這些邏輯內化到數據庫中迄委。當需要擴展系統(tǒng)時,可以非常方便地增加節(jié)點类少,系統(tǒng)也能夠針對新節(jié)點進行rebalance叙身。
其次是要讓數據成為不可變的。原始數據永遠都不能被修改硫狞,這樣即使犯了錯誤曲梗,寫了錯誤數據,原來好的數據并不會受到破壞妓忍。
何謂“數據系統(tǒng)”虏两?Mathan Marz認為:
如果數據系統(tǒng)通過查找過去的數據去回答問題,則通常需要訪問整個數據集世剖。因此可以給data system的最通用的定義:Query = function(all data)
一個大數據系統(tǒng)必須具備的屬性包括:
健壯性和容錯性(Robustness和Fault Tolerance)
低延遲的讀與更新(Low Latency reads and updates)
可伸縮性(Scalability)
通用性(Generalization)
可擴展性(Extensibility)
內置查詢(Ad hoc queries)
維護最卸ò铡(Minimal maintenance)
可調試性(Debuggability)
Lambda架構
Lambda架構的主要思想就是將大數據系統(tǒng)構建為多個層次,如下圖所示:
理想狀態(tài)下旁瘫,任何數據訪問都可以從表達式Query = function(all data)開始祖凫,但是琼蚯,若數據達到相當大的一個級別(例如PB),且還需要支持實時查詢時惠况,就需要耗費非常龐大的資源遭庶。
一個解決方式是預運算查詢函數(precomputed query funciton)。Mathan Marz將這種預運算查詢函數稱之為Batch View稠屠,當需要執(zhí)行查詢時峦睡,可以從Batch View中讀取結果。這樣一個預先運算好的View是可以建立索引的权埠,因而可以支持隨機讀取榨了。于是系統(tǒng)就變成:
batch view = function(all data)query = function(batch view)
Batch Layer
在Lambda架構中,實現batch view = function(all data)的部分被稱之為batch layer攘蔽。它承擔了兩個職責:
存儲Master Dataset龙屉,這是一個不變的持續(xù)增長的數據集
針對這個Master Dataset進行預運算
顯然,Batch Layer執(zhí)行的是批量處理满俗,例如Hadoop或者Spark支持的Map-Reduce方式转捕。 它的執(zhí)行方式可以用一段偽代碼來表示:
function runBatchLayer(): while (true): recomputeBatchViews()
例如這樣一段代碼:
Api.execute(Api.hfsSeqfile("/tmp/pageview-counts"), new Subquery("?url", "?count") .predicate(Api.hfsSeqfile("/data/pageviews"), "?url", "?user", "?timestamp") .predicate(new Count(), "?count");
代碼并行地對hdfs文件夾下的page views進行統(tǒng)計(count),合并結果唆垃,并將最終結果保存在pageview-counts文件夾下五芝。
利用Batch Layer進行預運算的作用實際上就是將大數據變小,從而有效地利用資源降盹,改善實時查詢的性能与柑。但這里有一個前提,就是我們需要預先知道查詢需要的數據蓄坏,如此才能在Batch Layer中安排執(zhí)行計劃价捧,定期對數據進行批量處理。此外涡戳,還要求這些預運算的統(tǒng)計數據是支持合并(merge)的结蟋。
Serving Layer
Batch Layer通過對master dataset執(zhí)行查詢獲得了batch view,而Serving Layer就要負責對batch view進行操作渔彰,從而為最終的實時查詢提供支撐嵌屎。因此Serving Layer的職責包含:
對batch view的隨機訪問
更新batch view
Serving Layer應該是一個專用的分布式數據庫,例如Elephant DB恍涂,以支持對batch view的加載宝惰、隨機讀取以及更新。注意再沧,它并不支持對batch view的隨機寫尼夺,因為隨機寫會為數據庫引來許多復雜性。簡單的特性才能使系統(tǒng)變得更健壯、可預測淤堵、易配置寝衫,也易于運維。
Speed Layer
只要batch layer完成對batch view的預計算拐邪,serving layer就會對其進行更新慰毅。這意味著在運行預計算時進入的數據不會馬上呈現到batch view中。這對于要求完全實時的數據系統(tǒng)而言是不能接受的扎阶。要解決這個問題汹胃,就要通過speed layer。從對數據的處理來看乘陪,speed layer與batch layer非常相似统台,它們之間最大的區(qū)別是前者只處理最近的數據雕擂,后者則要處理所有的數據啡邑。另一個區(qū)別是為了滿足最小的延遲,speed layer并不會在同一時間讀取所有的新數據井赌,相反谤逼,它會在接收到新數據時,更新realtime view仇穗,而不會像batch layer那樣重新運算整個view流部。speed layer是一種增量的計算,而非重新運算(recomputation)纹坐。
因而枝冀,Speed Layer的作用包括:
對更新到serving layer帶來的高延遲的一種補充
快速、增量的算法
最終Batch Layer會覆蓋speed layer
Speed Layer的等式表達如下所示:
realtime view = function(realtime view, new data)
注意耘子,realtime view是基于新數據和已有的realtime view果漾。
總結下來,Lambda架構就是如下的三個等式:
batch view = function(all data)realtime view = function(realtime view, new data)query = function(batch view . realtime view)
整個Lambda架構如下圖所示:
基于Lambda架構谷誓,一旦數據通過batch layer進入到serving layer绒障,在realtime view中的相應結果就不再需要了。
說明:本文內容摘譯自Mathan Marz的大作Big Data: Principles and best practices of salable real-time data systems. 作者:張逸
End.