【干貨】大數(shù)據(jù)入門:SparkCore開發(fā)調(diào)優(yōu)原則

加米谷大數(shù)據(jù)張老師
Spark在大數(shù)據(jù)領(lǐng)域,能夠?qū)崿F(xiàn)離線批處理、SQL類處理、流式/實(shí)時(shí)計(jì)算、機(jī)器學(xué)習(xí)、圖計(jì)算等各種不同類型的計(jì)算操作,對(duì)于企業(yè)而言是低成本下的可靠性選擇,但是想要真正用好Spark,實(shí)現(xiàn)真正的高性能,調(diào)優(yōu)是不可或缺的手段。

大數(shù)據(jù)計(jì)算引擎當(dāng)中,Spark受到的重視是越來越多的,尤其是對(duì)數(shù)據(jù)處理實(shí)時(shí)性的要求越來越高,Hadoop原生的MapReduce引擎受到詬病,Spark的性能也需要不斷調(diào)整優(yōu)化。今天的大數(shù)據(jù)入門分享,我們就來講講SparkCore開發(fā)調(diào)優(yōu)原則。

11.jpeg

Spark在大數(shù)據(jù)領(lǐng)域,能夠?qū)崿F(xiàn)離線批處理、SQL類處理、流式/實(shí)時(shí)計(jì)算、機(jī)器學(xué)習(xí)、圖計(jì)算等各種不同類型的計(jì)算操作,對(duì)于企業(yè)而言是低成本下的可靠性選擇,但是想要真正用好Spark,實(shí)現(xiàn)真正的高性能,調(diào)優(yōu)是不可或缺的手段。

SparkCore開發(fā)調(diào)優(yōu)原則

1、避免創(chuàng)建重復(fù)的RDD

通常來說,我們?cè)陂_發(fā)一個(gè)Spark作業(yè)時(shí),首先是基于某個(gè)數(shù)據(jù)源(比如Hive表或HDFS文件)創(chuàng)建一個(gè)初始的RDD;接著對(duì)這個(gè)RDD執(zhí)行某個(gè)算子操作,然后得到下一個(gè)RDD;以此類推,循環(huán)往復(fù),直到計(jì)算出最終我們需要的結(jié)果。

我們?cè)陂_發(fā)過程中要注意:對(duì)于同一份數(shù)據(jù),只應(yīng)該創(chuàng)建一個(gè)RDD,不能創(chuàng)建多個(gè)RDD來代表同一份數(shù)據(jù)。否則,我們的Spark作業(yè)會(huì)進(jìn)行多次重復(fù)計(jì)算來創(chuàng)建多個(gè)代表相同數(shù)據(jù)的RDD,進(jìn)而增加作業(yè)的性能開銷。

2、盡可能復(fù)用同一個(gè)RDD

除了要避免在開發(fā)過程中對(duì)一份完全相同的數(shù)據(jù)創(chuàng)建多個(gè)RDD之外,在對(duì)不同的數(shù)據(jù)執(zhí)行算子操作時(shí)還要盡可能地復(fù)用一個(gè)RDD。

尤其對(duì)于類似這種多個(gè)RDD的數(shù)據(jù)有重疊或者包含的情況,盡量復(fù)用一個(gè)RDD,這樣可以盡可能地減少RDD的數(shù)量,從而盡可能減少算子執(zhí)行的次數(shù)。

3、對(duì)多次使用的RDD進(jìn)行持久化

Spark中對(duì)于一個(gè)RDD執(zhí)行多次算子的默認(rèn)原理是這樣的:每次你對(duì)一個(gè)RDD執(zhí)行一個(gè)算子操作時(shí),都會(huì)重新從源頭處計(jì)算一遍,計(jì)算出那個(gè)RDD來,然后再對(duì)這個(gè)RDD執(zhí)行你的算子操作。這種方式的性能是很差的。

而對(duì)多次使用的RDD進(jìn)行持久化,Spark就會(huì)根據(jù)你的持久化策略,將RDD中的數(shù)據(jù)保存到內(nèi)存或者磁盤中。以后每次對(duì)這個(gè)RDD進(jìn)行算子操作時(shí),都會(huì)直接從內(nèi)存或磁盤中提取持久化的RDD數(shù)據(jù),然后執(zhí)行算子,而不會(huì)從源頭處重新計(jì)算一遍這個(gè)RDD,再執(zhí)行算子操作。

22.jpeg

4、盡量避免使用shuffle類算子

如果有可能的話,要盡量避免使用shuffle類算子。因?yàn)镾park作業(yè)運(yùn)行過程中,最消耗性能的地方就是shuffle過程。shuffle過程,簡單來說,就是將分布在集群中多個(gè)節(jié)點(diǎn)上的同一個(gè)key,拉取到同一個(gè)節(jié)點(diǎn)上,進(jìn)行聚合或join等操作。

比如reduceByKey、join等算子,都會(huì)觸發(fā)shuffle操作。沒有shuffle操作或者僅有較少shuffle操作的Spark作業(yè),可以大大減少性能開銷。

5、使用map-side預(yù)聚合的shuffle操作

如果因?yàn)闃I(yè)務(wù)需要,一定要使用shuffle操作,無法用map類的算子來替代,那么盡量使用可以map-side預(yù)聚合的算子。

所謂的map-side預(yù)聚合,說的是在每個(gè)節(jié)點(diǎn)本地對(duì)相同的key進(jìn)行一次聚合操作,類似于MapReduce中的本地combiner。map-side預(yù)聚合之后,每個(gè)節(jié)點(diǎn)本地就只會(huì)有一條相同的key,因?yàn)槎鄺l相同的key都被聚合起來了。其他節(jié)點(diǎn)在拉取所有節(jié)點(diǎn)上的相同key時(shí),就會(huì)大大減少需要拉取的數(shù)據(jù)數(shù)量,從而也就減少了磁盤IO以及網(wǎng)絡(luò)傳輸開銷。

6、使用高性能的算子

除了shuffle相關(guān)的算子有優(yōu)化原則之外,其他的算子也都有著相應(yīng)的優(yōu)化原則。

比如說使用reduceByKey/aggregateByKey替代groupByKey;使用mapPartitions替代普通map;使用foreachPartitions替代foreach;使用filter之后進(jìn)行coalesce操作;使用repartitionAndSortWithinPartitions替代repartition與sort類操作等。

33.jpeg

7、廣播大變量

在開發(fā)過程中,有時(shí)會(huì)遇到需要在算子函數(shù)中使用外部變量的場(chǎng)景(尤其是大變量,比如100M以上的大集合),那么此時(shí)就應(yīng)該使用Spark的廣播(Broadcast)功能來提升性能。

在算子函數(shù)中使用到外部變量時(shí),默認(rèn)情況下,Spark會(huì)將該變量復(fù)制多個(gè)副本,通過網(wǎng)絡(luò)傳輸?shù)絫ask中,此時(shí)每個(gè)task都有一個(gè)變量副本。如果變量本身比較大的話(比如100M,甚至1G),那么大量的變量副本在網(wǎng)絡(luò)中傳輸?shù)男阅荛_銷,以及在各個(gè)節(jié)點(diǎn)的Executor中占用過多內(nèi)存導(dǎo)致的頻繁GC,都會(huì)極大地影響性能。

8、使用Kryo優(yōu)化序列化性能

在Spark中,主要有三個(gè)地方涉及到了序列化:

在算子函數(shù)中使用到外部變量時(shí),該變量會(huì)被序列化后進(jìn)行網(wǎng)絡(luò)傳輸。

將自定義的類型作為RDD的泛型類型時(shí)(比如JavaRDD,Student是自定義類型),所有自定義類型對(duì)象,都會(huì)進(jìn)行序列化。因此這種情況下,也要求自定義的類必須實(shí)現(xiàn)Serializable接口。

使用可序列化的持久化策略時(shí)(比如MEMORY_ONLY_SER),Spark會(huì)將RDD中的每個(gè)partition都序列化成一個(gè)大的字節(jié)數(shù)組。

對(duì)于這三種出現(xiàn)序列化的地方,我們都可以通過使用Kryo序列化類庫,來優(yōu)化序列化和反序列化的性能。

關(guān)于大數(shù)據(jù)入門,SparkCore開發(fā)調(diào)優(yōu)原則,以上就為大家做了簡單的介紹了。SparkCore作為Spark的核心部分,要真正掌握Spark框架,那么核心部分一定要吃透。

THEEND

最新評(píng)論(評(píng)論僅代表用戶觀點(diǎn))

更多
暫無評(píng)論