Spark相关
一、Spark运行流程
1、Driver 端提交任务,向Master 申请资源
2、Master 与Work 进行RPC 通信,让Work启动Executor
3、Executor 启动会主动连接Drive ,通过Drive->Master->Work-Executor 从而得
到Driver 在哪里
4、Driver 会产生Task,提交给Executor 中启动Task去做真正的计算
二、Spark运行模式
1、本地模式:Spark 单机运行,一般用于开发测试。
2、Standalone 模式:构建一个由Master+Slave 构成的Spark 集群,Spark 运行在集群中。StandAlone 模式对内存要求高,
3、Spark on Yarn 模式:Spark 客户端直接连接Yarn。不需要额外构建Spark 集群。Spark on yarn 可以提高Hadoop 集群的计算速度。
4、Spark on Mesos 模式:Spark 客户端直接连接Mesos。不需要额外构建Spark 集群。
Spark on YARN模式根据Driver在集群中的位置分为两种模式:一种是YARN-Client模式,另一种是YARN-Cluster(或称为YARN-Standalone模式)。
三、Yarn-client与Yarn-cluster
yarn-client:主要用于测试,driver 在本地客户端,集群产生超大量的网络通信时容易网卡流量过大,导致任务失败,这种方式的好处是执行时本地可以看到所有log 方便调试。
yarn-cluster:用于生产环境,因为driver 运行NM上,没有网卡流量的问题,缺点在于,调试不方便,本地用spark-submit 提交之后,看不到log,只能通过yarn app logs 这种命令查看,很麻烦
四、Spark和MapReduce区别
1、spark 和mapreduce 的shuffle 相比, spark 的shuffle 过程不用等,用的时候再进行排序
2、spark 可以把经常用到的中间数据通过RDD放入内存中,而maprduce 需要通过HDFS 从磁盘中取数据
3、spark 会的招式多,各种算子方便计算
4、spark 过度依赖内存,当内存不够的时候,就很难堪。(此原因是因为频繁GC会导致task 线程等待)
五、DataFrame、Dataset、RDD的区别与联系
RDD是分布式的 Java对象的集合。DataFrame是分布式的Row对象的集合。Dataset可以认为是DataFrame的一个特例,主要区别是Dataset每一个record存储的是一个强类型值而不是一个Row。
相同点:
1、RDD、DataFrame、Dataset全都是spark平台下的分布式弹性数据集,为处理超大型数据提供便利
2、三者都有惰性机制,在进行创建、转换,如map方法时,不会立即执行,只有在遇到Action如foreach时,三者才会开始遍历运算
3、三者都会根据spark的内存情况自动缓存运算
4、三者都有partition的概念
5、三者有许多共同的函数,如filter,排序等
不同点:
RDD:
1、RDD一般和spark mlib同时使用
2、RDD不支持sparksql操作
DataFrame:
1、DataFrame每一行的类型固定为Row,只有通过解析才能获取各个字段的值
2、DataFrame与Dataset一般与spark ml同时使用
3、DataFrame与Dataset均支持sparksql的操作
4、DataFrame与Dataset支持一些特别方便的保存方式,比如保存成csv
六、Partition分区机制
Spark从HDFS读入文件的分区数默认等于HDFS文件的块数(blocks),HDFS中的block是分布式存储的最小单元。如果我们上传一个30GB的非压缩的文件到HDFS,HDFS默认的块容量大小128MB,因此该文件在HDFS上会被分为235块(30GB/128MB);Spark读取SparkContext.textFile()读取该文件,默认分区数等于块数即235。
分区太多太少都不好。
分区数太多意味着任务数太多,每次调度任务也是很耗时的,所以分区数太多会导致总体耗时增多。
分区数太少的话,会导致一些结点没有分配到任务;另一方面,分区数少则每个分区要处理的数据量就会增大,从而对每个结点的内存要求就会提高;还有分区数不合理,会导致数据倾斜问题。
一般合理的分区数设置为总核数的2~3倍。
七、如何处理Spark数据倾斜
1、可以用hive 将发生倾斜的key做聚合
2、进行数据的清洗,把发生倾斜的刨除,用单独的程序去除倾斜的key
3、提高shuffle 的并行度,用随机前缀,方法是打上随机前缀先聚合一次,然后去掉随机前缀再聚合一次。适用场景groupby
4、指定“倍数”的数据扩容加上随机“倍数”值前缀。适用场景join
5、小数据join 大数据,就用map join
6、能不shuffle 就不shuffle
八、checkpoint 操作
RDD持久化算子:
1、cache:将数据持久化到内存
2、persist:可以将数据持久化到磁盘,也可以将数据持久化到内存
3、checkpoint:将数据持久化到磁盘。
九、Spark-Streaming
Spark-Streaming基本工作原理:
接收实时输入数据流,然后将数据拆分成多个batch,比如每收集5秒的数据封装为一个batch,然后将每个batch交给Spark的计算引擎进行处理,最后会生产出一个结果数据流,其中的数据,也是由一个一个的batch所组成的。
十、RDD依赖
RDD在每次转化时候,会生成一个新的RDD,但新的RDD和旧的RDD之间保持着关系,就是依赖,依据依赖的样式,可以划分为窄依赖和宽依赖;
窄依赖是指每个父RDD的Partition最多被子RDD的一个Partition所使用,例如map、filter。
宽依赖是指一个父RDD的Partition会被多个子RDD的Partition所使用,例如groupByKey、reduceByKey等。
十一、RDD的持久化
当你把RDD持久化,每个Node会存储RDD的分区在内存,在其他action中用到此rdd的时候,就不用从头转化,而是直接使用。你可以用persist或者cache方法持久化rdd,Spark的缓存是一个容错的技术:如果RDD的任何一个分区丢失,它可以通过原有的转换 (transformations)操作自动的重复计算并且创建出这个分区。另外,每一个RDD可以选择不同的持久化级别。
MEMORY_ONLY:把RDD非序列化为Java对象存在jvm中,如果RDD不适合持久化在内存中,RDD的一些分区可能不能持久化,让此RDD需要的时候,此丢失的RDD分区会重新计算获取;
MEMORY_AND_DISK:将RDD作为非序列化的Java对象存储在jvm中。如何RDD不适合存在内存中,将这些不适合存在内存的分区存在磁盘中
MEMORY_ONLY_SER:把RDD序列化为Java对象存在jvm中,如果RDD不适合持久化在内存中,RDD的一些分区可能不能持久化,让此RDD需要的时候,此丢失的RDD分区会重新计算获取;
DISK_ONLY:仅仅存在磁盘中。
Spark也会自动持久化一些shuffle操作(如 reduceByKey )中的中间数据,即使用户没有调用 persist 方法。这样的好处是避免了在shuffle出错情况下,需要重复计算整个输入。
十二、Spark的Shuffle 和 MR的Shuffle
1、MR的Shuffle中,将拉取过来的数据会进行合并排序(merge sort),是在磁盘上进行的,有效的控制了内存的使用,但是代价是更多的磁盘I/O
2、Spark的Shuffle,在大多数情况下,拉取(fetch)的数据不需要sort,因此Spark并不在Reducer端进行merge sort,而是使用聚合(aggregator),实际上使用hashmap,来一个处理一个,存放在Partition中,为了使得内存能够容纳这个Partition,可以增加Mapper和Reducer的数量来减少Partition的大小。但是弊端是Partition多了,会带来Shuffle write时桶的write handle。所以要权衡。
十三、Spark中的常用算子
Spark支持两种RDD操作:transformation和action。transformation操作会针对已有的RDD创建一个新的RDD;而action则主要是对RDD进行最后的操作。
transformation的特点就是lazy特性。如果一个spark应用中只定义了transformation操作,那么即使你执行该应用,这些操作也不会执行。
action操作执行,会触发一个spark job的运行,从而触发这个action之前所有的transformation的执行。
Transformation:
1、map:map的输入变换函数应用于RDD中所有元素,而mapPartitions应用于所有分区。区别在于mapPartitions主要在于调用粒度不同。
2、flatMap:map是对RDD中元素逐一进行函数操作映射为另外一个RDD,而flatMap操作是将函数应用于RDD之中的每一个元素,将返回的迭代器的所有内容构成新的RDD。map对每一次(func)都产生一个元素,返回一个对象,而flatMap多一步就是将所有对象合并为一个对象。
3、mapPartitions:区于foreachPartition(属于Action,且无返回值),而mapPartitions可获取返回值。
4、filter:过滤操作,满足filter内function函数为true的RDD内所有元素组成一个新的数据集。
5、sample:采样操作,用于从样本中取出部分数据。withReplacement是否放回,fraction采样比例,seed用于指定的随机数生成器的种子。
6、union:对于源数据集和其他数据集求并集,不去重。
7、intersection:对于源数据集和其他数据集求交集,并去重,且无序返回。
8、distinct:返回一个在源数据集去重之后的新数据集,即去重,并局部无序而整体有序返回。
9、groupByKey:将相同的所有的键值对分组到一个集合序列当中,其顺序是不确定的。
10、reduceByKey:与groupByKey类似,reduceByKey主要作用是聚合,groupByKey主要作用是分组。如(a,1), (a,2), (b,1), (b,2)。groupByKey产生中间结果为( (a,1), (a,2) ), ( (b,1), (b,2) )。而reduceByKey为(a,3), (b,3)。
11、sortByKey:基于pairRDD的,根据key值来进行排序。ascending升序,默认为true,即升序。
12、join:加入一个RDD,在一个(k,v)和(k,w)类型的dataSet上调用,返回一个(k,(v,w))的pair dataSet。
Action:
1、reduce:将RDD中元素两两传递给输入函数,同时产生一个新值,新值与RDD中下一个元素再被传递给输入函数,直到最后只有一个值为止。
2、collect:将一个RDD以一个Array数组形式返回其中的所有元素。
3、count:返回数据集中元素个数,默认Long类型。
4、take(n):返回一个包含数据集前n个元素的数组(从0下标到n-1下标的元素),不排序。
5、takeOrdered:返回RDD中前n个元素,并按默认顺序排序(升序)或者按自定义比较器顺序排序。
6、saveAsTextFile:将dataSet中元素以文本文件的形式写入本地文件系统或者HDFS等。Spark将对每个元素调用toString方法,将数据元素转换为文本文件中的一行记录。若将文件保存到本地文件系统,那么只会保存在executor所在机器的本地目录。
7、countByKey:用于统计RDD[K,V]中每个K的数量,返回具有每个key的计数的(k,int)pairs的hashMap。
8、foreach:对数据集中每一个元素运行函数function。