Spark
- Spark VS MapReduce
- Spark VS Hadoop
- spark如何保证宕机迅速恢复?
- RDD持久化原理?
- checkpoint检查点机制?
- checkpoint和持久化机制的区别?
- RDD机制理解吗?
- rdd、dataset、dataframe数据区别,如何转换,为何转换
- Spark streaming以及基本工作原理?
- DStream以及基本工作原理?
- spark有哪些组件?
- spark工作机制?
- 说下宽依赖和窄依赖
- Spark主备切换机制原理知道吗?
- spark解决了hadoop的哪些问题?
- 数据倾斜的产生和解决办法?
- 你用sparksql处理的时候, 处理过程中用的dataframe还是直接写的sql?为什么?
- 现场写一个笔试题
- RDD中reduceBykey与groupByKey哪个性能好,为什么
- Spark master HA主从切换过程不会影响到集群已有作业的运行,为什么
- spark master使用zookeeper进行ha,有哪些源数据保存到Zookeeper里面
- 数仓模型建设
- MR过程
- Spark OOM解决方法
- Spark参数调优
- parquet存储格式
- Spark standalone 模式
- 解析json
1. Spark VS MapReduce
spark是借鉴了Mapreduce 并在其基础上发展起来的,继承了其分布式计算的优点并进行了改进,spark生态更为丰富,功能更为强大,性能更加适用范围广,mapreduce更简单,稳定性好对性能的要求也相对较弱,适合长期后台运行。
1. Spark基于内存计算,MR基于磁盘计算+容错性对比
2. Spark 是多线程模型,MR是多进程模型
3. Spark比MR更灵活丰富
(1) Spark内存计算VS MapReduce读写磁盘MapReduce:MapReduce通常需要将计算的中间结果写入磁盘。map进程和reduce进程需要读取指定位置的数据作为输入,如果不将中间结果写入磁盘以保证可靠存储,一旦中间结果丢失或者损坏,MapReduce没有机制能够恢复中间结果(容错性差); 一个job可能涉及到多个stage,而每个stage的处理结果都需要存储到HDFS中,这就必然导致频繁的磁盘IO,导致性能下降。Spark:在Spark中一个job的多个stage任务可以串联或者并行执行,stage的中间结果不需要写入磁盘是基于内存计算的从而提升了处理性能。(容错性高)这得益于Spark的RDD(弹性分布式数据集)和DAG(有向无环图)。RDD是Spark中引入的一种只读的、可扩展的数据结构,DAG则记录了job的stage以及在job执行过程中父RDD和子RDD之间的依赖关系。中间结果能够以RDD的形式存放在内存中,一旦Job中的某个RDD丢失或者损坏,则可以根据血缘关系记录的元数据信息和转换行为来重新计算得到该RDD。
(2)Hadoop的MapReduce的Map Task和Reduce Task都是进程级别的,每次创建task需要创建进程,开销大(每个MapTask/ReduceTask都要经历申请资源 -> 运行task -> 释放资源的过程);而Spark的Task则是基于多线程模型的,每个worker节点运行一个或多个executor服务,每个executor是一个进程,每个task作为线程运行在executor中,task间可共享资源(同一节点上所有task运行在一个executor中,有利于共享内存。比如通过Spark的广播变量,将某个文件广播到executor端,那么在这个executor中的task不用每个都拷贝一份处理,而只需处理这个executor持有的共有文件即可);Spark通过复用线程池中的线程来减少启动、关闭task所需要的开销(executor所占资源不会在一些task运行结束后立即释放掉,可连续被多批任务使用,这避免了每个任务重复申请资源带来的开销)
(3)MR仅支持map和reduce两种操作。当一个计算逻辑复杂的时候,需要写多个MR任务运行(并且这些MR任务生成的结果在下一个MR任务使用时需要将数据持久化到磁盘才行)。 Spark编程模型更灵活,提供了transformation和action这两大类的多功能api,另外还有流式处理spark streaming模块、图计算等。。
2. Spark VS Hadoop
Hadoop由于作业间的通信都依赖于磁盘,适合应用在处理可延时性比较高,数据量比较大,长期后台运行的场景
从 Spark 的设计理念(基于内存的迭代计算框架)出发,其最适合有迭代运算的或者需要多次操作特定数据集的应用场合。并且迭代次数越多,读取的数据量越大,Spark 的应用效果就越明显。因此,对于机器学习之类的“迭代式”应用,Spark要比 Hadoop MapReduce 快数十倍。另外,Spark Streaming因为内存存储中间数据的特性,处理速度非常快,也可以应用于需要实时处理大数据的场合。
Hadoop底层使用MapReduce计算架构,只有map和reduce两种操作,表达能力比较欠缺,而且在MR过程中会重复的读写hdfs,造成大量的磁盘io读写操作,所以适合高时延环境下批处理计算的应用;
Spark是基于内存的分布式计算架构,提供更加丰富的数据集操作类型,主要分成转化操作和行动操作,包括map、reduce、filter、flatmap、groupbykey、reducebykey、union和join等,数据分析更加快速,所以适合低时延环境下计算的应用;
spark与hadoop最大的区别在于迭代式计算模型。基于mapreduce框架的Hadoop主要分为map和reduce两个阶段,两个阶段完了就结束了,所以在一个job里面能做的处理很有限;spark计算模型是基于内存的迭代式计算模型,可以分为n个阶段,根据用户编写的RDD算子和程序,在处理完一个阶段后可以继续往下处理很多个阶段,而不只是两个阶段。所以spark相较于mapreduce,计算模型更加灵活,可以提供更强大的功能。
但是spark也有劣势,由于spark基于内存进行计算,虽然开发容易,但是真正面对大数据(一般来说,10TB 以上(单次分析)的数据就可以算是“超级大”的数据了)的时候,在没有进行调优的情况下,可能会出现各种各样的问题,比如OOM内存溢出等情况,导致spark程序可能无法运行起来,而mapreduce虽然运行缓慢,但是至少可以慢慢运行完。
3. spark如何保证宕机迅速恢复?
适当增加spark standby master
编写shell脚本,定期检测master状态,如果不是running就对master进行重启操作
4. RDD持久化原理?
spark非常重要的一个功能特性就是可以将RDD持久化在JVM的堆内存中。但是并不是这两个方法被调用时立即缓存,而是触发后面的 action 算子时,该 RDD 将会被缓存在计算节点的内存中,并供后面重用。调用cache()和persist()方法即可。cache()和persist()的区别在于,cache()是persist()的一种简化方式,cache()的底层就是调用persist()的无参版本persist(MEMORY_ONLY),将数据持久化到内存中。如果需要从内存中清除缓存,可以使用unpersist()方法。RDD持久化是可以手动选择不同的策略的。在调用persist()时传入对应的StorageLevel即可。
5. checkpoint检查点机制?
应用场景:当spark应用程序特别复杂,从初始的RDD开始到最后整个应用程序完成有很多的步骤,而且整个应用运行时间特别长,这种情况下就比较适合使用checkpoint功能。
原因:对于特别复杂的Spark应用,会出现某个反复使用的RDD,即使之前持久化过但由于节点的故障导致数据丢失了,没有容错机制,所以需要重新计算一次数据。
Checkpoint首先会调用SparkContext的setCheckPointDIR()方法,设置一个容错的文件系统的目录,比如说HDFS;然后对RDD调用checkpoint()方法。之后在RDD所处的job运行结束之后,会启动一个单独的job,来将checkpoint过的RDD数据写入之前设置的文件系统,进行高可用、容错的类持久化操作。
检查点机制是我们在spark streaming中用来保障容错性的主要机制,它可以使spark streaming阶段性的把应用数据存储到诸如HDFS等可靠存储系统中,以供恢复时使用。具体来说基于以下两个目的服务:
- 控制发生失败时需要重算的状态数。Spark streaming可以通过转化图的谱系图来重算状态,检查点机制则可以控制需要在转化图中回溯多远。
- 提供驱动器程序容错。如果流计算应用中的驱动器程序崩溃了,你可以重启驱动器程序并让驱动器程序从检查点恢复,这样spark streaming就可以读取之前运行的程序处理数据的进度,并从那里继续。
6. checkpoint和持久化机制的区别?
最主要的区别在于持久化只是将数据保存在BlockManager中,但是RDD的lineage(血缘关系,依赖关系)是不变的。但是checkpoint执行完之后,rdd已经没有之前所谓的依赖rdd了,而只有一个强行为其设置的checkpointRDD,checkpoint之后rdd的lineage就改变了。
持久化的数据丢失的可能性更大,因为节点的故障会导致磁盘、内存的数据丢失。但是checkpoint的数据通常是保存在高可用的文件系统中,比如HDFS中,所以数据丢失可能性比较低
- 血缘关系:Cache 缓存只是将数据保存起来,不切断血缘依赖。Checkpoint 检查点切断血缘依赖,重新建立血缘关系,相当于改变了数据源。
- 存储安全及性能: Cache 将数据临时存储在内存中,可靠性低。persist 可以选择存储级别,可以存在磁盘中,会涉及到磁盘IO 性能较低但数据安全。如果Job执行完毕,临时保存的数据文件就会丢失。Checkpoint 的数据通常存 储在 HDFS 等容错、高可用的文件系统,可靠性高,会涉及到磁盘IO,性能较低
- checkpoint和cache联合使用:建议对 checkpoint()的 RDD 使用 Cache 缓存,这样 checkpoint 的 job 只需从 Cache 缓存 中读取数据即可,否则需要再从头计算一次 RDD。
7. RDD机制理解吗?
- rdd分布式弹性数据集,简单的理解成一种数据结构,是spark框架上的通用货币。所有算子都是基于rdd来执行的,不同的场景会有不同的rdd实现类,但是都可以进行互相转换。rdd执行过程中会形成dag图,然后形成lineage保证容错性等。从物理的角度来看rdd存储的是block和node之间的映射。
- RDD是spark提供的核心抽象,全称为弹性分布式数据集。
- RDD在逻辑上是一个hdfs文件,在抽象上是一种元素集合,包含了数据。它是被分区的,分为多个分区,每个分区分布在集群中的不同结点上,从而让RDD中的数据可以被并行操作(分布式数据集)
- 比如有个RDD有90W数据,3个partition,则每个分区上有30W数据。RDD通常通过Hadoop上的文件,即HDFS或者HIVE表来创建,还可以通过应用程序中的集合来创建;RDD最重要的特性就是容错性,可以自动从节点失败中恢复过来。即如果某个结点上的RDD partition因为节点故障,导致数据丢失,那么RDD可以通过自己的数据来源重新计算该partition。这一切对使用者都是透明的。
- RDD的数据默认存放在内存中,但是当内存资源不足时,spark会自动将RDD数据写入磁盘。比如某结点内存只能处理20W数据,那么这20W数据就会放入内存中计算,剩下10W放到磁盘中。RDD的弹性体现在于RDD上自动进行内存和磁盘之间权衡和切换的机制。
8. rdd、dataset、dataframe数据区别,如何转换,为何转换
RDD:RDD (Resilient Distributed Dataset) 叫做弹性分布式数据集,它归属于SpqrkCore模块中,是Spark中最基本的数据抽象,代码中RDD是一个抽象类,它代表一个弹性的、不可变、可分区、里面的元素可并行计算的集合。并且RDD表示只读的分区的数据集,对RDD进行改动,只能通过RDD的转换操作来进行。
DataFrame: 归属于SparkSql模块里面,是一种以RDD为基础的分布式数据集,类似于传统数据库中的二维表格。相对于RDD来讲它多了schema元信息,即DataFrame它里面是结构化的信息包含了每一列的字段名和类型,这让SparkSql可以很方便的清楚了数据的具体信息,提升了任务的执行效率。
DataSet: 也是归属于SparkSql模块,具有Spark SQL优化执行引擎的优点,它是建立在DataFrame之上的一个分布式数据集合,DateSet整合了RDD和DataFrame的优点,因为RDD支持的是非结构化的数据,DataFrame支持的是结构化的数据,而DataSet支持结构化和非结构化数据。相对于DataFrame来说DataSet它提供的是一种强类型的获取数据的方法(因为在DataFrame中获取某列数据你需要知道数据的类型以及索引,假设获取第一列的name需要getString(0) ,而在DataSet中只需要_.name就可以了),所以说它和DataFrame的最核心区别是在类型的判定上面,DataFrame在运行期才做类型的检查,而DataSet在程序的编译期就会做类型的检查,多了类型校验的功能。还有就是DataSet既具有类型安全检查也具有DataFrame的查询优化特性。
9. Spark streaming以及基本工作原理?
Spark streaming是spark core API的一种扩展,可以用于进行大规模、高吞吐量、容错的实时数据流的处理。
它支持从多种数据源读取数据,比如Kafka、Flume、Twitter和TCP Socket,并且能够使用算子比如map、reduce、join和window等来处理数据,处理后的数据可以保存到文件系统、数据库等存储中。
Spark streaming内部的基本工作原理是:接受实时输入数据流,然后将数据拆分成batch,比如每收集一秒的数据封装成一个batch,然后将每个batch交给spark的计算引擎进行处理,最后会生产处一个结果数据流,其中的数据也是一个一个的batch组成的。
10. DStream以及基本工作原理?
- DStream是spark streaming提供的一种高级抽象,代表了一个持续不断的数据流。
- DStream可以通过输入数据源来创建,比如Kafka、flume等,也可以通过其他DStream的高阶函数来创建,比如map、reduce、join和window等。
- DStream内部其实不断产生RDD,每个RDD包含了一个时间段的数据。
- Spark streaming一定是有一个输入的DStream接收数据,按照时间划分成一个一个的batch,并转化为一个RDD,RDD的数据是分散在各个子节点的partition中。
11. spark有哪些组件?
1)Spark core:是其它组件的基础,spark的内核,主要包含:有向无环图、RDD、Lingage、Cache、broadcast等,并封装了底层通讯框架,是Spark的基础。
2)SparkStreaming是一个对实时数据流进行高通量、容错处理的流式处理系统,可以对多种数据源(如Kafka、Flume、Twitter、Zero和TCP 套接字)进行类似Map、Reduce和Join等复杂操作,将流式计算分解成一系列短小的批处理作业。
3)Spark sql:Shark是SparkSQL的前身,Spark SQL能够统一处理关系表和RDD,可使用SQL命令进行外部查询,同时进行更复杂的数据分析。
4)MLBase是Spark生态圈的一部分专注于机器学习。MLBase分为四部分:MLlib、MLI、ML Optimizer和MLRuntime。
5)GraphX是Spark中用于图和图并行计算
6)集群管理器 :Spark支持在各种集群管理器(cluster manager)上运行,包括Hadoop的YARN、Apache的Mesos以及Spark自带的一个简易调度器,叫独立调度器。
12. spark工作机制 - 运行原理?
用户在client端提交作业后,会由Driver运行main方法并创建spark context上下文。执行rdd算子,形成dag图输入dagscheduler,按照rdd之间的依赖关系划分stage输入task scheduler。task scheduler会将stage划分为task set分发到各个节点的executor中执行。
(1) Job 是以 Action 方法为界,遇到一个 Action 方法则触发一个 Job。
(2) Stage 是 Job 的子集,以 RDD 宽依赖(即 Shuffle)为界,遇到 Shuffle 做一次划分。
(3) Task 是 Stage 的子集,以并行度(分区数)来衡量,分区数是多少,则有多少个 task。
DAG Scheduler 工作流程:
DAG Scheduler是一个高级的scheduler 层,他实现了基于stage的调度,他为每一个job划分stage,并将单个stage分成多个task,然后他会将stage作为taskSet提交给底层的Task Scheduler,由Task Scheduler执行。
Task Schedule 工作流程:
Task Scheduler是sparkContext中除了DAG Scheduler的另一个非常重要的调度器,
Task Scheduler 负责将TaskSetPool中的task调度到executor中执行,一般的调度模式是FIFO(先进先出),也可以按照FAIR(公平调度)的调度模式,具体根据配置而定。其中FIFO:顾名思义是先进先出队列的调度模式,而FAIR则是根据权重来判断,权重可以根据资源的占用率来分,如可设占用较少资源的task的权重较高。这样就可以在资源较少时,调用后来的权重较高的task先执行了。至于每个executor中同时执行的task数则是由分配给每个executor中cpu的核数决定的。
13. 说下宽依赖和窄依赖
宽依赖: 本质就是shuffle。父RDD的每一个partition中的数据,都可能会传输一部分到下一个子RDD的每一个partition中,此时会出现父RDD和子RDD的partition之间具有交互错综复杂的关系,这种情况就叫做两个RDD之间是宽依赖。
窄依赖: 父RDD和子RDD的partition之间的对应关系是一对一的。
14. Spark主备切换机制原理知道吗?
Master实际上可以配置两个,Spark原生的standalone模式是支持Master主备切换的。当Active Master节点挂掉以后,我们可以将Standby Master切换为Active Master。
Spark Master主备切换可以基于两种机制,一种是基于文件系统的,一种是基于ZooKeeper的。
基于文件系统的主备切换机制,需要在Active Master挂掉之后手动切换到Standby Master上;
而基于Zookeeper的主备切换机制,可以实现自动切换Master。
15. spark解决了hadoop的哪些问题?
- MR:抽象层次低,需要使用手工代码来完成程序编写,使用上难以上手;
- Spark:Spark采用RDD计算模型,简单容易上手。
- MR:只提供map和reduce两个操作,表达能力欠缺;
- Spark:Spark采用更加丰富的算子模型,包括map、flatmap、groupbykey、reducebykey等;
- MR:一个job只能包含map和reduce两个阶段,复杂的任务需要包含很多个job,这些job之间的管理以来需要开发者自己进行管理;
- Spark:Spark中一个job可以包含多个转换操作,在调度时可以生成多个stage,而且如果多个map操作的分区不变,是可以放在同一个task里面去执行;
- MR:中间结果存放在hdfs中;
- Spark:Spark的中间结果一般存在内存中,只有当内存不够了,才会存入本地磁盘,而不是hdfs;
- MR:只有等到所有的map task执行完毕后才能执行reduce task;
- Spark:Spark中分区相同的转换构成流水线在一个task中执行,分区不同的需要进行shuffle操作,被划分成不同的stage需要等待前面的stage执行完才能执行。
- MR:只适合batch批处理,时延高,对于交互式处理和实时处理支持不够;
- Spark:Spark streaming可以将流拆成时间间隔的batch进行处理,实时计算。
16. 数据倾斜的产生和解决办法?
SPARK数据倾斜原因与解决方法大总结__Kafka_的博客-CSDN博客
数据倾斜意味着某一个或者某几个partition的数据特别大,导致这几个partition上的计算需要耗费相当长的时间。
在spark中同一个应用程序划分成多个stage,这些stage之间是串行执行的,而一个stage里面的多个task是可以并行执行,task数目由partition数目决定,如果一个partition的数目特别大,那么导致这个task执行时间很长,导致接下来的stage无法执行,从而导致整个job执行变慢。
- 缓解数据倾斜的方法,并不能根本上解决数据倾斜
- 丢弃数据:可考虑过滤掉导致数据倾斜的key对应的数据(比如在测试逻辑的时候)
- 提高shuffle操作中的reduce并行度(spark.sql.shuffle.partitions默认是200)
解决数据倾斜的方法:
- 适用于聚合类的shuffle操作(groupbyKey,reduceByKey等),使用随机key实现双重聚合:通过 map 算子给每个数据的 key 添加随机数前缀,对 key 进行打散,将原先一 样的 key 变成不一样的 key,然后进行第一次聚合,这样就可以让原本被一个 task 处理的数 据分散到多个 task 上去做局部聚合;随后,去除掉每个 key 的前缀,再次进行聚合。
- 适用于(小表join大表时)join产生的shuffle: reduce join 转换为map join。普通的join是会走shuffle过程的,相当于将相同key的数据拉取到一个shuffle read task中在进行join,也就是reduce join。如果一个数据集比较小,则可以采用广播小 RDD 全量数据+map 算子来实现与 join 同样的效果,也就是 map join, 避免发生 shuffle 操作,也就不会发生数据倾斜。(注意,RDD 是并不能进行广播的,只能将 RDD 内部的数据通过 collect 拉取到 Driver 内 存然后再进行广播)
核心思路:不使用 join 算子进行连接操作,而使用 Broadcast 变量与 map 类算子实现 join 操作,进 而完全规避掉 shuffle 类的操作,彻底避免数据倾斜的发生和出现。将较小 RDD 中的数据直 接通过 collect 算子拉取到 Driver 端的内存中来,然后对其创建一个 Broadcast 变量;接着对 另外一个 RDD 执行 map 类算子,在算子函数内,从 Broadcast 变量中获取较小 RDD 的全量 数据,与当前 RDD 的每一条数据按照连接 key 进行比对,如果连接 key 相同的话,那么就 将两个 RDD 的数据用你需要的方式连接起来。
-
当由单个key造成数据倾斜时,sample 采样对倾斜 key 单独进行 join(不适用于导致数据倾斜的key很多的情况)。当由单个 key 导致数据倾斜时,可有将发生数据倾斜的 key 单独提取出来,组成一个 RDD,然后用这个原本会导致倾斜的 key 组成的 RDD 和其他 RDD 单独 join,再与普通key和其他RDD join的结果union起来。当数据量非常大时,可以考虑使用 sample 采样获取 10%的数据,然后分析这 10%的数据中哪个 key 可能会导致数据倾斜,然后将这个 key 对应的数据单独提取出来。(如果某个 RDD 只有一个 key,那么在 shuffle 过程中会默认将此 key 对应的数据打散,由不同的 reduce 端 task 进行处理)
-
适用于多个key导致的数据倾斜,可使用随机数扩容进行 join。选择一个 RDD,使用 flatMap 进行扩容,对每条数据的 key 添加数值前缀(1~N 的数值),将一条数据映射为多条数据;(扩容);选择另外一个 RDD,进行 map 映射操作,每条数据的 key 都打上一个随机数作为前缀 (1~N 的随机数);(稀释),将两个处理后的 RDD,进行 join 操作,再将随机数去掉。如果两个 RDD 都很大,那么将 RDD 进行 N 倍的扩容显然行不通; 使用扩容的方式只能缓解数据倾斜,不能彻底解决数据倾斜问题。
当 RDD 中有几个 key 导致数据倾斜时,方案3不再适用,而方案4又非常消耗资源,此时可以引入方案4的思想完善方案3:
➢ 对包含少数几个数据量过大的 key 的那个 RDD,通过 sample 算子采样出一份样本来, 然后统计一下每个 key 的数量,计算出来数据量最大的是哪几个 key。 然后将这几个key对应的数据从原来的RDD中拆分出来,形成一个单独的RDD,并给 每个key都打上n以内的随机数作为前缀。而不会导致倾斜的大部分key形成另外一个RDD。
➢ 接着将需要 join 的另一个 RDD,也过滤出来那几个倾斜 key 对应的数据并形成一个单独的 RDD,将每条数据膨胀成 n 条数据,这 n 条数据都按顺序附加一个 0~n 的前缀。不会导致倾斜的大部分 key 也形成另外一个 RDD。
➢ 再将附加了随机前缀的独立 RDD 与另一个膨胀 n 倍的独立 RDD 进行 join,此时就可以将原先相同的 key 打散成 n 份,分散到多个 task 中去进行 join 了。而另外两个普通的RDD就照常join即可。 最后将两次join的结果使用union算子合并起来即可,就是最终的join结果。
17. 你用sparksql处理的时候, 处理过程中用的dataframe还是直接写的sql?为什么?
DataFrame是一个分布式的数据集合,它按行组织,每行包含一组列,每列都有一个名称和一个关联的类型。换句话说,这个分布式数据集合具有由Schema定义的结构。你可以将它视为关系数据库中的表,但在底层,它具有更丰富的优化。
Spark SQL 是由DataFrame派生出来的,使用Spark SQL 之前必须先创建DataFrame,再注册临时表,然后才能使用Spark SQL。
Spark DataFrame是Spark的核心基础类, Spark SQL 是对DataFrame的高级封装。
Spark SQL相比于Spark DataFrame更灵活易用。
18. 现场写一个笔试题
有hdfs文件,文件每行的格式为作品ID,用户id,用户性别。请用一个spark任务实现以下功能:统计每个作品对应的用户(去重后)的性别分布。输出格式如下:作品ID,男性用户数量,女性用户数量
sc.textfile().flatmap(.split(","))//分割成作品ID,用户id,用户性别
.map(((_.1,_._2),1))//((作品id,用户性别),1)
.reduceByKey(_+_)//((作品id,用户性别),n)
.map(_._1._1,_._1._2,_._2)//(作品id,用户性别,n)
19. RDD中reduceBykey与groupByKey哪个性能好,为什么
从 shuffle 的角度: reduceByKey 和 groupByKey 都存在 shuffle 的操作,但是 reduceByKey 可以在 shuffle 前对分区内相同 key 的数据进行预聚合(combine)功能,这个操作是发生在map端的,在map端进行一次reduce之后,数据量会大幅度减小,从而减小传输,保证reduce端能够更快的进行结果计算。而 groupByKey 只是进行分组,不存在数据量减少的问题,会在reduce端 对每一个RDD中的value值进行聚合 形成一个序列(Iterator),所以势必会将所有的数据通过网络进行传输,造成不必要的浪费。同时如果数据量十分大,可能还会造成OutOfMemoryError。
从功能的角度:reduceByKey 包含分组和聚合的功能。groupByKey只能分组,不能聚合,所以在分组聚合的场合下,推荐使用 reduceByKey,如果仅仅是分组而不需要聚合。那么还是只能使用 groupByKey
reduceByKey 分区内和分区间的计算规则是相同的
所以在进行大量数据的reduce操作时候建议使用reduceByKey。不仅可以提高速度,还可以防止使用groupByKey造成的内存溢出问题。
20. Spark master HA主从切换过程不会影响到集群已有作业的运行,为什么
不会的。
因为程序在运行之前,已经申请过资源了,driver和Executors通讯,不需要和master进行通讯的。
21. spark master使用zookeeper进行ha,有哪些源数据保存到Zookeeper里面
spark通过这个参数spark.deploy.zookeeper.dir指定master元数据在zookeeper中保存的位置,包括Worker,Driver和Application以及Executors。standby节点要从zk中,获得元数据信息,恢复集群运行状态,才能对外继续提供服务,作业提交资源申请等,在恢复前是不能接受请求的。
1、在Master切换的过程中,所有的已经在运行的程序皆正常运行!
因为Spark Application在运行前就已经通过Cluster Manager获得了计算资源,所以在运行时Job本身的调度和处理和Master是没有任何关系。
2、在Master的切换过程中唯一的影响是不能提交新的Job:
一方面不能够提交新的应用程序给集群,因为只有Active Master才能接受新的程序的提交请求;
另外一方面,已经运行的程序中也不能够因Action操作触发新的Job的提交请求。
22. 数据建模都有哪些模型
星型模型星形模式(Star Schema)是最常用的维度建模方式。星型模式是以事实表为中心,所有的维度表直接连接在事实表上,像星星一样。 星形模式的维度建模由一个事实表和一组维表成,且具有以下特点: a. 维表只和事实表关联,维表之间没有关联; b. 每个维表主键为单列,且该主键放置在事实表中,作为两边连接的外键; c. 以事实表为核心,维表围绕核心呈星形分布;
雪花模型雪花模式(Snowflake Schema)是对星形模式的扩展。雪花模式的维度表可以拥有其他维度表的,虽然这种模型相比星型更规范一些,但是由于这种模型不太容易理解,维护成本比较高,而且性能方面需要关联多层维表,性能也比星型模型要低。所以一般不是很常用。
星座模型星座模式是星型模式延伸而来,星型模式是基于一张事实表的,而星座模式是基于多张事实表的,而且共享维度信息。前面介绍的两种维度建模方法都是多维表对应单事实表,但在很多时候维度空间内的事实表不止一个,而一个维表也可能被多个事实表用到。在业务发展后期,绝大部分维度建模都采用的是星座模式。
23. 数据仓库分层,分层的好处
合理的数据仓库分层一方面能够降低耦合性,提高重用性,可读性可维护性,另一方面也能提高运算的效率,影响到数据需求迭代的速度,近而影响到产品决策的及时性。
建立数据分层可以提炼公共层,避免烟囱式开发
问题简单化:将一个复杂的任务分解成多个步骤来完成,每一层只处理单一的步骤,比较简单和容易理解
数据结构化:每一个数据分层都有它的作用域,这样我们在使用表的时候能更方便地定位和理解。
提高复用性:规范数据分层,通过的中间层数据,能够减少极大的重复计算,增加一次计算结果的复用性。
隔离原始数:不论是数据的异常还是数据的敏感性,使真实数据与统计数据解耦开。
分层思路
-
ODS:操作型数据(Operational Data Store),指结构与源系统基本保持一致的增量或者全量数据。作为DW数据的一个数据准备区,同时又承担基础数据记录历史变化,之所以保留原始数据和线上原始数据保持一致,方便后期数据核对需要。
-
CDM:通用数据模型,又称为数据中间层(Common Data Model),包含DWD、DWS、DIM层。
-
DWD:数据仓库明细层数据(Data Warehouse Detail)。对ODS层数据进行清洗转化,以业务过程作为建模驱动,基于每个具体的业务过程特点,构建最细粒度的明细事实表。可以结合企业的数据使用特点,基于维度建模思想,将明细事实表的某些重要属性字段做适当冗余,也即宽表化处理,构建明细宽表。
-
DWS:数据仓库汇总层数据(Data Warehouse Summary),基于指标需求,构建初步汇总事实表,一般是宽表。基于上层的应用和产品的指标需求,构建公共粒度的汇总指标表。以宽表化手段物理化模型,构建命名规范、口径一致的统计指标,为上层提供公共指标。
-
DIM:建立一致数据分析维表,可以降低数据计算口径不统一的风险,同时可以方便进行交叉探查。以维度作为建模驱动,基于每个维度的业务含义,通过添加维度属性、关联维度等定义计算逻辑,完成属性定义的过程并建立一致的数据分析维表。
-
-
ADS:面向应用的数据服务层(Application Data Service)。整合汇总成分析某一个主题域的服务数据,面向应用逻辑的数据加工。该层主要存放数据产品个性化的统计指标数据,这一层的数据直接对接数据的消费者,是产品、运营等角色可以直接感知理解的一层,大多数这一层的表都可以直接在BI上通过图表的形式直接透出。
23. Map Reduce 过程
MapReduce过程详解_SunnyRivers的博客-CSDN博客_mapreduce过程详解
MapReduce流程_loser与你的博客-CSDN博客_mapreduce过程
MapReduce的主要思想:自动将一个大的计算(程序)拆分成Map(映射)和Reduce(化简)的方式。数据被分割后通过Map函数将数据映射成不同的区块,分配给计算集群进行处理,以达到分布式运算的效果,再通过Reduce函数将结果进行汇整,从而输出开发者所需要的结果。
map每次读取split的数据(一行一行的读取)后先放在buffer缓冲区中,然后进行分区、排序(快排)、当缓冲区满了之后,会进行溢写磁盘。磁盘中会生成很多个溢写小文件,而这些小文件内部是有序的,但小文件和小文件之间是无序的,所以需要进行一次归并排序形成一个全盘有序的文件。由于一个split对应一个map,reduce端是从多个map中拉取数据,所以也需要进行归并排序为一个有序的文件,最终每个相同的key分为一组执行一次reduce方法
shuffle就是reduce从map拉取数据的过程。(说的形象一点就是:将数据重新打乱汇聚到不同节点的过程,当然相同key需要汇聚在同一个节点)
24. Spark OOM怎么解决
Spark面对OOM问题的解决方法及优化总结_拱头的博客-CSDN博客_spark.shuffle.memoryfraction
25. Spark 调优 优化
Spark性能优化:资源调优篇_铭霏的博客-CSDN博客_spark优化
26. Spark standalone 模式
Standalone:独立模式,Spark 原生的简单集群管理器,自带完整的服务,可单独部署到一个集群中,无需依赖任何其他资源管理系统,使用 Standalone 可以很方便地搭建一个集群;
Standalone 模式运行机制
Standalone 集群有 2 个重要组成部分,分别是:
1) Master(RM):是一个进程,主要负责资源的调度和分配,并进行集群的监控等职责;
2) Worker(NM):是一个进程,一个 Worker 运行在集群中的一台服务器上,主要负责两个
职责,一个是用自己的内存存储 RDD 的某个或某些 partition;另一个是启动其他进程 和线程(Executor),对 RDD 上的 partition 进行并行的处理和计算。
在 Standalone Cluster 模式下,任务提交后,Master 会找到一个 Worker 启动 Driver。 Driver 启动后向 Master 注册应用程序,Master 根据 submit 脚本的资源需求找到内部资源至 少可以启动一个 Executor 的所有 Worker,然后在这些 Worker 之间分配 Executor,Worker 上 的 Executor 启动后会向 Driver 反向注册,所有的 Executor 注册完成后,Driver 开始执行 main 函数,之后执行到 Action 算子时,开始划分 Stage,每个 Stage 生成对应的 taskSet,之后将Task 分发到各个 Executor 上执行。
在 Standalone Client 模式下,Driver 在任务提交的本地机器上运行。Driver 启动后向 Master 注册应用程序,Master 根据 submit 脚本的资源需求找到内部资源至少可以启动一个 Executor 的所有 Worker,然后在这些 Worker 之间分配 Executor,Worker 上的 Executor 启动 后会向 Driver 反向注册,所有的 Executor 注册完成后,Driver 开始执行 main 函数,之后执 行到 Action 算子时,开始划分 Stage,每个 Stage 生成对应的 TaskSet,之后将 Task 分发到 各个 Executor 上执行。
27. parquet存储格式
parquet列式存储格式_sun897827804的博客-CSDN博客_parquet存储格式
28. 数据湖,数据仓库
29. 解析json
from pyspark.sql.types import StructType, StringType, LongType, ArrayType
# 构造schema类型
schema = (
StructType()
.add("index", LongType())
.add("kind", StringType())
.add("content_id", StringType())
.add("apps", ArrayType(StringType()))
.add("name", StringType())
)
# from_json 解析app_detail列(string column in json format)
df = df_detail.withColumn(
"app_detail_dict", F.from_json("app_detail", schema)
)
col_list = schema.fieldNames()
# 获取每一列的值 gets a field by name in a StructType
for col in col_list:
df = df.withColumn(col, F.col("app_detail_dict").getField(col))
df = (
df.select(
F.posexplode(F.col("apps")), //把一行按list展开成多行(带position值)
# F.explode(F.col("apps")), //把一行按list展开成多行
"index",
"kind",
"content_id",
"name",
)
.withColumn("index_of_app", F.col("pos") + 1)
.withColumnRenamed("col", "app_id")
)