什么是spark的惰性计算?有什么优势?_spark——spark中常说RDD,究竟RDD是什么?
本文始發(fā)于個(gè)人公眾號(hào):TechFlow,原創(chuàng)不易,求個(gè)關(guān)注
今天是spark專題第二篇文章,我們來看spark非常重要的一個(gè)概念——RDD。
在上一講當(dāng)中我們?cè)诒镜匕惭b好了spark,雖然我們只有l(wèi)ocal一個(gè)集群,但是仍然不妨礙我們進(jìn)行實(shí)驗(yàn)。spark最大的特點(diǎn)就是無論集群的資源如何,進(jìn)行計(jì)算的代碼都是一樣的,spark會(huì)自動(dòng)為我們做分布式調(diào)度工作。
RDD概念
介紹spark離不開RDD,RDD是其中很重要的一個(gè)部分。但是很多初學(xué)者往往都不清楚RDD究竟是什么,我自己也是一樣,我在系統(tǒng)學(xué)習(xí)spark之前代碼寫了一堆,但是對(duì)于RDD等概念仍然云里霧里。
RDD的英文全名是Resilient Distributed Dataset,我把英文寫出來就清楚了很多。即使第一個(gè)單詞不認(rèn)識(shí),至少也可以知道它是一個(gè)分布式的數(shù)據(jù)集。第一個(gè)單詞是彈性的意思,所以直譯就是彈性分布式數(shù)據(jù)集。雖然我們還是不夠清楚,但是已經(jīng)比只知道RDD這個(gè)概念清楚多了,
RDD是一個(gè)不可變的分布式對(duì)象集合,每個(gè)RDD都被分為多個(gè)分區(qū),這些分區(qū)運(yùn)行在集群的不同節(jié)點(diǎn)上。
很多資料里只有這么一句粗淺的解釋,看起來說了很多,但是我們都get不到。細(xì)想有很多疑問,最后我在大神的博客里找到了詳細(xì)的解釋,這位大神翻了spark的源碼,找到了其中RDD的定義,一個(gè)RDD當(dāng)中包含以下內(nèi)容:
- A list of partitions
- A function for computing each split
- A list of dependencies on other RDDs
- Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned)
- Optionally, a list of preferred locations to compute each split on (e.g. block locations for an HDFS file)
我們一條一條來看:
通過以上五點(diǎn),我們可以看出spark一個(gè)重要的理念。即移動(dòng)數(shù)據(jù)不如移動(dòng)計(jì)算,也就是說在spark運(yùn)行調(diào)度的時(shí)候,會(huì)傾向于將計(jì)算分發(fā)到節(jié)點(diǎn),而不是將節(jié)點(diǎn)的數(shù)據(jù)搜集起來計(jì)算。RDD正是基于這一理念而生的,它做的也正是這樣的事情。
創(chuàng)建RDD
spark中提供了兩種方式來創(chuàng)建RDD,一種是讀取外部的數(shù)據(jù)集,另一種是將一個(gè)已經(jīng)存儲(chǔ)在內(nèi)存當(dāng)中的集合進(jìn)行并行化。
我們一個(gè)一個(gè)來看,最簡(jiǎn)單的方式當(dāng)然是并行化,因?yàn)檫@不需要外部的數(shù)據(jù)集,可以很輕易地做到。
在此之前,我們先來看一下SparkContext的概念,SparkContext是整個(gè)spark的入口,相當(dāng)于程序的main函數(shù)。在我們啟動(dòng)spark的時(shí)候,spark已經(jīng)為我們創(chuàng)建好了一個(gè)SparkContext的實(shí)例,命名為sc,我們可以直接訪問到。
我們要?jiǎng)?chuàng)建RDD也需要基于sc進(jìn)行,比如下面我要?jiǎng)?chuàng)建一個(gè)有字符串構(gòu)成的RDD:
texts = sc.parallelize(['now test', 'spark rdd'])返回的texts就是一個(gè)RDD:
除了parallelize之外呢,我們還可以從外部數(shù)據(jù)生成RDD,比如我想從一個(gè)文件讀入,可以使用sc當(dāng)中的textFile方法獲取:
text = sc.textFile('/path/path/data.txt')一般來說,除了本地調(diào)試我們很少會(huì)用parallelize進(jìn)行創(chuàng)建RDD,因?yàn)檫@需要我們先把數(shù)據(jù)讀取在內(nèi)存。由于內(nèi)存的限制,使得我們很難將spark的能力發(fā)揮出來。
轉(zhuǎn)化操作和行動(dòng)操作
剛才我們?cè)诮榻BRDD的時(shí)候其實(shí)提到過,RDD支持兩種操作,一種叫做轉(zhuǎn)化操作(transformation)一種叫做行動(dòng)操作(action)。
顧名思義,執(zhí)行轉(zhuǎn)化操作的時(shí)候,spark會(huì)將一個(gè)RDD轉(zhuǎn)化成另一個(gè)RDD。RDD中會(huì)將我們這次轉(zhuǎn)化的內(nèi)容記錄下來,但是不會(huì)進(jìn)行運(yùn)算。所以我們得到的仍然是一個(gè)RDD而不是執(zhí)行的結(jié)果。
比如我們創(chuàng)建了texts的RDD之后,我們想要對(duì)其中的內(nèi)容進(jìn)行過濾,只保留長(zhǎng)度超過8的,我們可以用filter進(jìn)行轉(zhuǎn)化:
textAfterFilter = texts.filter(lambda x: len(x) > 8)我們調(diào)用之后得到的也是一個(gè)RDD,就像我們剛才說的一樣,由于filter是一個(gè)轉(zhuǎn)化操作,所以spark只會(huì)記錄下它的內(nèi)容,并不會(huì)真正執(zhí)行。
轉(zhuǎn)化操作可以操作任意數(shù)量的RDD,比如如果我執(zhí)行如下操作,會(huì)一共得到4個(gè)RDD:
inputRDD = sc.textFile('path/path/log.txt') lengthRDD = inputRDD.filter(lambda x: len(x) > 10) errorRDD = inputRDD.filter(lambda x: 'error' in x) unionRDD = errorRDD.union(lengthRDD)最后的union會(huì)將兩個(gè)RDD的結(jié)果組合在一起,如果我們執(zhí)行完上述代碼之后,spark會(huì)記錄下這些RDD的依賴信息,我們把這個(gè)依賴信息畫出來,就成了一張依賴圖:
無論我們執(zhí)行多少次轉(zhuǎn)化操作,spark都不會(huì)真正執(zhí)行其中的操作,只有當(dāng)我們執(zhí)行行動(dòng)操作時(shí),記錄下來的轉(zhuǎn)化操作才會(huì)真正投入運(yùn)算。像是first(),take(),count()等都是行動(dòng)操作,這時(shí)候spark就會(huì)給我們返回計(jì)算結(jié)果了。
其中first的用處是返回第一個(gè)結(jié)果,take需要傳入一個(gè)參數(shù),指定返回的結(jié)果條數(shù),count則是計(jì)算結(jié)果的數(shù)量。和我們逾期的一樣,當(dāng)我們執(zhí)行了這些操作之后,spark為我們返回了結(jié)果。
本文著重講的是RDD的概念,我們下篇文章還會(huì)著重對(duì)轉(zhuǎn)化操作和行動(dòng)操作進(jìn)行深入解讀。感興趣的同學(xué)不妨期待一下吧~
今天的文章就是這些,如果覺得有所收獲,請(qǐng)順手點(diǎn)個(gè)關(guān)注或者轉(zhuǎn)發(fā)吧,你們的舉手之勞對(duì)我來說很重要。
總結(jié)
以上是生活随笔為你收集整理的什么是spark的惰性计算?有什么优势?_spark——spark中常说RDD,究竟RDD是什么?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 戴尔电脑怎么安装一级计算机,手把手教你戴
- 下一篇: 灯效控制器和rgb控制器_更具个性的RG