一、使用Spark的目的
- MapReduce编程模型的局限性
* 繁杂
* 只有Map和Reduce两个操作,复杂的逻辑需要大量的样板代码
* 处理效率低:
* 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-shell:Spark自带的交互式工具
本机
- spark-shell --master local[*]
Standalone
- spark-shell --master spark://MASTERHOST:7077
YARN
- spark-shell --master yarn-client
五、Spark架构设计
- 在驱动程序中,通过SparkContext主导应用的执行
- SparkContext可以连接不同类型的Cluster Manager(Standalone、YARN、Mesos),连接后,获得集群节点上的Executor
- 一个Worker节点默认一个Executor,可通过SPARK_WORKER_INSTANCES调整
- 每个应用获取自己的Executor
- 每个Task处理一个RDD分区
spark核心组件
术语 | 说明 |
---|---|
Application | 建立在Spark上的用户程序,包括Driver代码和运行在集群哥哥节点Executor中的代码 |
Driver program | 程序驱动。Application中的main函数并创建SparkContext |
Cluster Manager | 在集群(Standalone、Mesos、YARN)上获取资源的外部服务 |
Worker Node | 集群中任何可以运行Application代码的节点 |
Executor | 某个Application运行在worker节点上的一个进程 |
Task | 被送到摸个Executor上的工作单元 |
Job | 包含多个Task组成的并行计算,往往由Spark Action触发生成,一个Application中往往会产生多个Job |
Stage | 每个Job会被拆分成多组Task,作为一个TaskSet,其名称为Stage |
Spark API
SparkContext
- 连接Driver与Spark Cluster(Workers)
- Spark的主入口
- 每个JVM仅能有一个活跃的SparkContext
- SparkContext.getOrCreate
//创建一个spark context对象
val conf: SparkConf = new SparkConf().setMaster("local[6]").setAppName("sparkTest")
val sc: SparkContext = SparkContext.getOrCreate(conf)
SparkSession
- Spark 2.0+应用程序的主入口:包含了SparkContext、SQLContext、HiveContext以及StreamingContext
- SparkSession.getOrCreate
//创建spark session对象,local[2]代表两个线程
val spark: SparkSession = SparkSession.builder()
.master("local[2]")
.appName("sparkSessionTest")
.getOrCreate()
RDD
- Spark核心,主要数据抽象
RDD概念
RDD简单地说就是将数据项拆分为多个分区的集合,存储在集群的工作节点上的内存中,并执行正确的操作。进一步解释就是RDD是用于数据转换的接口,RDD指向了存储在HDFS、Cassandra、HBase等、或缓存(内存、内存+磁盘、仅磁盘等),或者在故障或缓存回收时重新计算其他RDD分区中的数据。
RDD是弹性分布式数据集
- 分布式数据集
- RDD是只读的、分区记录的集合,每个分区分布在集群的不同节点上
- RDD并不存储真正的数据,只是对数据的操作描述
- 弹性
- RDD默认存放在内存中,当内存不足,Spark自动将RDD写入磁盘
- 容错性
- 根据数据血统,可以自动从节点失败中恢复分区。
RDD与DAG
- 两者都是Spark提供的核心抽象
RDD特性
- 一系列的分区(分片)信息,每个任务处理一个分区
- 每个分区上都有compute函数,计算该分区中的数据
- RDD之间有一系列的依赖
- 分区函数决定数据(key-value)分配至哪个分区
- 最佳位置列表,将计算任务分配到器所在处理数据块的存储位置
RDD创建
- 使用集合创建RDD
val rdd=sc.parallelize(List(1,2,3,4,5,6))
- 通过加载文件产生RDD
val distFile=sc.textFile("file:///home/hadoop/data/hello.txt")
- 其他创建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.sequenceFile[K,V]()
Hadoop SequenceFile的读写支持
SparkContext.hadoopRDD()、newAPIHadoopRDD()
从Hadoop接口API创建
SparkContext.objectFile()
RDD.saveAsObjectFile()的逆操作
Dataset
- 从Spark1.6开始引入的新的抽象,特定领域对象中的强类型集合。他可以使用函数或者相关操作并行地进行转换操作
DataFrame
- DataFrame是特殊的Dataset