Spark的誤解-不僅Spark是內(nèi)存計(jì)算,Hadoop也是內(nèi)存計(jì)算
市面上有一些初學(xué)者的誤解,他們拿Spark和Hadoop比較時(shí)就會(huì)說(shuō),Spark是內(nèi)存計(jì)算,內(nèi)存計(jì)算是Spark的特性。請(qǐng)問(wèn)在計(jì)算機(jī)領(lǐng)域,MySQL,Redis,SSH框架等等他們不是內(nèi)存計(jì)算嗎?依據(jù)馮諾依曼體系結(jié)構(gòu),有什么技術(shù)的程序不是在內(nèi)存中運(yùn)行,需要數(shù)據(jù)從硬盤中拉取,然后供CPU進(jìn)行執(zhí)行?所有說(shuō)Spark的特點(diǎn)是內(nèi)存計(jì)算相當(dāng)于什么都沒(méi)有說(shuō)。
那么Spark的真正特點(diǎn)是什么?拋開Spark的執(zhí)行模型的方式,它的特點(diǎn)無(wú)非就是多個(gè)任務(wù)之間數(shù)據(jù)通信不需要借助硬盤而是通過(guò)內(nèi)存,大大提高了程序的執(zhí)行效率。而Hadoop由于本身的模型特點(diǎn),多個(gè)任務(wù)之間數(shù)據(jù)通信是必須借助硬盤落地的。那么Spark的特點(diǎn)就是數(shù)據(jù)交互不會(huì)走硬盤。只能說(shuō)多個(gè)任務(wù)的數(shù)據(jù)交互不走硬盤,但是Spark的shuffle過(guò)程和Hadoop一樣仍然必須走硬盤的。
誤解一:Spark是一種內(nèi)存技術(shù)
大家對(duì)Spark***的誤解就是spark一種內(nèi)存技術(shù)。其實(shí)沒(méi)有一個(gè)Spark開發(fā)者正式說(shuō)明這個(gè),這是對(duì)Spark計(jì)算過(guò)程的誤解。Spark是內(nèi)存計(jì)算沒(méi)有錯(cuò)誤,但是這并不是它的特性,只是很多專家在介紹spark的特性時(shí),簡(jiǎn)化后就成了spark是內(nèi)存計(jì)算。
什么樣是內(nèi)存技術(shù)?就是允許你將數(shù)據(jù)持久化在RAM中并有效處理的技術(shù)。然而Spark并不具備將數(shù)據(jù)數(shù)據(jù)存儲(chǔ)在RAM的選項(xiàng),雖然我們都知道可以將數(shù)據(jù)存儲(chǔ)在HDFS, HBase等系統(tǒng)中,但是不管是將數(shù)據(jù)存儲(chǔ)在磁盤還是內(nèi)存,都沒(méi)有內(nèi)置的持久化代碼。它所能做的事就是緩存數(shù)據(jù),而這個(gè)并不是數(shù)據(jù)持久化。已經(jīng)緩存的數(shù)據(jù)可以很容易地被刪除,并且在后期需要時(shí)重新計(jì)算。
但是有人還是會(huì)認(rèn)為Spark就是一種基于內(nèi)存的技術(shù),因?yàn)镾park是在內(nèi)存中處理數(shù)據(jù)的。這當(dāng)然是對(duì)的,因?yàn)槲覀儫o(wú)法使用其他方式來(lái)處理數(shù)據(jù)。操作系統(tǒng)中的API都只能讓你把數(shù)據(jù)從塊設(shè)備加載到內(nèi)存,然后計(jì)算完的結(jié)果再存儲(chǔ)到塊設(shè)備中。我們無(wú)法直接在HDD設(shè)備上計(jì)算;所以現(xiàn)代系統(tǒng)中的所有處理基本上都是在內(nèi)存中進(jìn)行的。
然Spark允許我們使用內(nèi)存緩存以及LRU替換規(guī)則,但是你想想現(xiàn)在的RDBMS系統(tǒng),比如Oracle ,你認(rèn)為它們是如何處理數(shù)據(jù)的?它們使用共享內(nèi)存段作為table pages的存儲(chǔ)池,所有的數(shù)據(jù)讀取以及寫入都是通過(guò)這個(gè)池的,這個(gè)存儲(chǔ)池同樣支持LRU替換規(guī)則;所有現(xiàn)代的數(shù)據(jù)庫(kù)同樣可以通過(guò)LRU策略來(lái)滿足大多數(shù)需求。但是為什么我們并沒(méi)有把Oracle 稱作是基于內(nèi)存的解決方案呢?再想想操作系統(tǒng)IO,你知道嗎?所有的IO操作也是會(huì)用到LRU緩存技術(shù)的。
Spark在內(nèi)存中處理所有的操作嗎?Spark的核心:shuffle,其就是將數(shù)據(jù)寫入到磁盤的。shuffle的處理包括兩個(gè)階段:map 和 reduce。Map操作僅僅根據(jù)key計(jì)算其哈希值,并將數(shù)據(jù)存放到本地文件系統(tǒng)的不同文件中,文件的個(gè)數(shù)通常是reduce端分區(qū)的個(gè)數(shù);Reduce端會(huì)從 Map端拉取數(shù)據(jù),并將這些數(shù)據(jù)合并到新的分區(qū)中。所有如果你的RDD有M個(gè)分區(qū),然后你將其轉(zhuǎn)換成N個(gè)分區(qū)的PairRDD,那么在shuffle階段將會(huì)創(chuàng)建 M*N 個(gè)文件!雖然目前有些優(yōu)化策略可以減少創(chuàng)建文件的個(gè)數(shù),但這仍然無(wú)法改變每次進(jìn)行shuffle操作的時(shí)候你需要將數(shù)據(jù)先寫入到磁盤的事實(shí)!
所以結(jié)論是:Spark并不是基于內(nèi)存的技術(shù)!它其實(shí)是一種可以有效地使用內(nèi)存LRU策略的技術(shù)。
誤解二:Spark要比Hadoop快 10x-100x
大家在Spark的官網(wǎng)肯定看到了如下所示的圖片
這個(gè)圖片是分別使用 Spark 和 Hadoop 運(yùn)行邏輯回歸(Logistic Regression)機(jī)器學(xué)習(xí)算法的運(yùn)行時(shí)間比較,從上圖可以看出Spark的運(yùn)行速度明顯比Hadoop快上百倍!但是實(shí)際上是這樣的嗎?大多數(shù)機(jī)器學(xué)習(xí)算法的核心部分是什么?其實(shí)就是對(duì)同一份數(shù)據(jù)集進(jìn)行相同的迭代計(jì)算,而這個(gè)地方正是Spark的LRU算法所驕傲的地方。當(dāng)你多次掃描相同的數(shù)據(jù)集時(shí),你只需要在***訪問(wèn)時(shí)加載它到內(nèi)存,后面的訪問(wèn)直接從內(nèi)存中獲取即可。這個(gè)功能非常的棒!但是很遺憾的是,官方在使用Hadoop運(yùn)行邏輯回歸的時(shí)候很大可能沒(méi)有使用到HDFS的緩存功能,而是采用極端的情況。如果在Hadoop中運(yùn)行邏輯回歸的時(shí)候采用到HDFS緩存功能,其表現(xiàn)很可能只會(huì)比Spark差3x-4x,而不是上圖所展示的一樣。
根據(jù)經(jīng)驗(yàn),企業(yè)所做出的基準(zhǔn)測(cè)試報(bào)告一般都是不可信的!一般獨(dú)立的第三方基準(zhǔn)測(cè)試報(bào)告是比較可信的,比如:TPC-H。他們的基準(zhǔn)測(cè)試報(bào)告一般會(huì)覆蓋絕大部分場(chǎng)景,以便真實(shí)地展示結(jié)果。
一般來(lái)說(shuō),Spark比MapReduce運(yùn)行速度快的原因主要有以下幾點(diǎn):
- task啟動(dòng)時(shí)間比較快,Spark是fork出線程;而MR是啟動(dòng)一個(gè)新的進(jìn)程;
- 更快的shuffles,Spark只有在shuffle的時(shí)候才會(huì)將數(shù)據(jù)放在磁盤,而MR卻不是。
- 更快的工作流:典型的MR工作流是由很多MR作業(yè)組成的,他們之間的數(shù)據(jù)交互需要把數(shù)據(jù)持久化到磁盤才可以;而Spark支持DAG以及pipelining,在沒(méi)有遇到shuffle完全可以不把數(shù)據(jù)緩存到磁盤。
- 緩存:雖然目前HDFS也支持緩存,但是一般來(lái)說(shuō),Spark的緩存功能更加高效,特別是在SparkSQL中,我們可以將數(shù)據(jù)以列式的形式儲(chǔ)存在內(nèi)存中。
所有的這些原因才使得Spark相比Hadoop擁有更好的性能表現(xiàn);在比較短的作業(yè)確實(shí)能快上100倍,但是在真實(shí)的生產(chǎn)環(huán)境下,一般只會(huì)快 2.5x ~ 3x!
版權(quán)聲明:
作者:劉洋 合作微信號(hào):intsmaze 本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。