一)什么是分区
【复习提问:RDD的定义是什么?】
在 Spark 里,弹性分布式数据集(RDD)是核心的数据抽象,它是不可变的、可分区的、里面的元素并行计算的集合。
在 Spark 中,分区是指将数据集按照一定的规则划分成多个较小的子集,每个子集可以独立地在不同的计算节点上进行处理,这样可以实现数据的并行处理,提高计算效率。
可以将 Spark 中的分区类比为快递公司处理包裹的过程。假设你有一批包裹要从一个城市发送到另一个城市,快递公司会将这些包裹按照一定的规则进行分区,比如按照收件地址的区域划分。每个分区的包裹会被分配到不同的快递员或运输车辆上进行运输,这些快递员或车辆可以同时出发,并行地将包裹送到不同的区域。这就类似于 Spark 中的分区,每个分区的数据可以在不同的计算节点上同时进行处理,从而加快整个数据处理的速度。
(二)默认分区的情况
【老师编写代码,复习创建RDD的两个方法】
从集合创建 RDD(使用 parallelize 方法)
当使用 parallelize 方法从一个集合创建 RDD 时,默认分区数通常取决于集群的配置。
在本地模式下,默认分区数等于本地机器的 CPU 核心数;在集群模式下,默认分区数由 spark.default.parallelism 配置项决定。
import org.apache.spark.SparkContext
import org.apache.spark.SparkConf
val conf = new SparkConf().setAppName("DefaultPartitionExample").setMaster("local")
val sc = new SparkContext(conf)
val data = Seq(1, 2, 3, 4, 5)
val rdd = sc.parallelize(data)
println(s"默认分区数: ${rdd.partitions.length}")
sc.stop()
2.从外部存储(如文件)创建 RDD(使用 textFile 方法)
当使用 textFile 方法从外部存储(如 HDFS、本地文件系统等)读取文件创建 RDD 时,默认分区数通常由文件的块大小决定。对于 HDFS 文件,默认分区数等于文件的块数。例如,一个 128MB 的文件在 HDFS 上被分成 2 个 64MB 的块,那么创建的 RDD 默认分区数就是 2。
import org.apache.spark.SparkContext
import org.apache.spark.SparkConf
val conf = new SparkConf().setAppName("DefaultPartitionFileExample").setMaster("local")
val sc = new SparkContext(conf)
// 假设文件存在于本地
val rdd = sc.textFile("path/to/your/file.txt")
println(s"默认分区数: ${rdd.partitions.length}")
sc.stop()
(三)分区的作用
并行计算:Spark 能够同时对多个分区的数据进行处理,充分利用集群的计算资源,进而加快作业的执行速度。例如,若一个 RDD 有 10 个分区,且集群有足够的计算资源,Spark 就可以同时处理这 10 个分区的数据。
数据局部性:分区有助于实现数据局部性,也就是让计算尽量在数据所在的节点上进行,减少数据在网络间的传输,从而降低网络开销。
容错性:当某个分区的数据处理失败时,Spark 能够重新计算该分区,而不需要重新计算整个 RDD。
object PartitionExample {
def main(args: Array[String]): Unit = {
// 创建 SparkConf 对象,设置应用程序名称和运行模式
val conf = new SparkConf().setAppName("PartitionExample").setMaster("local")
// 使用 SparkConf 创建 SparkContext 对象
val sc = new SparkContext(conf)
// 创建一个包含 10 个元素的 Seq
val data = Seq(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
// 使用 parallelize 方法创建 RDD,并设置分区数为 3
val rdd = sc.parallelize(data, 3)
// 将 RDD 保存为文本文件,保存路径为 "output"
rdd.saveAsTextFile("output")
// 停止 SparkContext,释放资源
sc.stop()
}
}