文章目录
- RDD详解
-
- 为什么需要RDD
- 什么是RDD
- [RDD 5大特性](#RDD 5大特性)
- wordCount中RDD
- 总结
-
- 如何正确理解RDD
- [RDD 5大特性](#RDD 5大特性)
- RDD编程入门
RDD详解
为什么需要RDD
分布式计算需要:
- 分区控制
- shuffle控制(不同分区进行数据传输)
- 数据存储、序列化、发送
- 数据计算API
- 其他一系列功能
这些功能不能简单地通过python内置的本地集合对象(list、dict等)来实现,在分布式框架中,需要有一个统一的数据抽象对象,来实现上述分布式计算所需功能。
上述抽象对象:RDD
什么是RDD
Resilient Distributed Dataset,弹性分布式数据集,spark中最基本的数据抽象,代表一个不可变、可分区、里面元素可并行计算的集合
Resilient:数据可存放在内存或磁盘中
Distributed:数据是分布式存储的,可用于分布式计算(数据跨机器存储、跨进程存储;本地集合:数据全部在一个进程内部)
Dataset:数据集合,用来存放数据
RDD 5大特性
RDD数据结构内部有5大特性,前3个特性每个RDD都具备,后2个特性可选
- RDD有分区
- 计算方法作用到每一个分区(分片)之上
- RDD之间相互依赖
- KV型RDD可以有分区器
- RDD分区数据的读取尽量靠近数据所在地(数据不动,数据在哪,就在哪个机器上计算)
RDD有分区
分区是RDD数据存储的最小单位
一份RDD数据,本质上是分隔成了多个分区
RDD方法会作用在所有分区上
map方法体现在了每一个分区上
glom方法,将一个分区的数据转换为相同类别的内存数组进行处理,分区不变
RDD之间有依赖关系
KV型RDD可以有分区器
KV型RDD:RDD内存储的数据是二元元组,如("hadoop",3)
默认分区器:Hash分区规则,可以通过rdd.partitionBy方法手动设置一个分区器
这个特性只是可能的,因为并不是所有RDD都是KV型
RDD分区尽量靠近数据所在服务器
初始RDD(读取数据的时候)规划的时候,分区尽量规划到存储数据所在的服务器上
因此,尽量走本地读取,避免网络读取
本地读取:Executor所在服务器,也是一个DataNode,同时这个DataNode上有它要读的数据,因此可以直接读取硬盘,而不需要走网络
网络读取:读取数据时,需要经历网络传输才能读取到
因此,spark会在确保并行计算能力的前提下,尽量本地读取(非100%)
wordCount中RDD
总结
如何正确理解RDD
弹性分布式数据集,分布式计算的实现载体(数据抽象)
RDD 5大特性
- 可分区
- 方法应用到每一个分区
- RDD相互依赖
- KV型RDD可以有分区器
- RDD构建尽量靠近数据
RDD编程入门
程序执行入口--SparkContext对象
Spark RDD编程的程序入口对象是SparkContext对象(不论何种语言)
只有构建出SparkContext,基于sc才能执行后续的API调用和计算
本质上sc对编程来说,主要功能就是创建出第一个RDD出来
RDD创建
RDD创建的两种方式:
- 通过并行化集合创建(本地对象 转 分布式RDD)
- 读取外部数据源(读取文件)
并行化创建
读取文件创建
通过textFile API 读取本地数据或hdfs数据
sc.textFile(para1, para2)
para1必填,文件路径
para2可选,最小分区数(spark有自己的判断,允许范围内,para2有效,允许范围外,para2无效)
wholeTextFile
读取文件的API,适用于读取一堆小文件
RDD算子
算子
分布式集合对象上的API,称为算子
本地对象的API叫方法、函数
算子分类
- Transformation:转换算子
- Action:动作(行动)算子
transformation转换算子
定义:返回值仍然是一个RDD,称为转换算子
特性:lazy懒加载,如果没有action算子,则transformation算子不工作
action动作算子
定义:返回值不是RDD的就是action算子
区分
transformation转换算子相当于构建执行计划,action动作算子相当于执行计划
常用transformation转换算子
map算子
将RDD的数据一条一条处理(处理逻辑:基于map算子中接受的处理函数),返回新的RDD
python
rdd.map((func)
# func: f(T)->U
flatMap算子
对RDD执行map操作,然后进行解除嵌套操作
python
# 嵌套list
lst = [[1,2,3],[4,5,6],[7,8,9]]
# 解除嵌套
lst = [1,2,3,4,5,6,7,8,9]
flatMap传入参数和map一致,就是给map逻辑用的,在map逻辑上解除嵌套
reduceByKey算子
针对KV型RDD,自动按照key分组,根据提供的聚合逻辑,完成组内数据(value)的聚合操作
python
rdd.reducebyKey(func)
# func: (V,V)->V
# 接受两个类型一致的传入参数,返回值类型也和传入一致
key相同的分为一组,再根据value聚合
mapValues算子
针对二元元组RDD,对其元组内部的value执行map操作
python
rdd.mapValues(func)
# func: (V)->V
# 只针对value进行处理
groupBy算子
对RDD数据进行分组
python
rdd.groupBy(func)
# func: (T)->K
# 拿到返回值后,将相同返回值放入一个组中
# 分组完成后,每个组是一个二元元组,key是返回值,同组的数据放入迭代器中作为value
[('b',[('b',1), ('b', 1), ('b',1)])('a',[('a',1),('a',1)])]
key是返回值,value是同组的数据
filter算子
过滤想要的数据,进行保留
python
rdd.filter(func)
# func: (T)->bool
# 传入的参数任意类型,返回值必须是布尔型(真True、假False)
distinct算子
对RDD进行去重,返回新RDD
rdd.distinct(参数) # 参数为去重分区数量,按几个分区进行去重,一般不传
union算子
将2个RDD合并为1个RDD并返回
rdd.union(other_rdd)
只合并(不同类型的RDD也可以合并),不去重
join算子
对2个RDD进行join(可实现SQL的内、外连接)
join算子只能用于二元元组
python
rdd.join(other_rdd) # 内连接
rdd.leftOuterJoin(other_rdd) # 左外连接
rdd.rightOuterJoin(other_rdd) # 右外连接