大数据笔记(二十九)——RDD简介、特性及常用算子
1、什么是RDD? 最核心
(*)弹性分布式数据集,Resilent distributed DataSet
(*)Spark中数据的基本抽象
(*)结合源码,查看RDD的概念
RDD属性
* Internally, each RDD is characterized by five main properties:
*
* - A list of partitions
一组分区,把数据分成了的不同的分区,每个分区可能运行在不同的worker
* - A function for computing each split
一个函数,用于计算每个分区中的数据
RDD的函数(算子)
(1)Transformation
(2)Action
* - A list of dependencies on other RDDs
RDD之间依赖关系:(1)窄依赖 (2)宽依赖
根据依赖的关系,来划分任务的Stage(阶段)
* - Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned)
* - Optionally, a list of preferred locations to compute each split on (e.g. block locations for an HDFS file)
如何创建一个RDD?有两种方式
(1)使用sc.parallelize方法
val rdd1 = sc.parallelize(Array(1,2,3,4,5,6,7,8),3)
(2)通过使用外部的数据源创建RDD:比如:HDFS
val rdd2 = sc.textFile("hdfs://bigdata11:9000/input/data.txt")
val rdd2 = sc.textFile("/root/temp/input/data.txt")
2、Transformation算子:不会触发计算、延时加载(lazy值)
RDD API网址:http://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.rdd.RDD
常见的RDD算子:
map(func):该操作是对原来的RDD进行操作后,返回一个新的RDD
filter: 过滤操作、返回一个新的RDD
flatMap:类似map
mapPartitions:对每个分区进行操作
mapPartitionsWithIndex: 对每个分区进行操作,带分区的下标
union 并集
intersection 交集
distinct 去重
groupByKey: 都是按照Key进行分组
reduceByKey: 都是按照Key进行分组、会有一个本地操作(相当于:Combiner操作)
3、Action算子:会触发计算
collect: 触发计算、打印屏幕上。以数组形式返回
count: 求个数
first: 第一个元素(take(1))
take(n)
saveAsTextFile: 会转成String的形式,会调用toString()方法
foreach: 在RDD的每个元素上进行某个操作
4、RDD的缓存机制:默认在内存中
(*)提高效率
(*)默认:缓存在Memory中
(*)调用:方法:persist或者cache
def persist(): this.type = persist(StorageLevel.MEMORY_ONLY)
def cache(): this.type = persist()
(*)缓存的位置:StorageLevel定义的
val NONE = new StorageLevel(false, false, false, false)
val DISK_ONLY = new StorageLevel(true, false, false, false)
val DISK_ONLY_2 = new StorageLevel(true, false, false, false, 2)
val MEMORY_ONLY = new StorageLevel(false, true, false, true)
val MEMORY_ONLY_2 = new StorageLevel(false, true, false, true, 2)
val MEMORY_ONLY_SER = new StorageLevel(false, true, false, false)
val MEMORY_ONLY_SER_2 = new StorageLevel(false, true, false, false, 2)
val MEMORY_AND_DISK = new StorageLevel(true, true, false, true)
val MEMORY_AND_DISK_2 = new StorageLevel(true, true, false, true, 2)
val MEMORY_AND_DISK_SER = new StorageLevel(true, true, false, false)
val MEMORY_AND_DISK_SER_2 = new StorageLevel(true, true, false, false, 2)
val OFF_HEAP = new StorageLevel(true, true, true, false, 1)
(*)示例:
测试数据:Oracle数据库的订单变 sales表(大概92万)
步骤
(1)从HDFS读入数据
val rdd1 = sc.textFile("hdfs://bigdata11:9000/input/sales")
(2)计算
rdd1.count ---> Action,这一次没有缓存
rdd1.cache ---> 缓存数据,但是不会触发计算,cache是一个Transformation
rdd1.count ----> 触发计算,将结果缓存
rdd1.count ----> ???会从哪里得到数据
通过UI进行监控:
IDEA功能键:ctrl + n 查找类
ctl+alt+shit+N 在类中找方法
5、RDD的容错机制:checkpoint检查点
(1)复习检查点:HDFS中,合并元信息
Oracle中,会以最高优先级唤醒数据库写进程(DBWn),来内存中的脏数据---> 数据文件
(2)RDD的检查点:容错机制,辅助Lineage(血统)---> 整个计算的过程
如果lineage越长,出错的概率就越大。出错之后,从最近一次的检查点开始运行。
两种类型
(1)本地目录 : 需要将spark-shell运行在本地模式上
(2)HDFS目录: 需要将spark-shell运行在集群模式上
scala> sc.setCheckpointDir("hdfs://bigdata11:9000/spark/checkpoint") scala> val rdd1 = sc.textFile("hdfs://bigdata11:9000/input/sales")
rdd1: org.apache.spark.rdd.RDD[String] = hdfs://bigdata11:9000/input/sales MapPartitionsRDD[41] at textFile at <console>:24 scala> rdd1.checkpoint scala> rdd1.count
源码中对于检查点的说明:
/**
* Mark this RDD for checkpointing. It will be saved to a file inside the checkpoint
* directory set with `SparkContext#setCheckpointDir` and all references to its parent
* RDDs will be removed. This function must be called before any job has been
* executed on this RDD. It is strongly recommended that this RDD is persisted in
* memory, otherwise saving it on a file will require recomputation.
*/
RDD的检查点多久发出一次,是手动发出的吗?
1、不是手动
2、每个RDD计算完成后
查看源码
/**
* Performs the checkpointing of this RDD by saving this. It is called after a job using this RDD
* has completed (therefore the RDD has been materialized and potentially stored in memory).
* doCheckpoint() is called recursively on the parent RDDs.
*/
private[spark] def doCheckpoint(): Unit = {
6、RDD的依赖关系、划分Spark任务的Stage(阶段)
(*)窄依赖(Narrow Dependencies):每一个父RDD的分区最多被子RDD的一个分区使用
比方:独生子女
举例:map,filter,union
(*)宽依赖(Wide Dependencies):多个子RDD的分区会依赖同一个父RDD的分区
比方:超生
举例:groupByKey
比如分区1和分区2都有10号部门的员工,那么在统计10号部门(key)的员工时需要依赖分区1和分区2,它们属于不同的父RDD的分区。
根据宽依赖和窄依赖的标准,我们可以划分任务的Stage(阶段)
7、RDD算子的基础例子
1、创建一个RDD(数字)
val rdd1 = sc.parallelize(List(5,6,1,2,10,4,12,20,100,30)) 每个元素*2,然后排序
val rdd2 = rdd1.map(_*2).sortBy(x=>x,true) 完整
val rdd2 = rdd1.map((x:Int)=>x*2) 过滤出大于10的元素
val rdd3 = rdd2.filter(_>10)
rdd3.collect 2、创建一个RDD(字符)
val rdd1 = sc.parallelize(Array("a b c","d e f","h i j"))
val rdd2 = rdd1.flatMap(_.split(' '))
rdd2.collect 3、集合运算、去重
val rdd1 = sc.parallelize(List(5,6,7,8,1,2))
val rdd2 = sc.parallelize(List(1,2,3,4)) val rdd3 = rdd1.union(rdd2)
rdd3.distinct.collect
val rdd4 = rdd1.intersection(rdd2)
4、分组
val rdd1 = sc.parallelize(List(("Tom",1000),("Jerry",3000),("Mary",2000)))
val rdd2 = sc.parallelize(List(("Jerry",500),("Tom",3000),("Mike",2000))) 并集
val rdd3 = rdd1 union rdd2
scala> val rdd4 = rdd3.groupByKey
rdd4: org.apache.spark.rdd.RDD[(String, Iterable[Int])] = ShuffledRDD[27] at groupByKey at <console>:30 scala> rdd4.collect
res8: Array[(String, Iterable[Int])] = Array((Tom,CompactBuffer(1000, 3000)),
(Jerry,CompactBuffer(3000, 500)),
(Mike,CompactBuffer(2000)),
(Mary,CompactBuffer(2000)))
六、Spark RDD的高级算子
1、mapPartitionsWithIndex: 对RDD中的每个分区进行操作,带有分区号
定义:def mapPartitionsWithIndex[U](f: (Int, Iterator[T])=>Iterator[U], preservesPartitioning: Boolean = false)
(implicit arg0: ClassTag[U]): RDD[U]
参数说明:
f: (Int, Iterator[T])=>Iterator[U]
(*)Int: 分区号
(*)Iterator[T]: 该分区中的每个元素
(*)返回值:Iterator[U]
Demo:
(1)创建一个RDD:
val rdd1 = sc.parallelize(List(1,2,3,4,5,6,7,8,9),2)
(2)创建一个函数,作为f的值
def func1(index:Int,iter:Iterator[Int]):Iterator[String] ={
iter.toList.map(x=>"[PartID:" + index +",value="+x+"]").iterator
}
(3)调用
rdd1.mapPartitionsWithIndex(func1).collect
(4)结果:
Array([PartID:0,value=1], [PartID:0,value=2], [PartID:0,value=3], [PartID:0,value=4],
[PartID:1,value=5], [PartID:1,value=6], [PartID:1,value=7], [PartID:1,value=8], [PartID:1,value=9])
2、aggregate:聚合操作
定义:def aggregate[U: ClassTag](zeroValue: U)(seqOp: (U, T) => U, combOp: (U, U) => U): U
作用:先对局部进行操作,再对全局进行操作
举例:
val rdd1 = sc.parallelize(List(1,2,3,4,5),2)
(1)求每个分区最大值的和
先查看每个分区中的元素:
rdd1.mapPartitionsWithIndex(func1).collect rdd1.aggregate(0)(math.max(_,_),_+_)
(2)改一下:
rdd1.aggregate(0)(_+_,_+_) ====> 15 两个分区求和并相加
rdd1.aggregate(10)(math.max(_,_),_+_) ===> 30 初始值是10,每个分区里有10,初始值10+分区一10+分区二10 = 30
(3)一个字符串的例子
3、aggregateByKey
(1)类似aggregate,也是先对局部,再对全局
(2)区别:aggregateByKey操作<key,value>
(3)测试数据:
val pairRDD = sc.parallelize(List( ("cat",2), ("cat", 5), ("mouse", 4),("cat", 12), ("dog", 12), ("mouse", 2)), 2)
每个分区中的元素(key,value)
def func3(index: Int, iter: Iterator[(String, Int)]) : Iterator[String] = {
iter.toList.map(x => "[partID:" + index + ", val: " + x + "]").iterator
} [partID:0, val: (cat,2)], [partID:0, val: (cat,5)], [partID:0, val: (mouse,4)],
[partID:1, val: (cat,12)], [partID:1, val: (dog,12)], [partID:1, val: (mouse,2)]
(4)把每个笼子中,每种动物最多的个数进行求和
pairRDD.aggregateByKey(0)(math.max(_,_),_+_).collect
4、coalesce和repartition
(*)都是将RDD中的分区进行重分区
(*)区别:coalesce 默认:不会进行shuffle(false)
repartition 会进行shuffle (*)举例:
创建一个RDD
val rdd4 = sc.parallelize(List(1,2,3,4,5,6,7,8,9),2) 进行重分区
val rdd5 = rdd4.repartition(3)
val rdd6 = rdd4.coalesce(3,false) ---> 分区的长度: 2
val rdd6 = rdd4.coalesce(3,true) ---> 分区的长度: 2
5、其他高级算子:参考文档
http://homepage.cs.latrobe.edu.au/zhe/ZhenHeSparkRDDAPIExamples.html
大数据笔记(二十九)——RDD简介、特性及常用算子的更多相关文章
- 大数据笔记(十九)——数据采集引擎Sqoop和Flume安装测试详解
一.Sqoop数据采集引擎 采集关系型数据库中的数据 用在离线计算的应用中 强调:批量 (1)数据交换引擎: RDBMS <---> Sqoop <---> HDFS.HBas ...
- Java笔记(二十九)……网络编程
概述 网络模型 网络通讯的要素 ip地址:网络中设备的标识符 端口:用于标识同一台设备上不同的进程,有效端口:0~65535,其中0~1024是系统使用端口或者保留端口 TCP与UDP UDP特点: ...
- 大数据笔记(十二)——使用MRUnit进行单元测试
package demo.wc; import java.util.ArrayList; import java.util.List; import org.apache.hadoop.io.IntW ...
- 大数据笔记(十)——Shuffle与MapReduce编程案例(A)
一.什么是Shuffle yarn-site.xml文件配置的时候有这个参数:yarn.nodemanage.aux-services:mapreduce_shuffle 因为mapreduce程序运 ...
- angular学习笔记(二十九)-$q服务
angular中的$q是用来处理异步的(主要当然是http交互啦~). $q采用的是promise式的异步编程.什么是promise异步编程呢? 异步编程最重要的核心就是回调,因为有回调函数,所以才构 ...
- 论文阅读笔记二十九:SSD: Single Shot MultiBox Detector(ECCV2016)
论文源址:https://arxiv.org/abs/1512.02325 tensorflow代码:https://github.com/balancap/SSD-Tensorflow 摘要 SSD ...
- 大数据笔记(十八)——Pig的自定义函数
Pig的自定义函数有三种: 1.自定义过滤函数:相当于where条件 2.自定义运算函数: 3.自定义加载函数:使用load语句加载数据,生成一个bag 默认:一行解析成一个Tuple 需要MR的ja ...
- 大数据笔记(十五)——Hive的体系结构与安装配置、数据模型
一.常见的数据分析引擎 Hive:Hive是一个翻译器,一个基于Hadoop之上的数据仓库,把SQL语句翻译成一个 MapReduce程序.可以看成是Hive到MapReduce的映射器. Hive ...
- 大数据笔记(十四)——HBase的过滤器与Mapreduce
一. HBase过滤器 1.列值过滤器 2.列名前缀过滤器 3.多个列名前缀过滤器 4.行键过滤器5.组合过滤器 package demo; import javax.swing.RowFilter; ...
- Java学习笔记二十九:一个Java面向对象的小练习
一个Java面向对象的小练习 一:项目需求与解决思路: 学习了这么长时间的面向对象,我们只是对面向对象有了一个简单的认识,我们现在来做一个小练习,这个例子可以使大家更好的掌握面向对象的特性: 1.人类 ...
随机推荐
- C++中的类型识别
1,为什么会提出类型识别概念呢? 1,为什么在 C 语言中没有提出这个概念呢,就是因为在 C++ 中引入了面向对象的特性,面向对象里面有一个非常重要的原则就是赋值兼容性原则: 2,在面向对象中可能出现 ...
- PythonDay09
第九章函数 今日内容 函数定义 函数调用 函数返回值 函数的参数 函数定义 # 通过定义一个计算数据长度的函数,def为关键字,count_len是函数名def count_len(): lst = ...
- JAVA并发编程实战笔记 第二章
2.1 线程安全性 当多个线程访问某个类时,不论这些线程如何交替执行,这个类始终都能表现出正确的行为,且主调代码中不需要任何额外的同步或协同,则称这个类是线程安全的. 类不变性条件(Invariant ...
- 14.AutoMapper 之依赖注入(Dependency Injection)
https://www.jianshu.com/p/f66447282780 依赖注入(Dependency Injection) AutoMapper支持使用静态服务定位构建自定义值解析器和自定 ...
- springmvc中的数据传递
import javax.servlet.http.HttpServletRequest; import org.springframework.stereotype.Controller; impo ...
- 手把手教你如何安装使用webpack vue cli
1.安装node.js:https://nodejs.org/en/download/(看电脑的系统是多少位下载相应版本) 我下载的是Windows Installer(.msi) x64 2.打开c ...
- git常用命令之log
查看提交日志记录 基础命令: git log commit ca82a6dff817ec66f44342007202690a93763949 Author: Scott Chacon < ...
- 隐藏ie input的X和眼睛图标
IE10+ /** 文本输入框的 X **/input::-ms-clear{display: none;}/** 密码输入框的 X **/input::-ms-reveal{display: non ...
- webpack3 打包
1. 基于 webpack 3.0 2.步骤.说明 2.1 webpack 本地初始化.安装基本包 npm init > package.json npm i webpack ...
- 基于SOA的图书商城系统分析
1.1什么是SOA架构? SOA( Service Oriented Architecture)是一种面向服务的分布式架构,将每个实现特定功能的工程拆分为服务层和表现层.服务层负责处理业务逻辑,对外提 ...