Spark3.x——入门基础(相关知识理解篇)

本文详细介绍了Spark 3.x的运行环境配置,包括Local、StandAlone和Yarn模式,重点讲解了Spark Core、并行度与分区,以及如何配置历史服务和实现高可用。核心编程部分覆盖了RDD、并行计算和关键数据结构如RDD、累加器和广播变量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spark3.X

需要scala2.12,基于内存的快速、通用、可扩展的大数据分析计算引擎

14年成为Apache顶级项目

采用内存的计算策略,两次MR中间结果不会落盘而是在内存中

一次性的数据计算:各类的框架在处理数据的时候,会从存储的设备中读取数据,进行逻辑操作,然后将处理的结果重新存储到某种介质中

spark是有其生态的存在,包含:core、sql、streaming、MLlib、GraphX

Spark Core

运行环境

模式说明
Local本地模式,idea内并不是本地环境,而是spark-shell模式
StandLone独立部署模式,需修改slave、env文件
Yarnyarn模式,分为client和cluster
举例:将spark3.x的tar包上传linux,解压进入bin目录

1 运行spark-shell(本地模式),进行简单的wc
sc.textFile("/disk3/spark-3.0.0-bin-hadoop3.2/data/word.txt").flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).collect

2 用spark-submit方式
bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master local[2] \
./examples/jars/spark-examples_2.12-3.0.0.jar \
10

3 用standlone方式
bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://localhost:7077 \
./examples/jars/spark-examples_2.12-3.0.0.jar \
10
spark-submit相关参数解释举例
–class程序入口,包含主函数的类
–master运行的环境local[*]、spark://localhost:7077、Yarn
–executor-memory 2G每个executor可用内存为2G
–total-executor-cores 2所有executor可用cpu核数为2个
application-jarjar包(带位置),hdfs(hdfs:// )、本地文件(file:// )
application-arguments需要传入的参数

历史服务

很显然在运行任务结束后,4040也页面就无法访问到,所以需要配置历史服务器

# 注意:需要先启动 hadoop 集群,HDFS 上的 directory 目录需要提前存在。
# 修改spark-default.conf
spark.eventLog.enabled true
spark.eventLog.dir hdfs://xxx1:8020/directory

# 修改spark-env.sh文件
export SPARK_HISTORY_OPTS="
-Dspark.history.ui.port=18080 #WEB UI 访问的端口号为 18080
-Dspark.history.fs.logDirectory=hdfs://xxx1:8020/directory #指定历史服务器日志存储路径
-Dspark.history.retainedApplications=30" #指定保存 Application 历史记录的个数,如果超过这个值,旧的应用程序信息将被删除,这个是内存中的应用数,而不是页面上显示的应用数

配置高可用

采用zookeeper

# 关闭spark集群

# 启动zk

# 修改spark-env文件
注释如下内容:
#SPARK_MASTER_HOST=xxx1
#SPARK_MASTER_PORT=7077
添加如下内容:
#Master 监控页面默认访问端口为 8080,但是可能会和 Zookeeper 冲突,所以改成 8989,也可以自定义,访问 UI 监控页面时请注意
SPARK_MASTER_WEBUI_PORT=8989
export SPARK_DAEMON_JAVA_OPTS="
-Dspark.deploy.recoveryMode=ZOOKEEPER 
-Dspark.deploy.zookeeper.url=xxx1,xxx2,xxx3
-Dspark.deploy.zookeeper.dir=/spark"

# 分发集群,启动spark集群

# 提交任务,需要改变master
bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master spark://xxx1:7077,xxx2:7077 \
./examples/jars/spark-examples_2.12-3.0.0.jar \
10

Yarn模式

# 修改spark-env.sh文件
export JAVA_HOME=xxxxxx
YARN_CONF_DIR=xxxx/etc/hadoop

# spark目录内提交
bin/spark-submit \
--class org.apache.spark.examples.SparkPi \
--master yarn \
--deploy-mode client \
./examples/jars/spark-examples_2.12-3.0.0.jar \
10

运行架构

计算端

driver:并没有实际的名词叫做driver,而他是作为一种驱动类存在,驱使着整个应用运行的程序

executor:是集群worker中的一个jvm进程,具体运行具体的任务Task,彼此之前相互独立,生命周期只局限于整个应用的运行,即使有executor节点发生故障,spark应用也会继续进行,会将出错节点任务调度到其他executor节点上;作为执行器,它负责将运行结果返回给driver,它自身包含块管理器(BlockManager)为用户程序中需要缓存的rdd进行内存支持,所以rdd是直接缓存在executor进程内,因而可充分利用缓存数据计算

资源端

当我们运行standlone模式的时候会出现两个进程master和worker,master负责资源的调度和分配,并监控集群,而work就是由master分配资源对数据进行并行的处理和计算

如果单纯让资源和计算直接交互不就使得耦合性很高,所以采用了AM(ApplicationMaster),从而整体的效果计算计算端—>AM—>资源端

核心概念

硬件资源配置

名词解释
–num-executorsexecutor的数目
–executor-memory每个executor的内存大小
–executor-cores每个executor的cpu核数

并行度

Parallelism:多任务并行操作,分布式计算采用的就是并行

DAG

有向无环图:并不是真正的存在此图形,而是spark程序直接映射成数据流的高级抽象模型,更加易于理解

核心编程

相关数据结构

名词解释
RDD弹性分布式数据集
累加器共享写变量
广播变量共享读变量

RDD可以形象理解成是一个计算单元,就是要计算的每个步骤中的其中一个小步骤,我们可以拿word count举例

# 1 进入textfile内
  def textFile(
  ...
  {
    ...
    hadoopFile(path,classOf[TextInputFormat],classOf[LongWritable], classOf[Text],minPartitions).map(pair =>pair._2.toString).setName(path)
  }
)
  
# 进入hadoopFile内
  def hadoopFile[K, V]{
  ...
    new HadoopRDD(
      this,
      confBroadcast,
      Some(setInputPathsFunc),
      inputFormatClass,
      keyClass,
      valueClass,
      minPartitions).setName(path)
  }
  
# 发现HadoopRDD

# 2 进入flatMap内
  def flatMap {
    ...
    new MapPartitionsRDD[U, T](this, (_, _, iter) => iter.flatMap(cleanF))
  }
  
# 发现MapPartitionsRDD
......
......

每一个计算的方法都是由RDD组成,RDD数据处理的方式类似于java IO操作,装饰者模式,在io操作中不管是字符流还是字节流都是缓冲流存在,但是在rdd内没有缓冲这一操作,都是流式处理,中间不存储数据

RDD

特点

弹性的、不可变的、可分区的、元素可并行计算的

弹性

存储的弹性(磁盘、内存):内存不够需要落盘

容错:数据丢失自动恢复,每一个步骤的计算都会记录位置

计算:计算出错,重试的机制

分片:可以根据需要重新分区

分布式

数据集:RDD只是封装了计算的逻辑,并不保存数据

数据抽象:RDD是一个抽象类,需要子类具体实现

不可变:RDD封装了计算逻辑,不可改变,要想改变结构只能通过其他RDD改变(其他计算逻辑)

可分区、分区计算

五大属性
 *  - A list of partitions
 *  - A function for computing each split
 *  - A list of dependencies on other RDDs
 *  - 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)
 
# 1 分区列表
# 2 每个分区有计算的函数
# 3 RDD之间有依赖关系
# 4 分区器:怎么分区的,按什么规则
# 5 首选位置:task发给哪一个executor去执行,移动数据不如移动计算
并行度和分区
# 可以手动指定分区数目,后面接的2就是两个分区
val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4), 2)

# 这时调用另存文件的时候,就会保存两个文件===>两个分区
rdd.saveAsTextFile("output")

# 注意:默认的并行度是按照线程数
override def defaultParallelism(): Int =  scheduler.conf.getInt("spark.default.parallelism", totalCores)

集合作为数据源:数据是怎么被分区的?

# 源码
    def positions(length: Long, numSlices: Int): Iterator[(Int, Int)] = {
      (0 until numSlices).iterator.map { i =>
        val start = ((i * length) / numSlices).toInt
        val end = (((i + 1) * length) / numSlices).toInt
        (start, end)
      }
    }
    
# 采用的上述算法 数据总数目,分区数量 进行计算位置得出具体数据对应哪一个分区

单文件作为数据源:数据是怎么被分区的?

# 默认最小分区数是2,注意这里是默认最小,分区比2小就是不一定就是2
def defaultMinPartitions: Int = math.min(defaultParallelism, 2)

# 分区规则实现:
# 其实我们可以发现,spark是用了Hadoop中mapreduce读取文件方式
# 追溯FileInputFormat,其中有getSplits方法
# 该方法内有totalSize,这里要注意文件长度包含隐藏的字符(比如换行、回车)
totalSize += file.getLen();

# 每个分区存放几个字节
long goalSize = totalSize / (numSplits == 0 ? 1 : numSplits);

# 这里提及Hadoop中读取文件1.1概念,即剩余字节数大于上一个字节数的10%,产生新分区,否则不会产生新分区
# 因为当我们有7个字节文件,默认两个分区,但最后却是3个分区,就是因为7/2=3,还剩1个字节没地方放,又1>3*0.1,所以产生新分区,综上就是3个分区

# 继续解释
# 假设某个文件内容为1234567
# 按照上面理论,三个分区,三个文件,那要怎么读取?每个分区保存的是什么数据呢?

1、spark采用hadoop读文件,那应该是按行读取
2、数据读取应该是以偏移量作为单位

注意:上面计算是每个7/2=3,每个分区3个,按照偏移量排如下,偏移量范围是左开右闭
分区 偏移量范围
0   [0,3]
1   (3,6]
2   (6,7]

虽说这样理论排列,但并非如此,因为是按行,所以在读取刚开始的时候就知道一行数据,就会把一行数据放在一个分区文件,所以最后排列方式是,第一个文件为1234567,其他两个文件为空,其实这里可以想到贪婪的算法,既要考虑偏移量范围还要考虑一行,所以一行数据所在偏移量被读后,该行其他字节就会连着被读的偏移量

多文件作为数据源,分区以文件为单位进行分区

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

友培

数据皆开源!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值