Spark知识点概要

Spark知识点

一、基本特性

1、spark与MapReduce的不同

① 计算中间结果:mapreduce是基于磁盘维护, 磁盘IO及序列化代价大;而 spark是基于内存的维护 ,基于DAG计算模型,会减少Shaffer过程即磁盘IO减少。

②运行方式式:spark是多线程运行任务,mapreduce是多进程运行任务。进程的启动和关闭和会耗费一定的时间。

③运行模式:mapreduce一般都是on yarn模式;spark可以local部署、standalone 部署以及为on yarn模式

④ 用途:MR只能做离线计算,spark既可以做离线计算,有可以做实时计算,机器学习等

2、spark集群安装部署

  • vim spark-env.sh #配置java的环境变量 #配置zk相关信息
  • vim slaves 指定spark集群的worker节点
  • vim /etc/profile 修改spark环境变量
  • 环境变量生效 source /etc/profile
  • 启动:
    1、先启动zk ${ZK_HOME}/bin/zkServer.sh start
    2、启动spark集群 $SPARK_HOME/sbin/start-all.sh

zk作用:高可用

  • 在高可用模式下,整个spark集群就有很多个master,其中只有一个master被zk选举成活着的master,其他的多个master都处于standby,同时把整个spark集群的元数据信息通过zk中节点进行保存。
  • 如果活着的master挂掉。首先zk会感知到活着的master挂掉,开始在多个处于standby中的master进行选举,再次产生一个活着的master;这个活着的master会读取保存在zk节点中的spark集群元数据信息,恢复到上一次master的状态。

master的恢复阶段,对任务的影响?

  • 对已经运行的任务是没有任何影响,由于该任务正在运行,说明它已经拿到了计算资源,这个时候就不需要master。
  • 对即将要提交的任务是有影响,由于该任务需要有计算资源,这个时候会找活着的master去申请计算资源,由于没有一个活着的master,该任务是获取不到计算资源,也就是任务无法运行。

3、web管理界面

  • http://master主机名:8080
  • 集群的详细信息、总资源信息、已用资源信息、还剩资源信息 正在运行的任务信息、已经完成的任务信息

在这里插入图片描述

bin/spark-submit 
--class org.apache.spark.examples.SparkPi \
--master spark://node01:7077,node02:7077,node03:7077 \
--executor-memory 1G \
--total-executor-cores 2 \
examples/jars/spark-examples_2.11-2.3.3.jar \
10
  • spark集群中有很多个master,并不知道哪一个master是活着的master,即使你知道哪一个master是活着的master,它也有可能下一秒就挂掉,这里就可以把所有master都罗列出来

  • –master spark://node01:7077,node02:7077,node03:7077

  • 后期程序会轮训整个master列表,最终找到活着的master,然后向它申请计算资源,最后运行程序。

4、spark-shell使用

spark-shell --master local[2]

默认会产生一个SparkSubmit进程,sc
–master local[N] :表示本地采用N个线程计算任务

sc.textFile("file:///home/words.txt")
.flatMap(_.split(" "))
.map((_,1))
.reduceByKey(_+_).collect

读取HDFS上文件: vim spark-env.sh export HADOOP_CONF_DIR=hdoop安装位置
//实现读取hdfs上文件之后,需要把计算的结果保存到hdfs上

sc.textFile("/words.txt")
.flatMap(_.split(" "))
.map((_,1))
.reduceByKey(_+_).saveAsTextFile("/out")
import org.apache.spark.rdd.RDD
import org.apache.spark.{
   SparkConf, SparkContext}

/todo: 利用scala语言开发spark程序实现单词统计
object WordCount {
   
  def main(args: Array[String]): Unit = {
   
    //1、构建sparkConf对象 设置application名称和master地址
val sparkConf: SparkConf = new SparkConf().setAppName("WordCount").setMaster("local[2]")
    //2、构建sparkContext对象,该对象非常重要,它是所有spark程序的执行入口,它内部会构建  DAGScheduler和 TaskScheduler 对象
    val sc = new SparkContext(sparkConf)
  //设置日志输出级别
    sc.setLogLevel("warn")

    //3、读取数据文件
    val data: RDD[String] = sc.textFile("E:\\words.txt")

    //4、 切分每一行,获取所有单词
    val words: RDD[String] = data.flatMap(x=>x.split(" "))

    //5、每个单词计为1
    val wordAndOne: RDD[(String, Int)] = words.map(x => (x,1))

    //6、相同单词出现的1累加
    val result: RDD[(String, Int)] = wordAndOne.reduceByKey((x,y)=>x+y)

    //按照单词出现的次数降序排列  第二个参数默认是true表示升序,设置为false表示降序
    val sortedRDD: RDD[(String, Int)] = result.sortBy( x=> x._2,false)

    //7、收集数据打印
    val finalResult: Array[(String, Int)] = sortedRDD.collect()
    finalResult.foreach(println)
    //8、关闭sc
    sc.stop()
  }
}

打成jar包提交到集群中运行

spark-submit \
--master spark://node01:7077,node02:7077 \
--class com.kaikeba.WordCountOnSpark \
--executor-memory 1g  \
--total-executor-cores 4 \
original-spark_class01-1.0-SNAPSHOT.jar  /words.txt  /out    jar包与输入输出

spark-submit --class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode cluster \
--driver-memory 1g \
--executor-memory 1g \
--executor-cores 1 \
/kkb/install/spark/examples/jars/spark-examples_2.11-2.3.3.jar 10  10是main方法里面的

参数

  • executor-memory 小了,会把rdd一部分数据保存在内存中,一部分数据保存在磁盘;用该rdd时从内存和磁盘中获取,一定的磁盘io。需要设置的大一点,如10G/20G/30G等;
  • total-executor-cores:表示任务运行需要总的cpu核数,它决定了任务并行运行的粒度,也会设置的大一点,如30个/50个/100个;

加大计算资源它是最直接、最有效果的优化手段。在计算资源有限的情况下,可以考虑其他方面,比如说代码层面,JVM层面等

5、spark on yarn

最大的区别就是Driver端的位置不一样

  • yarn-cluster: Driver端运行在yarn集群中,与ApplicationMaster进程在一起。

  • yarn-client: Driver端运行在提交任务的客户端,与ApplicationMaster进程没关系,经常 用于进行测试

二、集群架构

1、spark集群架构

在这里插入图片描述

(1)Master:主节点,负责任务资源的分配。

(2)Worker:从节点,负责任务计算的节点。

  • ①Executor:是一个进程,它会在worker节点启动该进程(计算资源)
  • ②Task:任务是以task线程的方式运行在worker节点对应的executor进程中;

(3)ClusterManager:给程序提供计算资源的外部服务,standAlone模式整个任务的资源分配由spark集群的老大Master负责;把spark程序提交到yarn中运行,整个任务的资源分配由yarn中的老大ResourceManager负责

(4)Driver:是所有spark程序的执行入口,会执行客户端写好的main方法,它会构建一个名叫SparkContext对象 ,生成DAG,再根据算子的划分,把任务分到其他节点。

(5)Application:是一个spark的应用程序,它是包含了客户端的代码和任务运行的资源信息

  • 一个应用程序application就是提交到spark集群的一个job,会被分成很多个子任务job;
  • 其中,一个子任务job中又划分成了许多stage阶段(根据算子间产生shuffe的宽依赖划分);
  • 一 个stage中有存在很多分区 ,一个分区就是一个task,即一个stage中有很多个task;
  • 一个action操作对应一个DAG有向无环图,即一个action操作就是一个job;

2、调度分配

Spark中的调度模式:FIFO(先进先出)、FAIR(公平调度)

任务的分配资源worker策略:尽量打散、尽量集中
尽量打散:一个Application尽可能多的分配到不同的节点,发挥数据的本地性,提升执行效率
尽量集中:尽量分配到尽可能少的节点

3、运行模式

在这里插入图片描述

(1) local 本地模式

该模式主要用作测试用,一般编写的 spark 程序,将 master 设置为 local 或者local[n],以本地模式运行,所有的代码都在一个 Jvm 里面。

(2) Standalone 模式

该模式由 Spark 自带的集群管理模式,不依赖外部的资源管理器,由 Master 负责资源的分配管理,Worker 负责运行 Executor ,具体的运行过程可参考之前介绍 Spark 运行模式的篇章。

(4) yarn 模式
该模式由 yarn 负责管理整个集群资源,不再有 Master 和 Worker,根据 yarn-client 和 yarn-cluster 的不同。

  • yarn-client 中 driver运行在本地客户端,负责调度application,会与yarn集群产生大量的网络通信,但本地可以看见日志。

  • yarn-cluster 中 driver运行在yarn集群中,看不见日志。

(5) Mesos 模式

和 yarn 一样,Mesos 中,Spark 的资源管理从 Standalone 的 Master 转移到 Mesos Manager
中。

4、运行流程

在这里插入图片描述

spark集群模式,

  • 先开始资源准备:

    • 1)diver 拿到代码包,先到master那去,注册和申请计算资源;
    • 2)master知道后,就通知woker启动好executor进程开始准备一下;
    • 3)woker准备好进程后,就通知Driver自己好了,发送注册并且申请task请求;
  • 接下来,diver就运行main方法,分任务,运行程序;

    • 1)diver 先构建SparkContext对象,在SparkContext对象内部依次构建DAGScheduler和TaskScheduler;
    • 2)diver再根据代码rdd算子的操作顺序,生成DAG有向无环图;
    • 3)DAGScheduler拿到DAG后,按照宽依赖进行stage划分,每一个stage内部有很多可以并行运行的task,最后封装在一个一个的taskSet集合中,并把taskSet发送给TaskScheduler;
    • 4)TaskScheduler拿到taskSet集合后,依次遍历取出每一个task,提交task到worker节点上的executor进程中运行
  • 最后,程序运行完,diver通知Master注销,Master通知Worker关闭executor进程 ;

5、SparkContext对象内部

1.创建SparkEnv,里面有一个很重要的对象ActorSystem。

  • 在SparkContext中创建了两个Actor,
  • 一个是DriverActor,这里主要用于Driver和Executor之间的通信;
  • 还有一个是ClientActor,主要用于Driver和Master之间的通信。

2.创建TaskScheduler,这里是根据提交的集群来创建相应的TaskScheduler

  • 对于TaskScheduler,主要的任务调度模式有FIFO和FAIR
  • 调用taskScheduler.start()方法启动,进行资源调度,有两种资源分配方法,一种是尽量打散;一种是尽量集中

3.创建DAGScheduler,用于Stage的划分

  • Driver向Master注册,发送了一些信息,其中一个重要的类是CoarseGrainedExecutorBackend,这个类以后用于创建Executor进程。

三、计算资源

1、RDD概念

RDD(Resilient Distributed Dataset)叫做弹性 分布式 数据集,是Spark中最基本的数据抽象,它代表一个不可变、可分区、里面的元素可并行计算的集合.

  • Resilient: 表示弹性,rdd的数据是可以保存在内存或者是磁盘中.
  • Distributed:它内部的元素进行了分布式存储,方便于后期进行分布式计算.
  • Dataset: 就是一个集合,存储很多数据.

五大属性:

  • 1)A list of partitions:一个rdd有很多分区,每一个分区内部是包含了该rdd的部分数据
  • 2)A function for computing each split:每个分区都会实现 计算函数
  • 3)A list of dependencies on other RDDs:一个rdd会依赖于其他多个rdd
  • 4)Optionally, a Partitioner for key-value RDDs :kv数据的分区函数基于哈希,非kv是None
  • 5)Optionally, a list of preferred locations to compute each split on:有分区数据的节点会优先开启计算任务,数据的本地性。

RDD自定义分区
RDD数据进行分区时,默认使用的是HashPartitioner:对key进行哈希,然后对分区总数取模,

实现自定义partitioner大致分为3个步骤

  • 继承org.apache.spark.Partitioner
  • 重写numPartitions方法
  • 重写getPartition方法
 //5、对应上面的rdd数据进行自定义分区
val result: RDD[(String, Int)] = wordLengthRDD.partitionBy(new MyPartitioner(3))

2、RDD的创建

1、scala集合sc.parallelize

val rdd1=sc.parallelize(List(1,2,3,4,5))
val rdd2=sc.parallelize(Array("hadoop","hive","spark"))
val rdd3=sc.makeRDD(List(1,2,3,4))

2、加载外部的数据源sc.textFile

val rdd1=sc.textFile("/words.txt")

3、已存在rdd转换成一个新的

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值