Spark RDD

概念

RDD是一种抽象,是Spark对于分布式数据集的抽象,它用于囊括所有内存中和磁盘中的分布式数据实体

RDD 与 数组对比

对比项 数组 RDD
概念类型 数据结构实体 数据模型抽象
数据跨度 单机进程内 跨进程、跨计算节点
数据构成 数组元素 数据分片(Partitions)
数据定位 数组下标、索引 数据分片索引

RDD 4大属性

partitions 数据分片: 数据属性

partitioner 分片切割规则: 定义了把原始数据集切割成数据分片的切割规则

dependencies RDD依赖: 每个RDD都会通过dependencies属性来记录它所依赖的前一个、或是多个RDD,简称"父RDD"

compute 转换函数: 与此同时,RDD使用compute属性,来记录从父RDD到当前RDD的转换操作

例子

不同的食材形态,如带泥土豆、土豆片、即食薯片等等,对应的就是RDD概念

同一种食材形态在不同流水线上的具体实物,就是 RDD 的 partitions 属性

食材按照什么规则被分配到哪条流水线,对应的就是 RDD 的 partitioner 属性

每一种食材形态都会依赖上一种形态,这种依赖关系对应的是 RDD 中的 dependencies 属性

不同环节的加工方法对应 RDD的 compute 属性

RDD 编程模型

在RDD的编程模型中,一共有两种算子,Transformations 类算子和Actions类算子

开发者需要使用Transformations 类算子,定义并描述数据形态的转换过程,然后调用Actions类算子,将计算结果收集起来、或是物化到磁盘

延迟计算

RDD编程模型下,Spark在运行时的计算被划分为两个环节

  • 基于不同数据形态之间的转换,构建计算流图(DAG,Directed Acyclic Graph)
  • 通过Actions类算子,以回溯的方式去触发执行这个计算流图

换句话说,开发者调用的各类Transformations算子,并不立即执行计算

当且仅当开发者调用Actions算子时,之前调用的转换算子才会付诸执行

常用算子

算子类型 适用范围 算子用途 算子集合
Transformations 任意RDD RDD内数据转换 map、mapPartitons、mapPartitonsWithIndex、flatMap、 filter
Paired RDD RDD内数据耦合 groupByKey、sortByKey、reduceByKey、aggregateByKey
任意RDD RDD间数据整合 union、intersection、join、cogroup、cartesian
任意RDD 数据整理 sample、distinct
Actions 任意RDD 数据收集 collect、first、take、takeSample、takeOrdered、count
任意RDD 数据持久化 saveAsTextFile、saveAsSequenceFile、saveAsObjectFile
任意RDD 数据遍历 foreach

map: 元素为粒度对RDD做数据转换

复制代码
val rdd: RDD[Int] = sc.parallelize(Seq(1, 2, 3, 4, 5))
val result: RDD[Int] = rdd.map(x => x + 1)
result.collect() // 返回 Array(2, 3, 4, 5, 6)

在这个例子中,我们使用 parallelize 方法创建一个包含整数的 RDD
接着,我们使用 map 算子将 RDD 中的每个整数都加上 1,生成一个新的 RDD
最后,我们使用 collect 方法将新的 RDD 中的元素取回到驱动程序中

mapPartitons: 以数据分区为粒度,使用映射函数f对RDD进行数据转换

复制代码
val rdd = sc.parallelize(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 3)
val result = rdd.mapPartitions(partition => {
  val sum = partition.sum
  Iterator(sum)
}).collect()

这个例子中,我们首先创建了一个包含10个元素的RDD,并将其分成3个分区
然后,我们使用mapPartitions算子,以数据分区为粒度进行转换
在这个例子中,我们使用partition.sum计算每个数据分区的和,并将其放入一个新的迭代器中
最后,我们使用collect算子将结果收集到本地
这个例子展示了如何使用mapPartitions算子以数据分区为单位进行操作,从而提高执行效率

flatMap:从元素到集合、再从集合到元素

复制代码
val sentences: RDD[String] = sc.parallelize(List("Hello world", "How are you", "I am fine"))
val words: RDD[String] = sentences.flatMap(sentence => sentence.split(" "))

在上面的代码中,我们首先创建了一个包含多个句子的 RDD,然后使用 flatMap 方法,对每个句子进行拆分操作
具体地,对于 RDD 中的每个元素(即句子),我们都将其分割成单词,然后使用 yield 关键字将每个单词作为一个新的元素返回
最终,我们得到了一个包含所有单词的 RDD

filter:过滤RDD

复制代码
val numbersRDD = sc.parallelize(Seq(-2, 0, 5, -10, 7, -3, 9))
val positiveNumbersRDD = numbersRDD.filter(x => x >= 0)
positiveNumbersRDD.foreach(println) // RDD[0, 5, 7, 9]

我们创建了一个包含数字的RDD,然后使用filter算子过滤掉其中的负数,最终返回一个新的RDD,只包含正数

mapPartitionsWithIndex: 每个元素映射为一个包含索引和单词的元组

复制代码
val data = List("apple", "banana", "orange", "grape", "pear")
val rdd = sc.parallelize(data, 2)

val result = rdd.mapPartitionsWithIndex { (index, partition) =>
  partition.map(word => (index, word))
}

result.foreach(println)

这段代码创建了一个包含 5 个元素的列表,并将其转换为一个包含 2 个分区的 RDD
接着,使用 mapPartitionsWithIndex 函数将每个元素映射为一个包含索引和单词的元组,最后打印出结果

在这个例子中,mapPartitionsWithIndex 函数的输入函数接受两个参数:分区索引和分区中的元素迭代器
元素迭代器包含了分区中的所有元素,因此我们可以在其中使用 map 函数对所有元素进行操作
最终的输出结果是一个包含索引和单词的元组的 RDD

groupByKey:分组收集

groupByKey的字面意思是"按照Key做分组",但实际上,groupByKey算子包含两步,即分组和收集

相关推荐
智慧医养结合软件开源19 分钟前
规范新增·精准赋能,凝聚志愿力量守护老人安康
大数据·安全·百度·微信·云计算
未来之窗软件服务1 小时前
数据库优化(九)随机抽选系统数据表 ——东方仙盟
大数据·数据库·数据库优化·仙盟创梦ide·东方仙盟
b***25111 小时前
动力电池自动生产线的工艺逻辑与运维要点
大数据·人工智能
一切皆是因缘际会1 小时前
本地大模型轻量化部署
大数据·人工智能·机器学习·架构
LONGZETECH1 小时前
汽车电气故障诊断仿真教学软件【迈腾380TSI】技术解析
大数据·人工智能·汽车·汽车仿真教学软件·汽车教学软件
无忧智库2 小时前
某集团企业智能体(Agent)操作系统(AOS)基础平台与企业级Agent治理体系详细设计方案(WORD)
大数据·人工智能
qq_452396232 小时前
第十三篇:《分布式压测:JMeter Master-Slave集群》
分布式·jmeter
KKKlucifer2 小时前
数字安全浪潮下国产数据安全企业发展图鉴
大数据·安全
数字化顾问3 小时前
(121页PPT)IT规划咨询项目规划报告(附下载方式)
大数据
ws2019073 小时前
从芯片到架构:AUTO TECH China 2026聚焦汽车计算新赛道
大数据·人工智能·科技·汽车