Spark 基础
-
特点
速度快=>基于内存的分布式计算 高兼容=>多模式部署,hdfs,mysql,hive 多模式=>算子,sql,流,图,计算 高容错=>DAG Lineage 高灵活=>持久化(内存+磁盘)
-
Spark技术栈
1.Spark Core 核心组件,分布式计算引擎。其实现了 Spark 的作业调度、内存管理、容错、 与存储系统交互等基本功能,并针对弹性分布式数据集(RDD)提供了丰富的操 作。 2.Spark SQL 基于 Hadoop 的 SQL 解决方案。部分用法与 Hive 非常类似。 3.Spark Streaming 基于 Spark Core 实现的高吞吐量、具备容错机制的准实时流处理系统。 4.Spark GraphX 分布式图处理框架,支持图并行计算。 5.Spark MLlib 构建在Spark上的分布式机器学习库
-
Spark架构核心组件
[Application]:建立在Spark上的用户程序,包括Driver代码和运行在集群各节点Executor中的代码 [Driver program]:驱动程序。Application中的main函数并创建SparkContext [Cluster Manager]:在集群(Standalone、Mesos、YARN)上获取资源的外部服务 [Worker Node]:集群中任何可以运行Application代码的节点 [Executor]:某个Application运行在worker节点上的一个进程 [Task]:被送到某个Executor上的工作单元,task的调度和管理等是由TaskScheduler负责 [Job]:包含多个Task组成的并行计算,往往由Spark Action触发生成,一个Application中往往会产生多个Job [Stage]:每个Job会被拆分成多组Task,作为一个TaskSet,其名称为Stage,Stage的划分和调度是有DAGScheduler来负责的,Stage的边界就是发生shuffle的地方 数据本地化:保证一个Stage内不会发生数据移动
-
Standalone运行模式
即独立模式,自带完整的服务,可单独部署到一个集群中,无需依赖任
何其他资源管理系统
1、构建Spark Application的运行环境,初始化SparkContext,同时会产生两个对象,DAGSchedule和TaskSchedule 2、SparkContext可以连接不同类型的Cluster Manager(Standalone、YARN、Mesos),连接后,获得集群节点上的Executor 3、Executor向SparkContext申请Task 4、DAGSchedule构建成DAG图,将DAG图分解成Stage、将Taskset发送给Task Scheduler,最后由Task Scheduler将Task发送给Executor运行 5、每个executor持有一个线程池,每个线程可以执行一个task,每个Task处理一个RDD分区,executor执行完task以后将结果返回给driver --DAGScheduler: 负责分析用户提交的应用,并根据计算任务的依赖关系建立 DAG,且将DAG划分为不同的Stage,每个Stage可并发执行一组Task。 --TASKSedulter: 将TaskSET提交给worker运行,每个Executor运行什么Task就是在此处分配的. TaskScheduler维护所有TaskSet,当Executor向Driver发生心跳时,TaskScheduler会根据资源剩余情况分配相应的Task。 另外TaskScheduler还维护着所有Task的运行标签,重试失败的Task
-
RDD:弹性分布式数据集
分布式数据集 =>RDD是只读的、分区记录的集合,每个分区分布在集群的不同节点上 =>RDD并不存储真正的数据,只是对数据和操作的描述 弹性 =>RDD默认存放在内存中,当内存不足,Spark自动将RDD写入磁盘 容错性 =>根据数据血统,可以自动从节点失败中恢复分区
DAG(有向无环图)反映了RDD之间的依赖关系
RDD的特性1、一系列的分区(分片)信息,每个任务处理一个分区 2、每个分区上都有compute函数,计算该分区中的数据 3、RDD之间有一系列的依赖 4、分区器决定数据(key-value)分配至哪个分区 5、优先位置列表,将计算任务分派到其所在处理数据块的存储位置
RDD的依赖关系
Lineage:血统、遗传 RDD最重要的特性之一,保存了RDD的依赖关系 RDD实现了基于Lineage的容错机制
宽依赖:一个父RDD的分区被子RDD的多个分区使用,对应shuffle操作
窄依赖:一个父RDD的分区被子RDD的一个分区使用
当RDD分区丢失时,Spark会对数据进行重新计算,对于窄依赖只需重新计算一次子RDD的父RDD分区
-
DAG工作原理
--根据RDD之间的依赖关系,形成一个DAG(有向无环图) --DAGScheduler将DAG划分为多个Stage 1、划分依据:是否发生宽依赖(Shuffle) 2、划分规则:根据最后一个RDD创建 ResultStage,获取所有父RDD。判断父RDD是否宽依赖,如果是,则新创建一个ShuffleMapStage,否则将父RDD入栈并认为该父RDD属于当前Stage 3、每个Stage由一组并行的Task组成
-
RDD优化
RDD缓存机制:缓存数据至内存/磁盘,可大幅度提升Spark应用性能,遇到Action算子完成后才生效
cache=persist(MEMORY) cache() 只有一个默认的缓存级别MEMORY_ONLY persist()根据情况设置其它的缓存级别 StorageLevel类的主构造器包含了5个参数 useDisk:使用硬盘(外存) useMemory:使用内存 useOffHeap:使用堆外内存 deserialized:反序列化 replication:备份数
检查点:类似于快照
sc.setCheckpointDir("hdfs:/checkpoint0918") val rdd=sc.parallelize(List(('a',1), ('a',2), ('b',3), ('c',4))) rdd.checkpoint rdd.collect //生成快照
检查点与缓存的区别
1、检查点会删除RDD lineage,而缓存不会 2、SparkContext被销毁后,检查点数据不会被删除
常见数据倾斜解决方案
1、对数据进行ETL预处理 1)hive中文件大小不均匀 2)hive中key分布不均匀,可以将shuffle类操作先进行处理 2、过滤少数导致倾斜的key 3、提高shuffle操作的并行度 具体操作是将 shuffle 算子,比如 groupByKey、countByKey、reduceByKey。在调用的时候传入进去一个参数,一个数字。那个数字就代表了那个shuffle操 作的reduce端的并行度 4、两阶段聚合(局部聚合+全局聚合) 将原本相同的key通过附加随机前缀的方式,变成多个不同的key, 就可以让原本被一个 task 处理的数据分散到多个 task 上去做局部聚合,进而解 决单个task处理数据量过多的问题。接着去除掉随机前缀,再次进行全局聚合 5、将reduce join 转为map join 6、采样倾斜Key并分拆join操作 7、使用随机前缀和扩容RDD进行join
-
Spark性能优化
1、序列化 2、使用对象数组、原始类型代替Java、Scala集合类(如HashMap) 避免嵌套结构 尽量使用数字作为Key,而非字符串 RDD重用(以较大的RDD使用MEMORY_ONLY_SER) 加载CSV、JSON时,仅加载所需字段 仅在需要时持久化中间结果(RDD/DS/DF) 避免不必要的中间结果(RDD/DS/DF)的生成 DF的执行速度比DS快约3倍 3、自定义RDD分区与spark.default.parallelism 该参数用于设置每个stage的默认task数量 将大变量广播出去,而不是直接使用 尝试处理本地数据并最小化跨工作节点的数据传输 4、表连接(join操作) 包含所有表的谓词(predicate) 最大的表放在第一位 广播最小的表 最小化表join的数量