更新時間:2021年01月29日15時08分 來源:傳智教育 瀏覽次數(shù):
在分布式程序中,網(wǎng)絡(luò)通信的開銷是很大的,因此控制數(shù)據(jù)分布以獲得最少的網(wǎng)絡(luò)傳輸開銷可以極大地提升整體性能.Spark程序可以通過控制RDD分區(qū)方式來減少通信開銷。Spark中所有的RDD都可以進行分區(qū),系統(tǒng)會根據(jù)一個針對鍵的函數(shù)對元素進行分區(qū)。雖然Spark不能控制每個鍵具體劃分到哪個節(jié)點上,但是可以確保相同的鍵出現(xiàn)在同一個分區(qū)上。RDD的分區(qū)原則是分區(qū)的個數(shù)盡量等于集群中的CPU核心(Core)數(shù)目。對于不同的Spark部署模式而言,都可以通過設(shè)置spark.default.prallien這個參數(shù)值來配置默認的分區(qū)數(shù)目。一般而言,各種模式下的默認分區(qū)數(shù)目如下。
(1) Local模式:默認為本地機器的CPU數(shù)目,若設(shè)置了loca[N],則默認為N。
(2) Standalone或者Yarn模式:在“集群中所有CPU核數(shù)總和”和“2”這兩者中取較大值作為默認值。
(3) Mesos 模式:默認的分區(qū)數(shù)是8。
Spark框架為RDD提供了兩種分區(qū)方式,分別是哈希分區(qū)(HashPartitioner)和范圍分區(qū)(RangePartitioner)。其中,哈希分區(qū)是根據(jù)哈希值進行分區(qū);范圍分區(qū)是將一定范圍的數(shù)據(jù)映射到一個分區(qū)中。這兩種分區(qū)方式已經(jīng)可以滿足大多數(shù)應(yīng)用場景的需求。與此同時,Spark也支持自定義分區(qū)方式,即通過一個自定義的Partitioner對象來控制RDD的分區(qū),從而進一步減少通信開銷。 需要注意的是,RDD的分區(qū)函數(shù)是針對(Key, Value)類型的RDD,分區(qū)函數(shù)根據(jù)Key對RDD元素進行分區(qū)。因此,當需要對一些非(Key,Value)類型的RDD進行自定義分區(qū)時,需要先把RDD元素轉(zhuǎn)換為(Key,Value)類型,再通過分區(qū)函數(shù)進行分區(qū)操作。
如果想要實現(xiàn)自定義分區(qū),就需要定義一個類,使得這個自定義的類繼承org. apache.spark. Partitioner類,并實現(xiàn)其中的3個方法,具體如下。
(1) def numPartitions:Int:用于返回創(chuàng)建的分區(qū)個數(shù)。
(2) def getPartition(Key:Any):用于對輸人的Key做處理,并返回該Key的分區(qū)ID,分區(qū)ID的范圍是0~ numPartitions 1。
(3) equals (other: Any):用于Spark判斷自定義的Partitioner對象和其他的Partitioner 對象是否相同,從而判斷兩個RDD的分區(qū)方式是否相同。其中,equals()方法中的參數(shù)other表示其他的Partitioner 對象,該方法的返回值是一個Boolean類型,當返回值為true時表示自定義的Pritioer對象和其他Pritioer對象相同,則兩個RDD的分區(qū)方式也是相同的;反之,自定義的Pritoner對象和其他Prtitioer對象不相同,則兩個RDD的分區(qū)方式也不相同。