1.Spark特点:
Spark高效计算的原因是基于内存的计算(很快写,很快运行),高效DAG执行引擎,Spark比MapReduce快100倍,拥有Java,Scale,Python等API,且支持多种平台(Hadoop,Cloud,Mesos等),能够在一个应用中支持Spark Stream(流计算),Spark SQL(自查询),Spark Core(批处理),GraphX,MLLib等
MapReduce慢的原因是存在I/O开销(输入和输出存在大量读写HDFS操作)和大量的Sort操作
Spark快的原因:
2.Spark生态圈(伯克利数据分析栈)
3.Spark工作模式:
Local:本地测试
Standalone:集群(有自己的资源管理器)
Mesos:资源管理器选择Mesos
Yarn:资源管理器选择Yarn
4.RDD简介
RDD(Resilient Distributed Dataset)弹性分布式数据集,RDD是可分区的元素集合能够并行处理,基本操作包括map,filter,persist(持久化),其他操作隐式封装到其他类中
RDD五大特性:
1)RDD是一组分片(partition,位于某个节点中)的集合,HDFS中的每个Block对应于内存中的一个Partition(加载内存 )
读文件->HDFS Block->Partition(RDD)
2)一个partition对应一个split,算子即Function,每个split都会执行Function算子(并行计算)
3)算子RDD之间有依赖性,RDD存在瞬时状态
4)允许重新分区(基于key的哈希),以提升并行计算性能(key-value RDD)
5)由于HDFS存在副本,当读HDFS文件时,可选择最优的位置Block加载内存形成RDD进行计算
5.Spark运行时
1)驱动程序发布Job Tasks到每个Worker
2)Worker加载数据至本地内存
3)执行任务
4)返回结果
--deploy-mode client:Client和Driver在同一个节点(可见结果)
--deploy-mode cluster:Driver放在了Worker(不可见结果),但可以在Driver日志中可见
算子包括延迟执行(Transformation算子)和立即执行(Action 算子),在应用程序中Driver会审视代码,只要碰到立即执行算子则封装成一个Job提交执行。
总而言之,Application中Job的划分以Action算子为依据,old RDD->new RDD,则old RDD释放,如果后面Job需要使用old RDD,则需要对old RDD.persist持久化到内存
6. 持久化策略和缓存优化
StorageLevel.NONE:无策略
StorageLevel.DISK_ONLY:序列化到磁盘
StorageLevel.MEMORY_ONLY:不序列化到内存(默认)
StorageLevel.MEMORY_ONLY_SER:序列化到内存(类似压缩)
StorageLevel.MEMORYp_AND_DISK:尽量不序列化到内存,不够再写入磁盘
假设RDD依赖关系是RDD0->RDD1->RDD2,由于1G的RDD1采用ONLY_MEMORY持久化策略,而内存只有512MB,因此内存中只会缓存RDD1的前512MB的数据并赋予RDD2进行计算,而RDD1的后512MB的数据不存在内存,因此会去找其依赖RDD0,如果RDD0也没有做持久化,则会重新读取磁盘文件(HDFS)然后依次执行算子得到RDD0->RDD1->RDD2(后512MB);如果RDD1持久化策略是MOMERY_AND_DISK,则RDD1的数据内存够用则保存在内存,否则剩余的数据保存在磁盘(如果中间结果重新计算开销较大则选用该策略)
持久化策略选择:
Job的调度策略
1)FIFO(Job顺序执行)
2)Fair(Job并发执行)
为了保证数据本地行,尽量使得DataNode和Spark节点相同
7.Zookeeper实现Spark HA
目的:解决Master单节点故障问题,允许多个Master存在,Leader只允许一个,其他Master状态为Standby,当Leader故障之后,Zookeeper会重新选择Standby Master中的一个作为新的Master,耗时可能需要1到2分钟
实现流程:
1)修改spark-env.sh,添加
-Dspark.deploy.recoveryMode=ZOOKEEPER 指定spark HA的恢复模式是ZOOKEEPER(自动热储备),因为还可以指定为本地模式LOCAL(手动冷储备)
2)所有节点启动Zookeeper,bin/zKServer start,一个节点时Leader,其他节点为Follower
3)启动多个Master,sbin/start-master.sh,则有个节点Master Status为Active,另外的节点StandBy
4)当Active Master崩溃时,Zookeeper会进行选举从StandBy节点中选择新的Master节点
8.YARN模式启动配置:
1)配置spark-env.sh中的YARN_CONF_DIR
2)启动Hadoop集群
3)启动Spark
4)运行bin/spark-submit --class org.apache.spark.examples.SparkPi --master yarn-client example/jars/spark-examples_2.11-2.1.1.jar
YARN模式执行流程:
1)上传jar和数据文件到HDFS上
2)由于YARN ResourceManager已经分配了Container在各个节点上,当YARN 通过SAPRK_HOME找到Spark集群会解析Spark应用程序得到Driver
3)Driver向ResourceManager申请资源,ResourceManager告诉Driver资源在哪个NodeManager,由NodeManager启动Container
4)Driver则会分配任务到各个NodeManager,在Container环境下执行
9.常用算子解析
Transfomation算子:延迟执行,RDD1->RDD2
Action算子:立即执行,RDD->Result
最后的RDD一般需要执行Save算子,把结果存储在一个位置
10.RDD容错:
1)缓存中间RDD
2)Checkpoint(Lineage血统过长,即中间RDD过多)
RDD查看Lineage:rdd.toDebugString
窄依赖:父RDD的partition->子RDD的一个partition
宽依赖:父RDD的partition->子RDD的多个partition
宽依赖和窄依赖区分通过算子来,Action算子提交Job后会形成一个DAG
*DAG划分依据,碰到宽依赖就分一个Stage
一个Application->一个Driver->多个Job(Action算子)->多个Stage(宽依赖)->多个Task(Stage,一个Task形成一条pipeline)->多个算子
11.Spark术语解释
1)Application:基于Spark的应用程序,对应一个Driver(DAGSchedule和TaskSchedule)和多个Executor(运行Task并将数据存在内存或者磁盘)
2)Worker:运行应用程序代码的节点
3)Task:被分到每个Executor的最小执行单元
1)Driver中SparkContext首先向Master/ResourceManager申请资源
2)Master/ResourceManager返回可用资源的节点列表(空闲节点)
3)SparkContext请求Worker Node资源
4)Worker Node与Cluster Manager交互认证,返回SparkContext允许执行任务
5)SparkContext把任务分配给Work Node
6)Executor执行相应的任务并把结果返回给SparkContext,当所有任务执行(Job执行完成)完成后会告诉SparkContext
7)SparkContext告诉ClusterManager清理资源
源码分析:
Action算子均有submitJob(),由DAG Schedule从finalStage->最前面的stage(倒序),将stage分解成多个Task,加入到TaskSet并赋予Task Schedule,由Task Schedule根据申请的资源列表将Task分配到Block所在的节点(最优位置)执行
12.Application提交后的执行流程:
1.用户提交IDE编写好的Application应用程序,并打包成Jar上传到Spark集群
2.ShellSpark submit提交Application应用程序
Spark-submit --class 主类 --master master模式 --deploy-mode 部署模式(client or cluster)
3.通过反射方式创建一个DriverActor进程(即Driver)
4.SparkContext执行流程:
1)初始化一些对象,比如SparkConf,会赋予缺省值
2)检查是否设置了Master和AppName,若无则会报异常
3)加载SparkEnv设置参数,比如shuffle的方式(hash,sort默认,tunsten_sort),内存使用方式(legency模式默认),spark_executor_memory(1GB默认)
4)SparkContext.createTaskSchedule(this,master)//会匹配master模式(local,local[*],standalone,)创建的ScheduleBackend不一样(实际与Master通信申请资源的)
5)创建DAGSchedule,并将TaskSchedule和DAGSchedule相关联
5.TaskSchedule向Master注册Application
6.Master根据Worker的资源使用情况,分配空闲Worker
7.Worker启动多个Executor进程
8.Executor启动后反向注册到TaskSchedule上
9.当所有的Executor都反向注册到TaskSchedule上之后,Driver结束SparkContext初始化,并继续执行Application
SparkConf conf=new SparkConf().setMaster(“local”).setApp(“app”);
SparkContext sc=new SparkContext(conf);//SparkContext初始化完成
10.DAGSchedule执行流程:
1)DAGSchedule会根据Action算子提交Job,即runJob(rdd,func,partitions)
2)runJob中子方法submitJob(rdd,func,partitions,callSite,resultHandler,properties)
3)submitJob()子方法nextJobId.getAndIncrement()得到JobId
4)submitJob()子方法eventProcessLoop.post(JobSubmitted(jobId,rdd,func2,partitions)),即往DAGScheduleEventProcessLoop中添加event,DAGScheduleEventProcessLoop.doOnReceive()线程不断根据event类型判断是JobSubmitted,则会dagSchedule.handleJobSubmitted(jobId,rdd,func,partitions)根据rdd(finalRDD)创建finalStage,submitStage(finalStage)提交finalStage
5)submitStage(finalStage)会不断向左递归(通过getMissingParentStages(stage)碰到宽依赖就划分新的shuffleMapStage)or ResultStage,然后调用getPreferredLocs(rd,partition)
u 查看缓存中是否有RDD
u 检查该RDD是否做过checkpoint
u rdd.preferredLcations(rdd.partitions(partition)).toList找到rdd partition的最佳位置(数据本地性),假如是HadoopRDD.getPartitions,则会通过反射创建TextInputFormat然后调用getSplits()得到Block所在节点位置即为partition的最佳位置
u 否则找同一个stage里面的前一个rdd递归找该partition的最佳位置
就可以找到每个stage的每个partition的最佳位置即每个Task的最佳位置,若为ShuffleMapStage则创建ShuffleMapTask,否则创建ResultTask
6)当找到了初始Stage则通过submitMissingTasks(stage,jobId.get),会得到初始partitions,以及判断stage类型是属于ShuffleMapStage or ResultStage从而得到tasks,创建TaskSet并打乱
11.TaskSchedule.submitTasks(new TaskSet(tasks.toArray,stage.id,stage.latestInfo.attemptId,jodId,properties))即TaskSchedule提交TaskSet里面的每一个Task到Executor
12.Executor从ThreadPool线程池中选择一个线程执行TaskRunner,然后读取partition执行Task中相应的算子
13.当所有Task执行完成则Job执行完成,当所有的Job执行完成,则用户Application执行完成
源码解析:
Spark也存在speculation机制处理慢Task,在其他节点运行相同Task,最先执行完的Task的结果作为最终结果
13.Spark基本API见spark.apache.org Programming Guide
Ø Spark算子优化:
1.Spark提高并行度:
1)资源并行度:local[5],五个线程执行
2)数据并行度:conf.set(“spark.default.parallelism”,6),RDD分成6个partition
如果数据并行度高于资源并行度,则会批量执行,一般设置数据并行度是资源并行度的2~3倍
2.filter算子优化(即后面跟一个coalesce算子):
将partition合并,减少partition数量,从而减少partition的数据倾斜现象(shuffle=true);除此之外coalesce算子也可以增加partition,以提高数据并行度(shuffle=true)
3.序列化方式(Kryo serialization:)
conf.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer").
序列化使用场景:
1)RDD持久化
2)Shuffle操作,map端处理完数据后需要序列化数据,reduce端需要反序列化数据
3)Driver与Worker交互,分发task或者返回result
14.Exceutor设置
当为yarn-client模式:
Ø SPARK_EXECUTOR_INSTANCES:默认启动2个Executor实例
Ø SPARK_EXECUTOR_CORE:每个Executor的 cpu核默认1个
Ø SPARK_EXECUTOR_MEMORY:每个Executor的内存默认1G
当在standalone模式:
Ø SPARK_WORKER_MEMORY:指定每个Worker能管理的默认内存是1G
Ø SPARK_WORKER_INSTANCES:每个节点Worker进程数
每个Stage中 RDD partition的数量决定了Task的数量,窄依赖算子操作不会影响Partition数量(Task数量),shuffle类型算子(宽依赖)由map 阶段和Reduce 阶段组成
15.Spark共享变量
1)广播变量:允许程序员保存只读变量缓存到每台机器上
使用场景:
Ø 可以给每个节点(每一个Worker共享,每一个Executor共享,每一个Task共享)一份大的输入数据集,能够使用有效的广播算法减少通信开销
Ø Spark自动广播同一个stage中不同任务需要的共同变量
2)累加器:允许将不同task运行结果累加,并可在Spark UI显示,但不能在call方法中获得,只有Driver可读
16.Spark SQL
1)特点:
Ø 无缝整合SQL
Ø 通用数据访问,Hive,JSON,JDBC
Ø Hive兼容,允许使用HiveQL,Hive UDF,Hive Table
Ø 规范连接
2)Spark架构
Spark SQL有Catalyst Optimizer和Tungsten Execution Engine,Data Frame(先创建scheme后存储属性)类似于二维表
Spark SQL性能高于Shark
工作原理:SQL/HQL(Sql解析器)->Logical Plan(catalyst分析器)->分析逻辑计划(catalyst优化器)->优化的逻辑计划(Spark Planner)->物理计划(代价模型)->Spark Plan->准备的SparkPlan->RDD
3)Spark SQL standalone模式 JDBC源
*先启动zookeeper,再启动hadoop,最后启动spark
4)Spark SQL Hive 解决分组TopN问题
Select product,revenue from (select product,revenue,row_number() over (partition by product order by revenue desc) rank from sales)tmp_sales where rank <=2
相当于先根据product进行分组,然后根据revenue进行降序,并创建新的视图tmp_sales,此时tmp_sales类似于:
Rank product revenue
1 shuji 22
2 shuji 20
3 shuji 18
1 yifu 25
2 yifu 20
3 yifu 18 ...
即row_number的效果
Spark SQL默认并行度是200
Spark SQL实现UDF(Scala版本)
Spark SQL实现UDAF(scala)
区别需要继承UserDefineAggregateFunction
17.Spark PageRank问题
18.Spark Streaming流式计算
特点:
1)拥有大量算子
2)容错
3)允许join RDD
4)微批处理(基于Spark Core),Storm是真正的流式计算(实时处理)
Spark Stream架构类似于Spark Core
DStream中包含多个RDD,DStream之间存在状态迁移
Spark Stream支持多种数据源kaflka,flume,HDFS,kinesis,Twitter等等,且支持多种输出HDFS,Databases等等,工作原理实际上是等待数据输入一段时间后封装成RDD并传送给Spark Engine进行实时计算得到Result RDD
一个文件只会被Spark Streaming计算一次,即使是删除之后再上传也不会执行
19.Spark Streaming与Kafka(分布式消息队列),需要修改/config/server.properties中配置项broker.id(Kafka集群管理的节点号),每个Topic对应的partition个数,zookeeper连接(zookeeper.connect=localhost:2181)
先启动zookeeper(元数据存放),再启动bin/kafka-server-start.sh config/server.properties
Kafka采用生产者-消费者模式,Topic相当于消息队列
Spark Streaming与kafka整合:
1)Receive
KafkaUtils.createStream(jssc,zkList,”kafka”,kafkaParams);//zkList为zookeeper地址(ip:port),kafkaParams为kafka参数指定连接到哪个topic(消息队列),以及receiver线程
为了保证零数据丢失,需要开启Write Ahead Logs
2)Direct
JavaPairInputDStream
1)简单并行度:一个topic中的partitions对应于一个RDD的partitions
2)效率:保证零数据丢失,不需要持久化到预写日志
3)仅计算一次:仅调用简单kafka API,不使用zookeeper,消费者offset放到spark streaming checkpoint
19.Spark on yarn and MapReduce on yarn区别
1)Spark异步并发模型采用Akka(实现Acor,并发度更高),而MapReduce采用epoll+状态机
2)Spark采用多线程模型(一个Container运行多个TaskRunner即线程执行Task),MapReduce采用多进程模型(一个Container运行一个Task,便于控制每个Task的资源)
3)Spark允许资源复用,而MapReduce需要反复申请所以启动时间过长
4)Spark有利用共享内存,适合内存密集型任务或者计算密集型任务,但是会产生资源竞争,Task失败会重试Attempt
MapReduce on yarn
Spark on yarn
20.Spark内存管理模型
Spark 1.6以前采用静态内存管理模型
Spark on Yarn
Spark 1.6以后的动态内存管理模型
JVM堆内存中有300MB作为预留内存(Reservered Memory),剩余内存中25%的作为用户内存(User Memory),75%的是Spark允许使用的内存包括(Storage Memory和Execution Memory)
内存管理模型选择:spark.memory.useLegacyMode=true 则使用静态内存管理模型
否则使用新的模型
21.Spark MLLIB
Spark Mllib提供包括:
Ø 机器学习算法(ML Algorithms):分类,回归,聚类以及协同过滤
Ø 特征(Featurization):特征提取,转型,降维,选择
Ø 管道(Pipelines):构造,评估以及调整ML管道
Ø 持久化(persistence):保存以及加载算法,模型,管道
Ø 工具:线性代数,统计,数据处理
尽管Spark Mllib仍然支持RDD API,但现在主推DataFrame API
(1)Data types(数据类型)
u Local Vector(本地向量):Mllib允许本地向量或者本地矩阵存储在单机器中,或者由一个/多个RDD支持的分布式矩阵,本地向量有基于Integer类型和基于0的指数,double类型值
本地向量一般分为dense(密集)和sparse(稀疏),dense向量支持double数组,而sparse向量支持两平行数组(索引和值)
u LabeledPoint(打标签):允许给密集矩阵和稀疏矩阵打标签(Y),用于二分类或者多分类
Mllib支持读训练实例(LIBSVM)格式的数据文件,对应每一行:
label index1:value1 index2:value2
u Local Matrix(本地矩阵):分为稀疏矩阵和密集矩阵
u Distributed Matrix(分布式矩阵):分为RowMatrix,IndexedRowMatrix,CoordinateMatrix
机器学习算法:
1.分类和回归(classification and regression)
Ø Loss Function(损失函数):最小化损失(训练错误)以及最小化模型复杂度
Position label = 1
Negative label=0
Ø Regularizers(补偿函数)防止过拟合
L1补偿:可以提高权重的稀疏性,从而导致更合理更具代表性的模型
L2补偿:适用于特征提取
Elastic 网:是两者结合
Ø Optimization(优化)
线性方法使用凸优化方法优化目标函数,spark mllib采用SGD(多数API支持)和L-BFGS(少数API)
Ø Classification(分类)
分类包括二分类( binary classification,position label和negative label )和多分类(multiclass classification包括多个类别),Spark.mllib支持两种线性分类方法包括SVM(支持向量机,仅支持二分类)和logistic regression(逻辑回归,可支持多分类),L1和L2作为补偿函数,训练集实际上是an RDD of LabeledPoint
Ø SVM(线性支持向量机)
适用于大量数据的分类任务,其目标函数如下(损失函数采用 hinge loss:):
L(w;x,y):=max{0,1−ywTx}.
默认采用L2补偿函数,目标函数输出一个SVM模型,测试集得到大量positive label或者negative label
Ø Logistic regression(逻辑回归损失函数logistic loss)
逻辑回归广泛用于二进制响应
L(w;x,y):=log(1+exp(−ywTx)).使用以下模型来预测
线性最小二乘法(: ordinary least squares or linear least squares uses no regularization)没有补偿函数,(ridge regression uses L2 regularization)脊回归采用L2范数,(Lasso uses L1 regularization)拉索回归采用L1范数
2.Naive Bayes(贝叶斯分类器)、
Spark.mllib支持 multinomial naive Bayes and Bernoulli naive Bayes.都是基于文档分类( document classification),每个特征代表一个术语(其值可能是术语的频次或者01表示是否出现在文档),训练数据通常只使用一次因此没必要缓存
旨在填满用户-商品关联矩阵(user-item association matrix),一般为稀疏矩阵,Spark支持基于模型的协同过滤(spark.mllib currently supports model-based collaborative filtering),用户-商品可作为预测缺失项的潜在因子,spark.mllib使用交替最小二乘法(ALS)去学习这些潜在因子,其中参数包括:
numBlocks:用于并行计算的块数
rank:模型中潜在因子的个数
Iteration:ALS的迭代次数,一般是至多20次
lambda:ALS中的规则化参数
implicitPrefs:决定是否使用显示反馈ALS变体或者隐式反馈数据
alpha:隐式反馈变体的参数、
Spark mllib允许处理来自隐式反馈数据集的协同过滤,将这些隐式反馈数据集与用户偏好关联,可用于预测用户对项目预期偏好的潜在因素
3. Clustering(聚类)
Ø Kmeans clustering
Ø Gaussian mixture(高斯混合),点从k个高斯子分布的一个汇出,每个高斯子分布都有自身的概率,spark mllib采用期望最大化算法给出一组样本的最大似然模型
1)计算每个点由每个Component即Cluster生成的概率
2)由混合高斯分布计算得到每个Component的最大似然值
3)重复迭代直到收敛
Ø Power iteration clustering (PIC)
功率迭代聚类(PIC)用于把图中的顶点聚类为给定边属性的成对相似性,利用功率迭代计算图的归一化相似度矩阵的伪特征向量,输入(srcId,dstId,相似度)元组的RDD,输出具有聚类的模型
Ø LDA(潜在狄氏分配):基于文档document(rows)的话题topic(cluster center)模型,距离测度基于一种统计模型,优化器包括EMLDAOptimizer和OnlineLDAOptimizer
K(聚类数): Number of topics (i.e., cluster centers)
Optimizer(优化器): Optimizer to use for learning the LDA model, either EMLDAOptimizer or OnlineLDAOptimizer
docConcentration(文档集中): Dirichlet parameter for prior over documents’ distributions over topics. Larger values encourage smoother inferred distributions.
topicConcentration(话题集中): Dirichlet parameter for prior over topics’ distributions over terms (words). Larger values encourage smoother inferred distributions.
maxIterations(最大迭代): Limit on the number of iterations.
checkpointInterval(checkpoint): If using checkpointing (set in the Spark configuration), this parameter specifies the frequency with which checkpoints will be created. If maxIterations is large, using checkpointing can help reduce shuffle file sizes on disk and help with failure recovery.
All of spark.mllib’s LDA models support:
describeTopics(话题描述): Returns topics as arrays of most important terms and term weights
topicsMatrix(话题矩阵): Returns a vocabSize by k matrix where each column is a topic
Ø Bisecting k-means(平均K均值)
属于层次聚类,一般分为:
1)凝聚(Agglomerative):每个观察者从自身Cluster出发,自下而上层次合并pairs
2)分裂(Divisive):所有观察者从一个Cluster出发,随着层次结构向下依次分割pairs、
Ø SVD(奇异值分解降维)
Ø PCA(主成成分分析)
Ø TF-IDF(特征提取)反映数据项对文档的权重
TF(t,d):数据项t在文档d中出现的频次
DF(t,D):文档集合D中包含数据项t的文档个数
Ø Word2Vec
Word2Vec计算words的分布式向量表示,相似的words在向量域很近,采用skip-gram非常擅长在相同句子预测上下文,能最大化对数似然
通过扩展单位方差和消除平均值(使用训练集中样例的列汇总统计)
Ø Normalizer
允许对单个样本进行标度,用于文本分类或者聚合
特征选择试图确定模型构建中的相关特征,具有分类功能的标签数据,支持三种选择方法:numTopFeature(根据卡方检测选择固定数目的数据),percentile(百分比选择),fpr(选择p值以下的数据)
将一个向量转换为另一个向量,类似于矩阵相乘
Ø FP-growth
FP(频繁模式)-增长:一般分为两步
1)计算数据项频率以及识别频繁项
2)使用后缀树(FP-Tree)结构编码事物,而不用显示生成候选集
3)从FP-Tree中提取频繁项
7.PMML模型
8.Optimization(优化器)
L-BFGS性能要优于SGD