Spark基礎 之 Partition

本文是Spark知識總結帖,講述Spark Partition相關內容。

 

1 什麼是Partition 

Spark RDD 是一種分佈式的數據集,由於數據量很大,因此要它被切分並存儲在各個結點的分區當中。從而當我們對RDD進行操作時,實際上是對每個分區中的數據並行操作。

圖一:數據如何被分區並存儲到各個結點

 

                                                 圖二:RDD、Partition以及task的關係

 

參考: https://blog.csdn.net/zhangzeyuan56/article/details/80935034
 

 

2 Partition定義和初始化

查看spark源碼,trait Partition的定義很簡單,序列號index和hashCode方法。Partition和RDD是伴生的,即每一種RDD都有其對應的Partition實現,所以,分析Partition主要是分析其子類。我們關注兩個常用的子類,JdbcPartition和HadoopPartition。此外,RDD源碼中有5個方法,代表其組成,如下:

第二個方法,getPartitions是數據源如何被切分的邏輯,返回值正是Partition,第一個方法compute是消費切割後的Partition的方法,所以學習Partition,要結合getPartitions和compute方法。

JdbcPartition例子
下面是Spark JdbcRDDSuite中一個例子

val sc = new SparkContext("local[1]", "test")
val rdd = new JdbcRDD(
sc,
() => { DriverManager.getConnection("jdbc:derby:target/JdbcRDDSuiteDb") },
// DATA類型爲INTEGER
"SELECT DATA FROM FOO WHERE ? <= ID AND ID <= ?",
1, 100, 3,
(r: ResultSet) => { r.getInt(1) } ).count()

查看JdbcPartition實現,相比Partition,主要多了lower和upper這兩個字段。

查看JdbcRDD的getPartitions,按照如上圖所示算法將1到100分爲3份(partition數量),結果爲(1,33)、(34,66)、(67,100),封裝爲JdbcPartition並返回,這樣數據切分的部分就完成了。

查看JdbcRDD的compute方法,邏輯清晰,將Partition強轉爲JdbcPartition,獲取連接並預處理sql,將
例子中的”SELECT DATA FROM FOO WHERE ? <= ID AND ID <= ?”問號分別用Partition的lower和upper替換(即getPartitions切分好的(1,33)、(34,66)、(67,100))並執行查詢。至此,JdbcPartition如何發揮作用就分析完了。


參考:https://blog.csdn.net/u011564172/article/details/53611109

 

 

3 Partitioner 定義和用途

 

HashPartitioner簡介     

HashPartitioner採用哈希的方式對<Key,Value>鍵值對數據進行分區。其數據分區規則爲 partitionId = Key.hashCode % numPartitions,其中partitionId代表該Key對應的鍵值對數據應當分配到的Partition標識,Key.hashCode表示該Key的哈希值,numPartitions表示包含的Partition個數。圖3簡單描述了HashPartitioner的數據分區過程。

 

RangePartitioner簡介     

Spark引入RangePartitioner的目的是爲了解決HashPartitioner所帶來的分區傾斜問題,也即分區中包含的數據量不均衡問題。HashPartitioner採用哈希的方式將同一類型的Key分配到同一個Partition中,因此當某一或某幾種類型數據量較多時,就會造成若干Partition中包含的數據過大問題,而在Job執行過程中,一個Partition對應一個Task,此時就會使得某幾個Task運行過慢。RangePartitioner基於抽樣的思想來對數據進行分區。圖4簡單描述了RangePartitioner的數據分區過程。

Partitioner 用途

主要用在groupByKey, reduceByKey, repartition(n)這些需要shuffle操作的過程中。

 

參考: https://www.cnblogs.com/tongxupeng/p/10435976.html

https://www.jianshu.com/p/391d42665a30

 

4 Partition 參數設置

Partition數量的影響

Partition數量太少
太少的影響顯而易見,就是資源不能充分利用,例如local模式下,有16core,但是Partition數量僅爲8的話,有一半的core沒利用到。
Partition數量太多
太多,資源利用沒什麼問題,但是導致task過多,task的序列化和傳輸的時間開銷增大。
那麼多少的partition數是合適的呢,這裏我們參考spark doc給出的建議,Typically you want 2-4 partitions for each CPU in your cluster。
 

爲什麼不是partition數目不是和core 數量 1:1?

個人認爲,是partition對於的task直接有先後銜接關係,map -> transfer -> reduce 這樣兩到三個task可以同時在一個core上運行。

 

參考:https://spark.apache.org/docs/latest/tuning.html#level-of-parallelism

https://blog.csdn.net/u011564172/article/details/53611109

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章