Spark核心编程(Spark Core)
文章目录
1. 了解RDD
1.1 RDD概念
背景
首先分布式计算
- 分区控制
- Shuffle控制
- 数据存储\序列化\发送
- 数据计算API
- 等一系列功能
这些功能, 不能简单的通过Python内置的本地集合对象(如 List\ 字典等)去完成. 我们在分布式框架中, 需要有一个统一的数据抽象对象, 来实现上述分布式计算所需功能. 这个抽象对象, 就是RDD(Resilient Distributed Databases)
RDD定义
RDD定义 RDD(Resilient Distributed Dataset)叫做弹性分布式数据集。
是Spark中最基本的数据抽象,代表一个不可变、可 分区、里面的元素可并行计算的集合。
- Dataset:一个数据集合,用于存放数据的。 (这个概念 就是 类似于 List Array 之类的)
- Distributed:RDD中的数据是分布式存储的,可用于分布式计算。 (RDD的数据跨机器存储(跨进程))
- Resilient:RDD中的数据可以存储在内存中或者磁盘中
1.2 RDD五大特性
-
RDD有分区
-
计算方法作用到每一个分区
-
RDD之间相互依赖
-
KV型RDD可以有分区器(可选)
-
RDD分区数据的读取会尽量靠近数据所在地(可选)
-
RDD是有分区的
RDD的分区是RDD数据存储的最小单位(一份RDD数据本质上是分隔成多个分区)
-
RDD的方法会作用在其所有分区上
-
RDD之间是有依赖关系的
-
Key-Value 型的RDD可以有分区
KV型RDD数据:RDD内存储的数据是:二元元组
-
RDD的分区规划 会尽量靠近数据所在的服务器
1.3 WordCount案例分析
2 RDD编程入门
Spark RDD 编程的程序入口对象是SparkContext对象(不论何种编程语言)
只有构建出SparkContext, 基于它才能执行后续的API调用和计算
本质上, SparkContext对编程来说, 主要功能就是创建第一个RDD出来
2.1 RDD的创建
两种方式:
- 并行化集合方式创建(本地化对象 转 分布式RDD)
- 读取外部数据源(读取文件)
并行化集合方式创建
# 0. 创建Spark执行环境
from pyspark import SparkConf,SparkContext
#配置对象
conf = SparkConf().setAppName("test").setMaster("local[*]")
#入口对象
sc = SparkContext(conf=conf)
# master种类
# local:loacal[N] N核CPU运行 *所有CPU核心
# standalone
# yarn
#sc对象的parallelize 方法:将本地集合转换成RDD返回
data = [1,2,3,4,5,6,7,8,9]
rdd = sc.parallelize(data,numSlices=3)# 设置分区
print("默认分区数:",rdd.getNumPartitions())
# collect : 将RDD(分布式对象)中每个分区的数据都发送到Driver 中 形成一个 Python List
# collect: 分布式 -> 本地集合
print(rdd.collect())
读取外部数据源
- textFile() 既可以读取本地文件也可HDFS文件
在这里插入图片描述
#coding:utf-8
from pyspark import SparkConf,SparkContext
from pathlib import Path
FILE = Path(__file__).resolve()# /tmp/pycharm_project_362/00_example/HelloWorld.py
ROOT = FILE.parents[1]# /tmp/pycharm_project_362
if __name__ == '__main__':
conf = SparkConf().setAppName("test").setMaster("local[*]")
sc = SparkContext(conf=conf)
## 读取文本文件
filerdd1 = sc.textFile(f"file:///{
ROOT}/data/input/words.txt")
print("默认分区:",filerdd1.getNumPartitions())
print("file_rdd1:",filerdd1.collect())
filerdd2 = sc.textFile(f"file:///{
ROOT}/data/input/words.txt",minPartitions=3)
# 指定最小分区只是参考值 Spark 有自己的判断
filerdd3 = sc.textFile(f"file:///{
ROOT}/data/input/words.txt", minPartitions=100)
print("最小分区:", filerdd2.getNumPartitions())
print("filerdd3分区:", filerdd3.getNumPartitions())
print("file_rdd2:", filerdd2.collect())
##读取HDFS
hdfs_rdd = sc.textFile('hdfs://hadoop102:8020/wcinput/word.txt')
print(hdfs_rdd.collect())
- wholeTextFile()
import os
from pyspark import SparkConf,SparkContext
from pathlib import Path
FILE = Path(__file__).resolve()# /tmp/pycharm_project_362/00_example/HelloWorld.py
ROOT = FILE.parents[1]# /tmp/pycharm_project_362
if __name__ == '__main__':
conf = SparkConf().setAppName("test").setMaster("local[*]")
sc = SparkContext(conf=conf)
# 这样也可成功 但都需要绝对路径
# rdd = sc.wholeTextFiles("file:///"+os.path.abspath("../data/input/tiny_files"))
rdd = sc.wholeTextFiles(f"file:///{
ROOT}/data/input/tiny_files")
print(rdd.collect(