spark (五) RDD的创建 & 分区

1. RDD的创建方式

1.1 从内存创建RDD#

主要依赖如下两个方法

  • parallelize
  • makeRDD
    • 底层调用的还是parallelize
Copy
def main(args: Array[String]): Unit = { val sparkConfig: SparkConf = new SparkConf() .setMaster("local[*]") .setAppName("WordCount") val sparkContext: SparkContext = new SparkContext(sparkConfig) val rdd1: RDD[Int] = sparkContext.parallelize( List(1, 2, 3, 4) ) // makeRDD 底层调用的还是parallelize val rdd2: RDD[Int] = sparkContext.makeRDD( List(1, 2, 3, 4) ) }

1.2 从外部存储(文件)创建RDD#

由外部存储系统的数据集创建RDD包括

  • 本地文件系统
  • 所有Hadoop支持的数据集,比如HDFS、HBase等
Copy
def main(args: Array[String]): Unit = { val sparkConfig: SparkConf = new SparkConf() .setMaster("local[*]") .setAppName("WordCount") val sparkContext: SparkContext = new SparkContext(sparkConfig) val rdd1: RDD[String] = sparkContext.textFile("data") // 或者 hdfs://master:7077/input rdd1.collect().foreach(println) sparkContext.stop() }

1.3 从其他的RDD创建#

下述的flatMap map reduceByKey 每个操作都是以上一个RDD为基础创建另一个RDD

Copy
def main(args: Array[String]): Unit = { val sparkConfig: SparkConf = new SparkConf() .setMaster("local[*]") .setAppName("WordCount") val sparkContext: SparkContext = new SparkContext(sparkConfig) val rdd1: RDD[String] = sparkContext.textFile("data") // 或者 hdfs://master:7077/input rdd1 .flatMap(word => word.split(" ")) .map(word => (word, 1)) .reduceByKey(_ + _) .collect() .foreach(println) sparkContext.stop() }

1.4 直接 new RDD#

spark框架中会这么操作

2. 分区(partition)

2.1 makeRDD的分区#

可以通过以下优先级方式指定分区

  • 优先使用makeRDD的第二个参数指定的分区数量
  • 使用默认的配置的分区数量
    • SparkConf 若指定了 spark.default.parallelism, 则用这个
    • 否则使用CPU的核数(这里的CPU的核数在本地模式下,如local[3]则为3,local[*]等于物理机真实的CPU核数)
Copy
// 第二个参数指定numSlices, 即分区的数量 val rdd: RDD[Int] = sparkContext.makeRDD(List(1, 2, 3, 4), 2)

完整的表现分区的例子

Copy
package com.lzw.bigdata.spark.core.rdd_basic_usage_1 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} object Rdd_4_Partition_From_Mem { def main(args: Array[String]): Unit = { val sparkConfig: SparkConf = new SparkConf() .setMaster("local[*]") .setAppName("WordCount") // .set("spark.default.parallelism", "5") val sparkContext: SparkContext = new SparkContext(sparkConfig) val rdd: RDD[Int] = sparkContext.makeRDD(List(1, 2, 3, 4), 2) // 保存成分区文件,每个分区会生成一个文件,可以借此查看真实生成了几个分区 rdd.saveAsTextFile("output") sparkContext.stop() } }

2.2 读取文件的分区例子#

spark读取文件借助的是hadoop的方法, 所以以下的读取规则是hadoop的规则

Copy
// 可以指定 minPartitions, 不指定默认是 math.min(defaultParallelism, 2) sparkContext.textFile("data/word.txt", 2)

以以下一个文件word.txt为例, 该文件算上换行符\n一共13个字节

Copy
1234 567 8900

2.2.1 读取文件分区规则#

所以分区数计算方式为

Copy
分区数: 13 bytes / 2(这里2是minPartitions) = 6 13 bytes / 6 bytes = 2分区 + 剩余的1byte => 1/6 > 0.1 => 3分区

2.2.2 每个分区的数据#

Copy
每个分区里面的数据, (hadoop按偏移量之后按行读取): 分区1预期 [0, 6] => 1234\n 567\n 分区2预期[6, 12] => 但是上一个分区因为是偏移量到了某一行,某行就都被读走了,所以真实的 => 8900 分区3预计[12, 13] => 已无数据可读

2.2.3 完整示例#

Copy
package com.lzw.bigdata.spark.core.rdd_basic_usage_1 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} object Rdd_5_Partition_From_File { def main(args: Array[String]): Unit = { val sparkConfig: SparkConf = new SparkConf() .setMaster("local[*]") .setAppName("WordCount") // .set("spark.default.parallelism", "5") val sparkContext: SparkContext = new SparkContext(sparkConfig) /* 1234\n 567\n 8900 分区数: 13 bytes / 2(这里2是minPartitions) = 6 13 bytes / 6 bytes = 2分区 + 剩余的1byte => 1/6 > 0.1 => 3分区 每个分区里面的数据, (hadoop按偏移量之后按行读取): 分区1预期 [0, 6] => 1234\n 567\n 分区2预期[6, 12] => 但是上一个分区因为是偏移量到了某一行,某行就都被读走了,所以真实的 => 8900 分区3预计[12, 13] => 已无数据可读 */ val rdd: RDD[String] = sparkContext.textFile("data/word.txt", 2) rdd.saveAsTextFile("output") sparkContext.stop() } }



posted @   宝树呐  阅读(303)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示
CONTENTS