【SPARK】知识点全讲解

Spark环境部署

前置条件:完成Scala环境部署
可以参考我的博客:Scala环境部署和简单介绍

然后我们在vmware虚拟机上配置Scala和Spark并初步使用

Spark简介

诞生与发展

  • 诞生于加州大学伯克利分校AMP实验室,是一个基于内存的分布式计算框架

  • 发展历程:
    2009年诞生于加州大学伯克利分校AMP实验室
    2010年正式开源
    2013年6月正式成为Apache孵化项目
    2014年2月成为Apache顶级项目
    2014年5月正式发布Spark 1.0版本
    2014年10月Spark打破MapReduce保持的排序记录
    2015年发布了1.3 1.4 1.5版本
    2016年发布了1.6 2.x版本

为什么使用Spark

  • MapReduce编程模型的局限性
    繁杂
    只有Map和Reduce两个操作,复杂的逻辑需要大量的样板代码

  • MapReduce处理效率低
    Map中间结果写磁盘,Reduce写HDFS,多个Map通过HDFS交换数据
    任务调度与启动开销大
    不适合迭代处理、交互式处理和流式处理

  • Spark是类Hadoop MapReduce的通用并行框架
    Job中间输出结果可以保存在内存,不再需要读写HDFS
    比MapReduce平均快10倍以上

Spark优势

  • 速度快
    基于内存数据处理,比MR快100个数量级以上(逻辑回归算法测试)
    基于硬盘数据处理,比MR快10个数量级以上
  • 易用性
    支持Java、Scala、Python、R语言
    交互式shell方便开发测试
  • 通用性
    一栈式解决方案:批处理、交互式查询、实时流处理、图计算及机器学习
  • 随处运行
    YARN、Mesos、EC2、Kubernetes、Standalone、Local

Spark技术栈

在这里插入图片描述

  • Spark Core
    核心组件,分布式计算引擎
  • Spark SQL
    高性能的基于Hadoop的SQL解决方案
  • Spark Streaming
    可以实现高吞吐量、具备容错机制的准实时流处理系统
  • Spark GraphX
    分布式图处理框架
  • Spark MLlib
    构建在Spark上的分布式机器学习库

Spark架构设计

Spark的运行架构:
在这里插入图片描述

  • 在驱动程序中,通过SparkContext主导应用的执行
  • SparkContext可以连接不同类型的Cluster Manager(Standalone、YARN、Mesos),连接后,获得集群节点上的Executor
  • 一个Worker节点默认一个Executor,可通过SPARK_WORKER_INSTANCES调整
  • 每个应用获取自己的Executor
  • 每个Task处理一个RDD分区

Spark架构核心组件

在这里插入图片描述

Spark交互工具

  • 本机
    spark-shell --master local[*]
  • Standalone
    spark-shell --master spark://MASTERHOST:7077
  • YARN
    spark-shell --master yarn-client

Spark API

SparkContext

  • 连接Driver与Spark Cluster(Workers)
  • Spark的主入口
  • 每个JVM仅能有一个活跃的SparkContext
  • SparkContext.getOrCreate
import org.apache.spark.{
   SparkConf, SparkContext}

val conf=new SparkConf().setMaster("local[*]").setAppName("appName")
val sc=SparkContext.getOrCreate(conf)

SparkSession

  • Spark 2.0+应用程序的主入口:包含了SparkContext、SQLContext、HiveContext以及StreamingContext
  • SparkSession.getOrCreate
import org.apache.spark.sql.SparkSession
val spark = SparkSession.builder
                    .master("local[*]")
                    .appName("appName")
                    .getOrCreate()

RDD

Spark核心,主要数据抽象

DataSet

从Spark1.6开始引入的新的抽象,特定领域对象中的强类型集合,它可以使用函数或者相关操作并行地进行转换等操作

DateFrame

DataFrame是特殊的Dataset

Spark的RDD

概念

简单的解释:RDD是将数据项拆分为多个分区的集合,存储在集群的工作节点上的内存中,并执行正确的操作

复杂的解释:RDD是用于数据转换的接口;RDD指向了存储在HDFS、Cassandra、HBase等、或缓存(内存、内存+磁盘、仅磁盘等),或在故障或缓存收回时重新计算其他RDD分区中的数据

RDD是 弹性分布式数据集 (Resilient Distributed Datasets):

  • 分布式数据集
    RDD是只读的、分区记录的集合,每个分区分布在集群的不同节点上
    RDD并不存储真正的数据,只是对数据和操作的描述
  • 弹性
    RDD默认存放在内存中,当内存不足,Spark自动将RDD写入磁盘
  • 容错性
    根据数据血统,可以自动从节点失败中恢复分区

RDD与DAG

两者是Spark提供的核心抽象
DAG(有向无环图)反映了RDD之间的依赖关系

在这里插入图片描述

RDD的特性

  • 一系列的分区(分片)信息,每个任务处理一个分区
  • 每个分区上都有compute函数,计算该分区中的数据
  • RDD之间有一系列的依赖
  • 分区函数决定数据(key-value)分配至哪个分区
  • 最佳位置列表,将计算任务分派到其所在处理数据块的存储位置

RDD编程流程

在这里插入图片描述

创建RDD

第一种:使用集合创建RDD

val rdd=sc.parallelize(List(1,2,3,4,5,6))
rdd.count
rdd.partitions.size
val rdd=sc.parallelize(List(1,2,3,4,5,6),5)
rdd.partitions.size
val rdd=sc.makeRDD(List(1,2,3,4,5,6))

第二种:通过加载文件产生RDD

val distFile=sc.textFile("file:///home/hadoop/data/hello.txt")
distFile.count
val distHDFSFile=sc.textFile("hdfs://hadoop000:8020/hello.txt")

支持目录、压缩文件以及通配符

sc.textFile("/my/directory")
sc.textFile("/my/directory/*.txt")
sc.textFile("/my/directory/*.gz")

第三种:其他创建RDD的方法

  • SparkContext.wholeTextFiles():可以针对一个目录中的大量小文件返回<filename,fileContent>作为PairRDD
  • 普通RDD:org.apache.spark.rdd.RDD[data_type]
  • PairRDD:org.apache.spark.rdd.RDD[(key_type,value_type)]
  • SparkContext.sequenceFileK,V
    Hadoop SequenceFile的读写支持
  • SparkContext.hadoopRDD()、newAPIHadoopRDD()
    从Hadoop接口API创建
  • SparkContext.objectFile()
    RDD.saveAsObjectFile()的逆操作

RDD分区

分区是RDD被拆分并发送到节点的不同块之一

  • 拥有的分区越多,得到的并行性就越强
  • 每个分区都是被分发到不同Worker Node的候选者
  • 每个分区对应一个Task

在这里插入图片描述

RDD的操作

分为lazy与non-lazy两种:

  • Transformation(lazy):也称转换操作、转换算子
  • Actions(non-lazy):立即执行,也称动作操作、动作算子

RDD转换算子

对于转换操作,RDD的所有转换都不会直接计算结果:

  • 仅记录作用于RDD上的操作
  • 当遇到动作算子(Action)时才会进行真正计算

在这里插入图片描述

RDD常用算子转换

spark常用RDD算子汇总(java和scala版本)

Spark分布式计算原理

RDD的依赖关系

  • Lineage:血统、遗传
    RDD最重要的特性之一,保存了RDD的依赖关系
    RDD实现了基于Lineage的容错机制
  • 依赖关系
    宽依赖
    窄依赖

在这里插入图片描述

  • 宽依赖对比窄依赖
    宽依赖对应shuffle操作,需要在运行时将同一个父RDD的分区传入到不同的子RDD分区中,不同的分区可能位于不同的节点,就可能涉及多个节点间数据传输
    当RDD分区丢失时,Spark会对数据进行重新计算,对于窄依赖只需重新计算一次子RDD的父RDD分区

在这里插入图片描述

结论:相比于宽依赖,窄依赖对优化更有利

DAG工作原理

  • 根据RDD之间的依赖关系,形成一个DAG(有向无环图)
  • DAGScheduler将DAG划分为多个Stage
    划分依据:是否发生宽依赖(Shuffle)
    划分规则:从后往前,遇到宽依赖切割为新的Stage
    每个Stage由一组并行的Task组成

在这里插入图片描述

为什么需要划分Stage?
数据本地化
移动计算,而不是移动数据
保证一个Stage内不会发生数据移动

最佳实践:
尽量避免Shuffle
提前部分聚合减少数据移动

在这里插入图片描述

Spark Shuffle过程

  • 在分区之间重新分配数据
    父RDD中同一分区中的数据按照算子要求重新进入子RDD的不同分区中
    中间结果写入磁盘
    由子RDD拉取数据,而不是由父RDD推送
    默认情况下,Shuffle不会改变分区数量

在这里插入图片描述

RDD优化

RDD持久化
RDD共享变量
RDD分区设计
数据倾斜

RDD持久化

  • RDD缓存机制:缓存数据至内存/磁盘,可大幅度提升Spark应用性能
    cache=persist(MEMORY)
    persist
  • 缓存策略StorageLevel
    MEMORY_ONLY(默认)
    MEMORY_AND_DISK
    DISK_ONLY
val u1 = sc.textFile("file:///root/data/users.txt").cache
u1.collect//删除users.txt,再试试
u1.unpersist()

缓存应用场景:
从文件加载数据之后,因为重新获取文件成本较高
经过较多的算子变换之后,重新计算成本较高
单个非常消耗资源的算子之后

使用注意事项:
cache()或persist()后不能再有其他算子
cache()或persist()遇到Action算子完成后才生效

检查点

类似于快照

sc.setCheckpointDir("hdfs:/checkpoint0918")
val rdd=sc.parallelize(List(('a',1), ('a',2), ('b',3), ('c',4)))
rdd.checkpoint
rdd.collect //生成快照
rdd.isCheckpointed
rdd.getCheckpointFile

检查点与缓存的区别
检查点会删除RDD lineage,而缓存不会
SparkContext被销毁后,检查点数据不会被删除

共享变量

广播变量:允许开发者将一个只读变量(Driver端)缓存到每个节点(Executor)上,而不是每个任务传递一个副本

val broadcastVar
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值