当前位置:   article > 正文

计算引擎发展-Spark_spark计算引擎

spark计算引擎

Spark

Spark 是一种快速、通用、可扩展的大数据分析计算引擎,本质上也是 MapReduce 的后继产物,相比之下具有以下优点:

  1. Spark 提供了低延迟和高吞吐量的流式数据处理能力。它使用了一种称为“微批处理”的技术,将连续的数据流划分为小的批处理作业,并以非常短的间隔进行处理。这使得 Spark 能够实时处理和分析数据,并在数据到达时在短时间内做出响应。

  2. Spark 的内存计算引擎提供 Cache 机制来支持需要反复迭代计算或者多次数据共享,减少数据读取的 IO 开销,从而提高了处理效率。

  3. Spark 支持多种数据输入源,例如:Kafka、Flume、Twitter、ZeroMQ 和简单的 TCP socket等等。

  4. Spark 支持容错机制,可以自动恢复失败的任务,从而保证了系统的高可用性。

  5. Spark 支持 DAG(有向无环图)作业调度模型,可以方便地实现任务之间的依赖关系,从而提高了作业的执行效率。

与此同时随着内存价格的下降和普及,Spark 逐渐成为了大数据计算领域的热门选择。

Spark 编程模型

RDD(Resilient Distributed Dataset):是 Spark 中最基本的数据结构,是一个不可变的、分布式的对象集合。RDD 可以通过分区和复制来实现容错和并行处理。

大数据计算就是在大规模的数据集上进行一系列的数据计算处理MapReduce 针对输入数据,将计算过程分为两个阶段,一个 Map 阶段,一个 Reduce 阶段,可以理解成是面向过程的大数据计算。在用 MapReduce 编程的时候,思考的是,如何将计算逻辑用 Map 和 Reduce 两个阶段实现,map 和 reduce 函数的输入和输出是什么。

而 Spark 则直接针对数据进行编程,将大规模数据集合抽象成一个 RDD 对象,然后在这个 RDD 上进行各种计算处理,得到一个新的 RDD,继续计算处理,直到得到最后的结果数据。所以 Spark 可以理解成是面向对象的大数据计算。我们在进行 Spark 编程的时候,思考的是一个 RDD 对象需要经过什么样的操作,转换成另一个 RDD 对象,思考的重心和落脚点都在 RDD 上。

  1. // 读取文件
  2. val textFile = sc.textFile("hdfs://...")
  3. // RDD 转换,每次转换都得到一个新的 RDD
  4. val rdd1 = textFile.flatMap(line => line.split(" "))
  5. val rdd2 = rdd1.map(word => (word, 1))
  6. val rdd3 = rdd2.reduceByKey(_ + _)
  7. // 执行,保存到文件中
  8. counts.saveAsTextFile("hdfs://...")

Spark 的计算阶段

和 MapReduce 一样,Spark 也遵循移动计算比移动数据更划算 这一大数据计算基本原则。但是和 MapReduce 僵化的 Map 与 Reduce 分阶段计算相比,Spark 的计算框架更加富有弹性和灵活性,进而有更好的运行性能 。

Spark 会根据程序中的转换函数生成计算任务执行计划,这个执行计划就是一个 DAG 。Spark 可以在一个作业中完成非常复杂的大数据计算 。

所谓 DAG 也就是 有向无环图,就是说不同阶段的依赖关系是有向的,计算过程只能沿着依赖关系方向执行,被依赖的阶段执行完成之前,依赖的阶段不能开始执行,同时,这个依赖关系不能有环形依赖,否则就成为死循环了。下面这张图描述了一个典型的 Spark 运行 DAG 的不同阶段。

在上面的图中, A、C、E 是从 HDFS 上加载的 RDD,A 经过 groupBy 分组统计转换函数计算后得到的 RDD B,C 经过 map 转换函数计算后得到 RDD D,D 和 E 经过 union 合并转换函数计算后得到 RDD F ,B 和 F 经过 join 连接函数计算后得到最终的合并结果 RDD G 。

所以可以看到 Spark 作业调度执行的核心是 DAG,有了 DAG,整个应用就被切分成哪些阶段,每个阶段的依赖关系也就清楚了。之后再根据每个阶段要处理的数据量生成相应的任务集合(TaskSet),每个任务都分配一个任务进程去处理,Spark 就实现了大数据的分布式计算。

通过观察一下上面的 DAG 图,关于计算阶段的划分从图上就能看出规律,当 RDD 之间的转换连接线呈现多对多交叉连接(宽依赖)的时候,就会产生新的阶段。一个 RDD 代表一个数据集,图中每个 RDD 里面都包含多个小块,每个小块代表 RDD 的一个分片。

Spark的阶段划分是基于宽依赖(wide dependency)和窄依赖(narrow dependency)的概念。宽依赖发生在一个父RDD的每个分区都需要与下游操作的多个分区进行数据交换时,这会导致数据的洗牌操作。而窄依赖发生在每个父RDD的分区只需要与下游操作的一个分区进行数据交换时,不需要进行数据洗牌。

在Spark中,每个宽依赖都会划分为一个新的阶段,而窄依赖则可以在同一个阶段内进行处理。这样可以有效地减少数据洗牌的开销,提高数据处理的效率。

Spark SQL

Spark SQL是Spark的一个模块,用于处理结构化数据。

Spark Streaming

Spark Streaming 是 Spark 的核心组件之一,为 Spark 提供了可拓展、高吞吐、容错的流计算能力。

Streaming 架构

如下图所示,Spark Streaming 可整合多种输入数据源,如 Kafka、Flume、HDFS,甚至是普通的 TCP socket。经处理后的数据可存储至文件系统、数据库或显示在仪表盘里。

Spark Streaming 的基本原理是将实时输入数据流以时间片(秒级)为单位进行拆分,然后经 Spark 引擎以类似批处理的方式处理每个时间片数据,执行流程如下图所示:

Spark Streaming 最主要的抽象是 DStream(Discretized Stream,离散化数据流),表示连续不断的数据流。在内部实现上,Spark Streaming 的输入数据按照时间片(如1秒)分成一段一段的 DStream,每一段数据转换为Spark 中的 RDD,并且对 DStream 的操作都最终转变为对相应的 RDD 的操作。例如,下图展示了进行单词统计时,每个时间片的数据(存储句子的RDD)经 flatMap 操作,生成了存储单词的 RDD。整个流式计算可根据业务的需求对这些中间的结果进一步处理,或者存储到外部设备中。

容错性

Spark具有容错性是因为它是一种分布式计算框架,可以将计算任务分配到多个节点上执行。当某个节点出现故障时,Spark会自动将该节点上的计算任务重新分配到其他节点上执行,从而保证整个计算任务的连续性和正确性。

另一方面,每一个RDD都是一个不可变的分布式可重算的数据集,其记录着确定性的血统关系(lineage),所以只要输入数据是可容错的,那么任意一个RDD的分区(Partition)出错或不可用,都是可以利用原始输入数据通过转换操作而重新算出的。

对于Spark Streaming来说,其RDD的传承关系如下图所示,图中的每一个椭圆形表示一个RDD,椭圆形中的每个圆形代表一个RDD中的一个Partition,图中的每一列的多个RDD表示一个DStream(图中有三个DStream),而每一行最后一个RDD则表示每一个Batch Size所产生的中间结果RDD。我们可以看到图中的每一个RDD都是通过lineage相连接的,由于Spark Streaming输入数据可以来自于磁盘,例如HDFS(多份拷贝)或是来自于网络的数据流(Spark Streaming会将网络输入数据的每一个数据流拷贝两份到其他的机器)都能保证容错性,所以RDD中任意的Partition出错,都可以并行地在其他机器上将缺失的Partition计算出来。这个容错恢复方式比连续计算模型(如Storm)的效率更高。

    

在Spark中,检查点(Checkpoint)是一种容错机制,可以将RDD的中间结果写入磁盘,以便在需要时恢复数据。检查点的主要目的是通过血统(Lineage)来做容错的辅助,血统过长会造成容错成本过高,这样就不如在中间阶段做检查点容错,如果之后有节点出现问题,可以从检查点开始重做血缘,减少了开销。

Spark Streaming将流数据按批处理窗口大小(通常在0.5~2秒之间)分解为一系列批处理作业,在这个过程中,会产生多个Spark作业,且每一段数据的处理都会经过Spark DAG图分解、任务调度过程,一个完成才可以计算下一个,因此,无法实现毫秒级响应。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/727397
推荐阅读
相关标签
  

闽ICP备14008679号