20210117
大数据 | 大数据基础--系统之大数据批处理框架--Spark
亲爱的读者朋友大家晚上好,上次我们介绍了Hadoop的数据管理系统,并且我也提到从这次开始要介绍一些特殊的处理框架,在这篇文章中我们来看大数据的批处理框架Spark&Hyracks以及一些其它的批处理框架~
什么是大数据的批处理
- 批处理操作大容量静态数据集,并在计算过程完成后返回结果。
- 批处理模式中使用的数据集通常符合下列特征:
- 有界:批处理数据集代表数据的有限集合。
- 持久:数据通常始终存储在某种类型的持久存储位置中。
- 大量:批处理操作通常是处理极为海量数据集的唯一方法。
- 批处理适合
- 需要访问全套记录才能完成的计算工作
- 对历史数据进行分析
- 批处理不适合
- 对处理时间要求较高的场合
Spark的目标
- 为集群运算提供分布式内存抽象,以支持具有工作集的应用程序
- 保留了MapReduce的优秀特性
- 容错机制(为崩溃程序和落后程序)
- 数据局部性
- 可扩展性
解决方案:使用“弹性分布式数据集”(RDDs)的增强数据流模型
Spark与Hadoop的对比
先来看一下MapReduce的执行流程
再来看一下Spark的执行流程,相比于MapReduce的执行流程,主要是多了数据的存储过程
大数据的批处理任务的抽象(Spark-RDD)
需要解决的问题
- 操作的数据形式和结构是什么?
- 应用程序可以对于数据做何种操作?
需要考虑的问题
- 适用的场景/数据是什么?
- 面向的软硬件环境是什么?
- 支撑应用程序之间的界面在哪里?
RDD设计背景
- 许多迭代式(比如机器学习、图算法等)和交互式数据挖掘 工具,共同之处是,不同计算阶段之间会重用中间结果
- 目前的MapReduce框架都是把中间结果写入到稳定存储(比如磁盘)中,带来了大量的数据复制、磁盘IO和序列化开销
- RDD提供了一个抽象的数据架构,不必担心底层数据的分布式特性,只需将具体的应用逻辑表达为一系列转换处理
- 不同RDD之间的转换操作形成依赖关系,可以实现数据流水 处理,避免中间数据存储
RDD概念
- 一个RDD是一个分布式对象集合,本质上是一个只读的分 区记录集合
- 每个RDD可分成多个分区,每个分区就是一个数据集片段
- 一个RDD的不同分区可以被保存到集群中不同的节点上, 从而可以在集群中的不同节点上进行并行计算
- RDD提供了一种高度受限的共享内存模型
- RDD是只读的记录分区的集合,不能直接修改
- 只能基于稳定的物理存储中的数据集创建RDD,或者通过在其他RDD上执行确定的转换操作(如map、join和 group by)而创建得到新的RDD
RDD操作
- RDD提供了一组丰富的操作以支持常见的数据运算,分为 “动作”(Action)和“转换”(Transformation)两种类型
- RDD提供的转换接口都非常简单,都是类似map、filter、 groupBy、join等粗粒度的数据转换操作,而不是针对某个数 据项的细粒度修改(不适合网页爬虫)
- RDD已经被实践证明可以高效地表达许多框架的编程模型(如MapReduce、SQL、Pregel)
- Spark用Scala语言实现了RDD的API,程序员可以通过调用 API实现对RDD的各种操作
RDD执行过程
- RDD读入外部数据源进行创建
- RDD经过一系列的转换(Transformation)操作,每一次都会产生不同的RDD,供给下一个转换操作使用
- 最后一个RDD经过“动作”操作进行转换,并输出到外部数据源
RDD的高效的原因
- 高效的容错性
- 现有容错机制:数据复制或者记录日志
- RDD:血缘关系、重新计算丢失分区、无需回滚系统、 重算过程在不同节点之间并行、只记录粗粒度的操作
- 中间结果持久化到内存,数据在内存中的多个RDD操作之间进行传递,避免了不必要的读写磁盘开销
- 存放的数据可以是Java对象,避免了不必要的对象序列化和反序列化
大数据的批处理框架的API
需要解决的问题
- 程序员如何基于框架编写应用程序?
需要考虑的问题
- 面向什么样的程序员?
- 开发的效率?
- 程序的易读性?
- 程序的美感?
- 是否符合传统开发的习惯?
Spark编程模型
操作RDD的API--程序员可以执行3种类型的操作
大数据的批处理系统的系统架构
需要解决的问题
- 系统有哪些模块?
- 模块之间如何交互?
需要考虑的问题
- 有效配合硬件
- 扩展性高
- 效率高
- 弹性好
- 开发容易
- 维护方便
- 升级简单
基本概念
- DAG:是Directed Acyclic Graph(有向无环图)的简称, 反映RDD之间的依赖关系
- Executor:是运行在工作节点(WorkerNode)的一个进程 ,负责运行Task
- 应用(Application):用户编写的Spark应用程序
- 任务( Task ):运行在Executor上的工作单元
- 作业( Job ):一个作业包含多个RDD及作用于相应RDD上 的各种操作
- 阶段( Stage ):是作业的基本调度单位,一个作业会分为 多组任务,每组任务被称为阶段,或者也被称为任务集合, 代表了一组关联的、相互之间没有Shuffle依赖关系的任务组成的任务集
架构设计
- Spark运行架构包括集群资源管理器(Cluster Manager)、运行 作业任务的工作节点(Worker Node)、每个应用的任务控制节 点(Driver)和每个工作节点上负责具体任务的执行进程 (Executor)
- 资源管理器可以自带或Mesos或YARN
- SparkContext处于DriverProgram核心位置,所有与 Cluster、Worker Node交互的操作都需要SparkContext 来完成,相当于交互的代理
- 一个应用由一个Driver和若干个作业构成,一个作业由多个阶段构成,一个阶段由 多个没有Shuffle关系的任务组成
- 当执行一个应用时,Driver会向集群管理器申请资源,启动Executor,并向 Executor发送应用程序代码和文件,然后在Executor上执行任务,运行结束后,执行结果会返回给Driver,或者写到HDFS或者其他数据库中
大数据的批处理系统的基本数据操作
需要解决的问题
- 包括哪些基本数据操作?
- 并行还是串行实现?
- 高效实现算法?
需要考虑的问题
- 有效支撑API
- 容易理解
- 扩展性高
- 效率高
shuffle操作
宽窄依赖
- 窄依赖 : 一个父RDD的分区对应 于一个子RDD的分区或多个父RDD的分区对应于一个子RDD 的分区
- 宽依赖 : 存在一个父RDD的一个 分区对应一个子 RDD的多个分区
大数据的批处理系统中的流程生成
需要解决的问题
- 基本数据操作和用户自定义逻辑的步骤划分
- 基本数据操作和用户自定义逻辑的执行顺序
需要考虑的问题
- 可用性高
- 效率高
- 容易理解
- 容易支持调试工具
阶段划分
- 根据DAG 图中的RDD 依赖关系,把一个作业分成多个阶段。
- 阶段划分的依据是窄依赖和宽依赖:窄依赖对于作业的优化很有利,宽依赖无法优化
- 逻辑上,每个RDD 操作都是一个fork/join(一种用于并行执行任务的框架),把计算fork 到每个RDD 分区,完成计算后对各个分区得到的结果进行join 操作,然后fork/join下一个RDD操作
宽依赖往往对应着shuffle操作(多对一,汇总,多节点),需要在运行过程中将同一个父RDD 的分区传入到不同的子RDD分区中,中间可能涉及多个节点之间的数据传输;而窄依赖 的每个父RDD的分区只会传入到一个子RDD分区中,通常可以在一个节点内完成转换。
具体的划分方法如下所示
- 通过分析各个RDD的依赖关系生成了DAG,再通过分析各个RDD 中的分区之间的依赖关系来决定如何划分Stage
- 具体步骤(贪心法):
- 在DAG中进行反向解析,遇到宽依赖就断开
- 遇到窄依赖就把当前的RDD加入到Stage中
- 将窄依赖尽量划分在同一个Stage中,可以实现流水线计算
大数据的批处理系统中的流程调度
需要解决的问题
- 执行过程中如何执行操作?
需要考虑的问题
- 可扩展性高
- 效率高
Spark端到端流程
- Spark 的Driver Program (简称 Driver)包含用户的应用程序
- Driver完成task的解析和生成
- Driver向Cluster Manager(集群资源管理器)申请运行task 需要的资源。
- 集群资源管理器 为task分配满足 要求的节点,并在节点按照要求 创建Executor
- 创建的Executor 向Driver注册。
- Driver将spark应用程序的代码和文件传送给分配的executor
- executor运行task,运行完之 后将结果返回给 Driver或者写入HDFS或其他介质。
RDD运行过程
- 创建RDD对象
- SparkContext负责计算RDD之间的依赖关系,构建DAG
- DAGScheduler负责把DAG图分解成多个Stage,每个Stage中包含了多个 Task,每个Task会被TaskScheduler分发给各个WorkerNode上的Executor去执行
大数据的批处理系统中的事务处理
需要解决的问题
- 如何保证执行的正确性
需要考虑的问题
- 结点出错怎么办?
- 分布式系统出现读脏写脏怎么办?
RDD容错机制
- RDD维护着可以用来重建丢失分区的信息
大数据的批处理系统中的数据存储机制
需要解决的问题
- 何时存储数据?
- 数据存储成什么形式?
需要考虑的问题
- 高(时间/存储)效率
- 内存满足要求
Spark中的存储机制
- RDD缓存:包括基于内存和磁盘的缓存
- 分区和数据块是一一对应的
- 在内部建立RDD分区和数据块之间的映射,需要读取缓存的RDD时,根据映射关系取得分区对应的数据块
- 内存缓存=哈希表+存取策略
- 一个数据块对应着文件系统中的一个文件,文件名和块名称的映射关系是通过哈希算法计算所得的
- Shuffle数据的持久化
- Shuffle数据块必须是在磁盘上进行缓存的
- Shuffle数据块的存储有两种方式:
- 将Shuffle数据块映射成文件
- 将Shuffle数据块映射成文件中的一段
总结
批处理框架其实还有很多,这次介绍的spark只是其中一个,下次我们来介绍另一个批处理框架hyracks~