SparkCore
1-RDD基本概念
-
RDD弹性分布式数据集Resilient Distributed Dataset
- 1-弹性:既可以存储在磁盘也可以存储在内存
- 2-分布式:分布式的存储
- 3-数据集:集合
- 不可变、可分区、里面的元素可并行计算
-
为什么需要RDD呢?
- MR使用代码实现数据分析处理–缺点使用的大量的代码,复杂
- Hive使用Hql实现数据分析,摆脱了Mr的繁琐的代码
- Spark-Impala以内存为首的计算框架,将数据尽量放在内存中
- 传统的计算以MR为例的有大量的写磁盘,RDD是spark的基本数据抽象,解决大量写磁盘的问题,而计算和存储放在内存中实现
-
RDD有哪些特性?
-
http://spark.apache.org/docs/2.2.0/rdd-programming-guide.html
-
* Internally, each RDD is characterized by five main properties: * * - A list of partitions--一个分区----如果block块数据小于2,默认2各分区 * - A function for computing each split---每个分区的函数----map或flatmap * - A list of dependencies依赖 on other RDDs -----RDD的依赖----寻找部分节点丢失 * - Optionally, a Partitioner for key-value RDDs (e.g. to say that the RDD is hash-partitioned) ---key-value类型RDD--基于hash-partitioned分区---分区函数 * - Optionally, a list of preferred locations to compute each split on (e.g. block locations for 移动计算比移动数据便宜 * an HDFS file)
-
对于key-value类型的数据可以使用hashpartitoner和rangepartitioner结构
-
-
RDD的算子:
- RDD支持两种操作:转化操作和行动操作
- 转换操作:A的RDD转化为B的RDD-Transform算子
- 行动操作:如collect触达前面的各个步骤的计算–Action算子
- 惰性求值思路:Spark采用惰性计算模式,RDD只有第一次在一个行动操作中用到时,才会真正计算
-
RDD的WordCount的理解
- 记住五个属性:
- 1-一组分片split 0号–1号–2号
- 2-分区函数-flatMap-map-reduceBykey
- 3-RDD的dependencies依赖关系
- 4-Key-Value类类型的数据Hash分区和Range分区
- 5-位置有限性
- 记住五个属性:
2-RDD创建以及操作的方式
-
从外部数据读取
- sc.textFile()方式读取文件为RDD数据结构
-
从makeRDD和paralise创建并行化的RDD
- sc.makeRDD()
- sc.parallelize()
-
从其他RDD转换而来
-
//1-RDD的创建方式 //1-1parallelize val pRDD1: RDD[Int] = sc.parallelize(Array(1,2,3,4,5),2) val pRDD2: RDD[Int] = sc.parallelize(Seq(1,2,3,4,5),3) println("rdd print way 1:") pRDD1.foreach(println(_)) println("rdd print way 2:") pRDD2.foreach(println) //1-2sc.textfile() //1-3makeRDD val sRDD1: RDD[Int] = sc.makeRDD(Array(1,2,3,4,5),1)
-
可以在Action时对RDD操作形成DAG有向无环图进行Stage的划分和并行优化
3-RDD基础练习
3-1值类型
- map操作:将一个rdd通过函数形成新的rdd2
- filter操作:将一个原来的RDD通过filter内部的函数转为新的RDD
- flatMap操作:根据wordCount案例理解
- (了解)mapPartitons:对分区内部的数据实现map的操作,需要实现一个对应的函数
- (了解)mapPartitonsindex:分区位置
- sample
- 随机采样
- withReplacement表示是抽出的数据是否放回
- franctiion表示的是抽样的比例–0.6
- seed用于指定随机数生成器种子
- seed指定上一个固定的数值,能够保证每次采样的数据的可重复性
- 如:seed=1,取样数据1-3-4-5
- takeSamples:采用指定个数的数据
- 随机采样
- glom果需要打印每个分区中的具体的数值,可以采用
- val rdd = sc.parallelize(1 to 16,4)
- rdd.glom().collect
- sortBy:
- 根据对应数值进行排序,而不仅仅是根据key排序
- coalesce缩减分区
- repartitions重新shuffle分区
4-Transformation-ValueType
5-Transformation-DoubleValueType
- union求解两个RDD的并集
- intersection求解两个RDD的交集
- distinct求解RDD的去重后的数据
- substract:求解差集
- zip:拉链操作,具有相同维度的数据整合在一起
##6-ransformation-KeyValueType
- partitionBy根据key-value类型的数据进行hash和range的分区的操作,改变分区的大小
- reduceBykey:根据key对数据进行运算
- groupyByKey:根据key对相同key的value进行分组
- join:将具有相同key的value组合在一起
- cartesian:将数据的进行组合输出
- mapValue:对value执行操作
- sortByKey:根据key进行排序
7-Action
- 直接运行得到结果,Action算子之前是很多的Transformer算子
- reduce,通过fun函数实现运算
- count:统计计数
- first:第一个元素
- take:求解出前k个元素
- saveAsTextFile:将数据保存在hdfs文件中
- saveASObjectFile:将数据保存在对象文件
- countByKy:根据key进行统计计数
- foreach:根据函数循环输出
- foreach(x=>println(x))
- foreach(=>println())
- foreach(printin)
- foreach(println(_))
- 数值运算RDD的操作
- max
- min
- stdev
- mean
- variance
- …
8-RDD常用算子的练习
-
aggregate (zeroValue: U)(seqOp: (U, T) ⇒ U, combOp: (U, U) ⇒ U)
-
**fold(**num)(func)
-
- zeroValue是初始值,可以赋值其他的数值
- seqOp是分区内的操作,需要和初始值进行运算
- combOp分区间的操作,需要和初始值进行运算
- 总体上加了三次的初始值
- var rdd1 = sc.makeRDD(1 to 10,2)
- rdd1.glom().collect
- rdd1.aggregate(0)(_+_,_+_)
- rdd1.aggregate(10)(_+_,_+_)
- rdd1.fold(10)(_+_,_+_)
-
aggregateByKey(zeroValue:U,[partitioner: Partitioner])(seqOp: (U, V) => U,combOp: (U, U) => U)
- 根据key进行聚合操作,通过初始值,和分区内的函数seqOp和分区间的函数combOp
-
foldByKey(zeroValue: V)(func: (V, V) => V): RDD[(K, V)]
- aggregateByKey的简化版本
-
重点算子
- valueType
- map
- filter
- flatMap
- glom
- sortBy
- coalesce
- repartition
- DoubleValueType
- union
- intersection
- distinct
- substract
- zip
- key-value
- reduceByKey
- groupByKey
- sortByKey
- join
- cartesian
- Action
- first
- take
- count
- reduce
- countByKey
- foreach
- saveASTextFile
- valueType
-
总结
10-RDD依赖关系
-
Spark中依赖关系Denpencies—RDD的五大属性的第三大属性
- [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-59VzJlA4-1614062471402)(assets/1574477969610.png)]
-
RDD的依赖的分类
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-otmDXygS-1614062471407)(assets/1574478008252.png)]
-
窄依赖:
- 更好的理解,一个子RDD如果依赖一个父RDD就是窄依赖,如上图的左侧
-
宽依赖:
- 更好的理解:一个子RDD如果依赖多个父RDD就是宽依赖,如上图的右侧
-
子RDD的一个分区依赖多个父RDD是宽依赖还是窄依赖?
- 不能确定,也就是宽窄依赖的划分依据是父RDD的一个分区是否被子RDD的多个分区所依赖,是,就是宽依赖,或者从shuffle的角度去判断,有shuffle就是宽依赖。
- 有shuffle的阶段就称之为宽依赖
-
-
为什么需要宽依赖和窄依赖?
- 1-窄依赖可以使得运行的程序并行化的执行
- 2-宽依赖是stages的划分依据
-
lineage血统概念:
- Spark容错机制的重要概念
- RDD只支持粗粒度转换,即只记录单个块上执行的单个操作
- RDD的Lineage会记录RDD的元数据信息和转换行为
- 目的:当该RDD的部分分区数据丢失时,它可以根据这些信息来重新运算和恢复丢失的数据分区。
- Spark容错机制的重要概念