從零開始學(xué)習(xí)Spark(七)Spark編程進(jìn)階

Spark編程進(jìn)階

這一部分將介紹一些沒有提到的一些Spark的特性,都是非常有用的,內(nèi)容之間關(guān)聯(lián)性不是很強(qiáng)。主要包括,共享變量,分區(qū)操作,調(diào)用腳本以及統(tǒng)計(jì)操作。

1. 共享變量之累加器

通常在向 Spark 傳遞函數(shù)時(shí),比如使用map()函數(shù)或者用filter()傳條件時(shí),可以使用驅(qū) 動(dòng)器程序中定義的變量,但是集群中運(yùn)行的每個(gè)任務(wù)都會(huì)得到這些變量的一份新的副本, 更新這些副本的值也不會(huì)影響驅(qū)動(dòng)器中的對應(yīng)變量。

下面這段scala程序讀取文件的同時(shí)統(tǒng)計(jì)了空白行的數(shù)量

val sc = new SparkContext(...)
val file = sc.textFile("file.txt")
val blankLines = sc.accumulator(0) // 創(chuàng)建Accumulator[Int]并初始化為0
val callSigns = file.flatMap(line => {
  if (line == "") {
    blankLines += 1 // 累加器加1
  }
  line.split(" ")
})
callSigns.saveAsTextFile("output.txt")
println("Blank lines: " + blankLines.value)

注意,工作節(jié)點(diǎn)上的任務(wù)不能訪問累加器的值。我的理解是轉(zhuǎn)化操作都是惰性操作,使用累加器的值存在同步問題。

2. 共享變量之廣播變量

Spark的第二種共享變量類型是廣播變量,它可以讓程序高效地向所有工作節(jié)點(diǎn)發(fā)送一個(gè) 較大的只讀值,以供一個(gè)或多個(gè)Spark操作使用

廣播變量為只讀變量,它由運(yùn)行SparkContext的驅(qū)動(dòng)程序創(chuàng)建后發(fā)送給會(huì)參與計(jì)算的節(jié)點(diǎn)。

廣播變量可以被非驅(qū)動(dòng)程序所在的節(jié)點(diǎn)(即工作節(jié)點(diǎn))訪問,訪問的方法是用該廣播變量的value方法。

val broadcastAList = sc.broadcast(List("a", "b", "c", "d", "e"))
sc.parallelize(List("1", "2", "3")).map(x => broadcastAList.value ++ x).collect

3. 基于分區(qū)的操作

基于分區(qū)對數(shù)據(jù)進(jìn)行操作可以讓我們避免為每個(gè)數(shù)據(jù)元素進(jìn)行重復(fù)的配置工作。諸如打開 數(shù)據(jù)庫連接或創(chuàng)建隨機(jī)數(shù)生成器等操作,都是我們應(yīng)當(dāng)盡量避免為每個(gè)元素都配置一次的 工作。Spark 提供基于分區(qū)的map和foreach,讓你的部分代碼只對RDD的每個(gè)分區(qū)運(yùn)行 一次,這樣可以幫助降低這些操作的代價(jià)。

4. 與外部程序間的管道

如果Scala、Java以及Python都不能實(shí)現(xiàn)你需要的功能,那么Spark也為這種情況提供了一種通用機(jī)制,可以將數(shù)據(jù)通過管道傳給用其他語言編寫的程序,比如R語言腳本。

有點(diǎn)類似Hadoop的Streaming

5. 數(shù)值RDD操作

Spark 對包含數(shù)值數(shù)據(jù)的RDD提供了一些描述性的統(tǒng)計(jì)操作。

之前已經(jīng)使用過的類似rdd.count()的操作,Spark提供了一系列的操作,如果需要用到多個(gè)操作的話建議先調(diào)用rdd.stats()將這些值通過一次遍歷全部計(jì)算出來。

Spark包含的統(tǒng)計(jì)值有:

count() RDD 中的元素個(gè)數(shù) 
mean() 元素的平均值 
sum() 總和
max() 最大值
min() 最小值
variance() 元素的方差 
sampleVariance() 從采樣中計(jì)算出的方差 
stdev() 標(biāo)準(zhǔn)差
sampleStdev() 采樣的標(biāo)準(zhǔn)差

下面這個(gè)例子用來篩選掉異常值

val distanceDouble = distance.map(string => string.toDouble)
val stats = distanceDoubles.stats()
val stddev = stats.stdev
val mean = stats.mean
val reasonableDistances = distanceDoubles.filter(x => math.abs(x-mean) < 3 * stddev) println(reasonableDistance.collect().toList)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容