在探索之前,我們來看一下hadoop解決了什麼問題,hadoop就是解決了大資料(大到單台伺服器無法進行存儲,單台伺服器無法在限定的時間内進行處理)的可靠存儲和處理。
hdfs:在由普通或廉價的伺服器(或pc)組成的叢集上提供高可用的檔案存儲,通過将塊儲存多個副本的辦法解決伺服器或硬碟壞掉的問題。
mapreduce:通過簡單的mapper和reducer的抽象提供一個程式設計模型,可以在一個由幾十台或上百台的伺服器組成的叢集上進行并
發,分布式的處理大量的資料集;而并發,分布式(如:機器間通信)和故障恢複等計算細節隐藏起來。而mapper和reducer的抽象,又是各種各樣的
複雜資料處理都可以分解為基本元素。這樣,複雜的資料處理可以分解為由多個job(包含一個mapper和一個reducer)組成的有向無環圖
(dag),然後每個mapper和reducer放到hadoop叢集上執行,就可以得出如下圖所示的結果:

在hadoop的源碼中,提供了一個很經典的例子:wordcount,具體源碼可以參見上篇文章,如果對
mapreduce不熟悉,通過該示例對mapreduce進行一些了解對了解下文會由幫助。在mapreduce中,shuffle是一個非常重要的過
程,正是有了看不見的shuffle過程,才可以使在mapreduce之上寫資料處理的開發者完全感覺不到分布式和并發的存在。
注:廣義的shuffle是指圖中在map和reduce之間的一系列過程。
mapreduce存在以下局限,使用起來比較困難。
抽象層次低,需要手工編寫代碼來完成,使用上難以上手,入門門檻較高。
隻提供兩個操作,map和reduce,表達的力度不夠。
一個job隻有map和reduce兩個階段,複雜的計算需要大量的job來完成。job之間的依賴關系是由開發者自己來管理的。
處理邏輯隐藏在代碼細節中,沒有整體邏輯。
中間結果也放在hdfs檔案系統中。
reducetask需要等待所有的maptask都完成後才可以開始。
時延高,隻适用batch資料處理,對于互動式資料處理,實時資料處理的支援不夠。
對于疊代式資料處理性能比較差。
舉個例子,用mapreduce實作表與表之間的join,都是一個很需要技巧來處理的過程,如下圖:
是以,在hadoop之後,出現來很多相關技術對其中的局限進行改進,如:hive,oozie,tez,spark,storm等等。
這裡就不多贅述了。hive是一種底層封裝了hadoop的資料倉庫處理工具,使用類sql的hivesql語言實作資料查詢,所有hive的資料都存儲
在hdfs中。hive在加載資料過程中不會對資料進行任何的修改,隻是将資料移動到hdfs中hive的指定目錄下,是以,hive不支援對資料的改寫
和添加,所有的資料都是在加載的時候确定的。
hive解決類mapreduce存在的大量手寫代碼,語義隐藏,提供操作種類少的問題。類似的項目還有pig,jaql等。
tez是hortonworks的stinger
initiative的的一部分。作為執行引擎,tez也提供了有向無環圖(dag),dag由頂點(vertex)和邊(edge)組成,edge是對
資料的移動的抽象,提供了one-to-one,broadcast,和scatter-gather三種類型,隻有scatter-gather才需要
進行shuffle。
示例:
tez的優化主要展現在:
去除了連續兩個任務之間的寫屏障
去除了每個工作流中多餘的map階段
通過提供dag語義和操作,提供了整體的邏輯,通過減少不必要的操作,tez提升了資料處理的執行性能。
spark也是一個大資料處理的引擎,主要特點是提供了一個叢集的分布式記憶體抽象,以支援需要工作集的應用。
這個抽象就是rdd(resilient distributed
dataset),rdd就是一個不可變的帶分區的記錄集合,rdd也是spark中的程式設計模型。spark提供了rdd上的兩類操作,轉換和動作。轉換
是用來定義一個新的rdd,包括map, flatmap, filter, union, sample, join, groupbykey,
cogroup, reducebykey, cros, sortbykey, mapvalues等,動作是傳回一個結果,包括collect,
reduce, count, save, lookupkey。
spark支援故障恢複的方式也不同,提供兩種方式,linage,通過資料的血緣關系,再執行一遍前面的處理,checkpoint,将資料集存儲到持久存儲中。
spark的api非常簡單易用,使用spark,wordcount的示例如下所示:
其中的file是根據hdfs上的檔案建立的rdd,後面的flatmap,map,reducebyke都建立出一個新的rdd,一個簡短的
程式就能夠執行很多個轉換和動作。在spark中,所有rdd的轉換都是是惰性求值的。spark的任務是由互相依賴的多個rdd組成的有向無環圖
(dag),每個rdd又包含多個分區,當在rdd上執行動作時,spark才對任務進行排程。
spark對于有向無環圖對任務進行排程,确定階段,分區,流水線,任務和緩存,進行優化,并在spark叢集上運作任務。rdd之間的依賴分為寬依賴(依賴多個分區)和窄依賴(隻依賴一個分區),在确定階段時,需要根據寬依賴劃分階段。根據分區劃分任務。
spark為疊代式資料處理提供更好的支援。每次疊代的資料可以儲存在記憶體中,而不是寫入檔案。
spark的性能相比hadoop有很大提升,2014年10月,spark完成了一個daytona gray類别的sort benchmark測試,排序完全是在磁盤上進行的,與hadoop之前的測試的對比結果如表格所示:
原圖連結位址:http://databricks.com/blog/2014/11/05/spark-officially-sets-a-new-record-in-large-scale-sorting.html
從表格中可以看出排序100tb的資料(1萬億條資料),spark隻用了hadoop所用1/10的計算資源,耗時隻有hadoop的1/3。
spark的優勢不僅展現在性能提升上的,spark架構為批處理(spark core),互動式(spark sql),流式(spark
streaming),機器學習(mllib),圖計算(graphx)提供一個統一的平台,這相對于使用hadoop有很大優勢。
那麼spark解決了hadoop的哪些問題?
抽象層次低,需要手工編寫代碼來完成,使用上難以上手。
=>基于rdd的抽象,實資料處理邏輯的代碼非常簡短。
隻提供兩個操作,map和reduce,表達力欠缺。
=>提供很多轉換和動作,很多基本操作如join,groupby已經在rdd轉換和動作中實作。
一個job隻有map和reduce兩個階段,複雜的計算需要大量的job完成,job之間的依賴關系是由開發者自己管理的。
=>一個job可以包含rdd的多個轉換操作,在排程時可以生成多個階段,而且如果多個map操作的rdd的分區不變,是可以放在同一個task中進行。
處理邏輯隐藏在代碼細節中,沒有整體邏輯。
=>在scala中,通過匿名函數和高階函數,rdd的轉換支援流式api,可以提供處理邏輯的整體視圖。
代碼不包含具體操作的實作細節,邏輯更清晰。 中間結果也放在hdfs檔案系統中。
=>中間結果放在記憶體中,記憶體放不下了會寫入本地磁盤,而不是hdfs。
reducetask需要等待所有maptask都完成後才可以開始
=>它允許使用者單獨為map task和reduce task設定不同的資源,進而細粒度控制任務占用資源量,有利于大作業的正常平穩運作。
=>通過将流拆成小的batch提供discretized stream處理流資料。
=>通過在記憶體中緩存資料,提高疊代式計算的性能。
這篇文章就分享到這裡,若在研究的過程中有什麼疑問,可以加群讨論或發送郵件給我,我會盡我所能為您解答,與君共勉!