spark、spark-core、RDD 总结
1. spark 概念
1.1 什么是spark
- 基于内存的分布式计算框架
- 只负责算 不负责存
- spark 在离线计算 功能上 类似于mapreduce的作用
1.2 为什么用spark
-
MapReduce的缺点
- 运行速度慢 (没有充分利用内存)
- 接口比较简单,仅支持Map Reduce
- 功能比较单一 只能做离线计算
- 不适合迭代计算(如机器学习、图计算等等),交互式处理(数据挖掘)
- 不适合流式处理(点击日志分析)
-
需要一种灵活的框架可同时进行批处理、流式计算、交互式计算
- 内存计算引擎,提供cache机制来支持需要反复迭代计算或者多次数据共享,减少数据读取的IO开销
- DAG引擎,减少多次计算之间中间结果写到HDFS的开销
- 使用多线程模型来减少task启动开销,shuffle过程中避免不必要的sort操作以及减少磁盘IO
- spark的缺点是:吃内存,不太稳定
-
Spark优势
- 速度快(比mapreduce在内存中快100倍,在磁盘中快10倍)spark中的job中间结果可以不落地,可以存放在内存中。 mapreduce中map和reduce任务都是以进程的方式运行着,而spark中的job是以线程方式运行在进程中。
- 易用性(可以通过java/scala/python/R开发spark应用程序)
- 通用性(可以使用spark sql/spark streaming/mlib/Graphx)
- 兼容性(spark程序可以运行在standalone/yarn/mesos)
2. RDD 的概念
RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变、可分区、里面的元素可并行计算的集合.
-
Dataset:一个数据集,简单的理解为集合,用于存放数据的
-
Distributed:它的数据是分布式存储,并且可以做分布式的计算
-
Resilient:弹性的
- 它表示的是数据可以保存在磁盘,也可以保存在内存中
- 数据分布式也是弹性的
- 弹性:并不是指他可以动态扩展,而是容错机制。
- RDD会在多个节点上存储,就和hdfs的分布式道理是一样的。hdfs文件被切分为多个block存储在各个节点上,而RDD是被切分为多个partition。不同的partition可能在不同的节点上
- spark读取hdfs的场景下,spark把hdfs的block读到内存就会抽象为spark的partition。
- spark计算结束,一般会把数据做持久化到hive,hbase,hdfs等等。我们就拿hdfs举例,将RDD持久化到hdfs上,RDD的每个partition就会存成一个文件,如果文件小于128M,就可以理解为一个partition对应hdfs的一个block。反之,如果大于128M,就会被且分为多个block,这样,一个partition就会对应多个block。
-
所有spark中对数据的操作最终都会转换成RDD的操作
- spark sql
- spark streaming
- spark ml 、spark mllib
-
RDD是不可变的
- 父RDD 生成一个子 RDD 父RDD的状态不会变化
- 从容错的角度去做这样的设计
2.1 RDD的创建
-
创建RDD之前先要有spark context
conf = SparkConf().setAppName(appName).setMaster(master) sc = SparkContext(conf=conf)
-
通过内存中的数据创建RDD
- data = [1, 2, 3, 4, 5]
distData = sc.parallelize(data)
- data = [1, 2, 3, 4, 5]
-
创建RDD时可以指定 partition的数量(RDD会分成几份)一个partition会对应一个task,根据CPU的内核数来指定partition (1核对应2~4个partition)
-
从文件创建RDD 可以是HDFS支持的任何一种存储介质
- 可以从 hdfs、 数据库(mysql) 、本地文件系统、 hbase 这些地方加载数据创建RDD
- rdd = sc.textFile(‘file:///root/tmp/test.txt’)
2.2 RDD的三类算子
-
transformation
-
所有的transformation 都是延迟执行的,只要不调用action 不会执行,只是记录过程
-
transformation 这一类算子返回值还是 rdd
-
rdd.transformation 还会得到新的rdd
-
map(func) 将func函数作用到数据集的每一个元素上,生成一个新的RDD返回
-
filter(func) 选出所有func返回值为true的元素,生成一个新的RDD返回
-
flatMap(func) 会先执行map的操作,再将所有对象合并为一个对象
-
union() 取并集
-
intersection() 交集
-
groupByKey() 以元组中的第0个元素作为key,进行分组,返回一个新的RDD 结果中 value是一个Iterable
-
reducebykey(func) 将key相同的键值对,按照Function进行计算
-
sortbykey(ascending=True, numPartitions=None, keyfunc=<function RDD.>)Sorts this RDD, which is assumed to consist of (key, value) pairs.按照关键词排序,排完后函数操作
-
-
action
- 会触发之前的rdd所有的transformation
- 获取最终的结果
- collect 所有的结果都会加载到内存中
- reduce将RDD中元素两两传递给输入函数,同时产生一个新的值,新产生的值与RDD中下一个元素再被传递给输入函数直到最后只有一个值为止。
- fitst 第一个
- take(num) 前n个
- count()
-
persist
- 数据存储,可以存到内存,也可以是磁盘
3. spark-core 实战
详情见spark-core 实战 通过spark实现ip地址查询
4. spark集群架构
-
Application
用户自己写的Spark应用程序,批处理作业的集合。Application的main方法为应用程序的入口,用户通过Spark的API,定义了RDD和对RDD的操作。
-
Client:客户端进程,负责提交作业到Master。
-
Master(类比与ResourceManager)
- Standalone模式中主控节点,负责接收Client提交的作业,管理Worker,并命令Worker启动Driver和Executor。
-
Worker(类比于NodeManager)
- Standalone模式中slave节点上的守护进程,负责管理本节点的资源,定期向Master汇报心跳,接收Master的命令,启动Driver和Executor。
-
Driver(类比于ApplicationMaster)
- 一个Spark作业运行时包括一个Driver进程,也是作业的主进程,负责作业的解析、生成Stage并调度Task到Executor上。包括DAGScheduler,TaskScheduler。
- DAGScheduler: 实现将Spark作业分解成一到多个Stage,每个Stage根据RDD的Partition个数决定Task的个数,然后生成相应的Task set放到TaskScheduler中。
- TaskScheduler:实现Task分配到Executor上执行。
- Stage:一个Spark作业一般包含一到多个Stage。
- Task:一个Stage包含一到多个Task,通过多个Task实现并行运行的功能。
-
Executor(类比于Container):即真正执行作业的地方,一个集群一般包含多个Executor,每个Executor接收Driver的命令Launch Task,一个Executor可以执行一到多个Task。