写点什么

大数据开发之 Spark 和 Flink 的对比(转载)

  • 2021 年 12 月 13 日
  • 本文字数:4356 字

    阅读完需:约 14 分钟

 大数据计算引擎的起源

Hadoop 和其他基于 mapreduce 的数据处理系统的出现首先是为了满足传统数据库无法满足的数据处理需求。随着 2004 年谷歌发布 MapReduce 白皮书以来的发展浪潮,利用 Hadoop 的开源生态系统或类似系统处理大数据已经成为行业的基本需求。

尽管最近努力降低进入门槛,但在开发自己的数据处理系统时,大数据培训组织不可避免地会遇到一系列问题,常常会发现从数据中获得价值所需的投资大大超出预期。

下面的章节将详细介绍这些问题中最普遍的部分,这有助于解释 Spark 和 Flink 继续竞争行业偏好的基础。

非常陡峭的学习曲线

刚接触大数据的人通常会对需要掌握的技术数量感到震惊。过去几十年发展起来的传统数据库一般都是为了综合数据处理而构建的,而像 Hadoop 这样的大数据生态系统需要几个不同的子系统,每个子系统在呈现各种需求场景之前都有自己的专长和优势。



点击并拖拽以移动

 上面的图片描述了一个典型的 lambda 架构。仅仅展示了两种场景(批处理和流处理),它已经涉及了至少四到五种技术,不包括经常需要考虑的替代方案。通过添加实时查询、交互分析、机器学习和其他场景,每种情况都涉及到以不同方式覆盖重叠区域的几种技术之间的选择。因此,业务通常需要使用许多技术来支持完整的数据处理。再加上研究和选择,投资者需要消化的信息量是巨大的。

开发运营效率低下

由于涉及的系统种类繁多,每个系统都有自己的开发工具和语言,大数据的开发效率在默认情况下相当有限。由于数据需要在多个系统之间传输,进一步的开发和操作成本不可避免地会出现。同时,数据一致性仍然难以保证。

在许多组织中,超过一半的开发工作花费在系统之间的数据传输上。

操作复杂、数据质量等问题

多个系统,每个系统都需要自己的操作和维护,带来较高的运行成本,增加系统出错的可能性。此外,很难保证数据的质量,而且当问题确实出现时,很难跟踪和解决它们。

最后但并非最不重要的,还有人的问题。在许多情况下,系统的复杂性意味着对每个子系统的支持和使用必须在不同的部门中实现,这些部门并不总是与目标和优先级保持一致。

到一个解决方案

鉴于这些问题,不难理解 Spark 的受欢迎程度。在其 2014 年崛起之时,Spark 不仅增强了 Hadoop MapReduce 的性能,而且还提供了一个通用引擎来支持各种数据处理场景。在一个笔记本中看到一个 Spark 演示程序与上述所有场景一起工作,对于许多开发人员来说,转向 Spark 是一个相对容易的决定。因此,Spark 作为 Hadoop 中的 MapReduce 引擎的完全替代品出现也就不足为奇了。

与此同时,Flink 的出现是为了在一系列场景中提供更方便的使用,特别是在数据流的实时处理方面。

随着竞赛领域的建立,下面的部分将在技术层面上比较这两种竞争的框架。

在 Spark 和 Flink 中处理引擎

本节重点讨论 Spark 和 Flink 引擎的架构特性,重点讨论它们架构的潜力和局限性。和它们的数据和处理模型一样,它们在数据处理场景、有状态处理方法和编程模型中的重点是不同的。

数据模型和处理模型

要了解 Spark 和 Flink 中的引擎特性,首先必须检查它们各自的数据模型。

Spark 使用弹性分布式数据集(RDD)数据模型。RDD 比 MapReduce 的文件模型更抽象,它依赖沿袭来确保可恢复性。RDD 通常可以实现为分布式共享内存或完全虚拟化。这就是说,当下游处理完全是本地的时候,可以优化和省略某些中间结果 RDD。这节省了大量不必要的输入和输出,这是 Spark 早期性能优势的主要基础。

Spark 还在 RDD 上使用转换(操作符)来描述数据处理。每个操作符(如 map、filter、join)都会生成一个新的 RDD。所有的算子一起构成一个有向无环图(DAG)。Spark 简单地将边缘划分为宽依赖项和窄依赖项。当上游和下游数据不需要洗牌时,边缘是一个狭窄的依赖项。在这种情况下,上游和下游算子可以在同一阶段进行本地处理,可以省去上游结果 RDD 的物化。下图显示了所涉及的基本概念。



点击并拖拽以移动

 相比之下,Flink 的基本数据模型是由数据流组成的。,事件的顺序。作为数据的基本模型,数据流可能不像表或数据块那样直观和熟悉,但仍然可以提供一组完全等价的特性。一条小溪可以是一条无限的小溪,是无限的,这是普遍的感知。它也可以是有边界的有限流,处理这些流等同于批处理。

为了描述数据处理,Flink 在数据流上使用操作符,每个操作符生成一个新的数据流。在运营商、DAGs 和上下游运营商链方面,整个模型与 Spark 模型大致相同。Flink 的顶点与 Spark 中的阶段大致相同,将操作符划分为顶点与上图中 Spark DAG 中的划分阶段基本相同。



点击并拖拽以移动

 Spark 和 Flink 在 DAG 执行方面有一个显著的区别。在 Flink 的流执行模式中,在一个节点上处理后的事件输出可以发送到下一个节点进行立即处理。这样执行引擎就不会引入任何额外的延迟。相应地,所有节点需要同时运行。相反,Spark 的微批处理执行与正常的批处理执行没有区别,只有在上游阶段完成微批处理后,下游阶段才开始处理其输出。

在 Flink 的流执行模式中,可以一起传输或计算多个事件以提高效率。然而,这纯粹是执行引擎自行决定的优化。它可以独立地为每个操作符确定,并且不像批处理模型中那样绑定到数据集(如 RDD)的任何边界。它可以为优化留下灵活性,同时满足低延迟需求。

Flink 使用异步检查点机制来实现任务状态的可恢复性,以确保处理一致性。因此,可以消除数据源和输出之间的整个主处理路径上的 I/O 延迟,从而实现更高的性能和更低的延迟。

数据处理方案

除了批处理,Spark 还支持实时数据流处理、交互式查询、机器学习和图形计算等场景。



点击并拖拽以移动

 实时数据流处理和批处理之间的主要区别是低延迟要求。因为 Spark RDD 是基于内存的,所以可以很容易地将其切割成更小的块进行处理。快速处理这些小块可以实现低延迟。

如果所有数据都在内存中并且处理速度足够快,Spark 还可以支持交互式查询。

Spark 的机器学习和图形计算可以看作是不同类别的 RDD 操作符。Spark 提供了一些库来支持常见的操作,用户或第三方库还可以扩展并提供更多的操作。值得一提的是,Spark 的 RDD 模型与机器学习模型训练的迭代计算非常兼容。从一开始,它就在一些场景中带来了显著的性能改进。

基于这些特性,Spark 本质上是一个比 Hadoop MapReduce 更快的基于内存的批处理程序,它使用足够快的批处理来实现各种场景。



点击并拖拽以移动

 在 Flink 中,如果输入数据流是有界的,则批处理的效果自然会产生。流处理和批处理之间的区别仅在于输入类型,并且独立于底层实现和优化,因此用户需要实现的逻辑是完全相同的,从而产生一种更清晰的抽象。

Flink 还提供了一些库来支持机器学习和图形计算等场景。在这方面,它与 Spark 并没有太大的区别。

值得注意的是,Flink 的低级 API 可以单独使用 Flink 集群来实现一些数据驱动的分布式服务。一些公司使用 Flink 集群来实现社交网络、web 爬行和其他服务。这些用途反映了 Flink 作为通用计算引擎的多功能性,并得益于 Flink 的内置状态支持。

通常,Spark 和 Flink 的目标都是在单个执行引擎中支持大多数数据处理场景,并且都应该能够实现这一点。主要的区别在于,在某些场景中,它们各自的体系结构可能会受到限制。这种情况的一个值得注意的地方是 Spark 流的微批处理执行模式。Spark 社区应该已经意识到这一点,并且最近开始致力于持续处理。我们稍后会回到这个问题。

有状态的处理

Flink 的另一个非常独特的方面是在引擎中引入了托管状态。要理解托管状态,我们必须首先从有状态处理开始。如果处理事件(或数据片段)的结果只与事件本身的内容相关,则称为无状态处理;否则,结果与之前处理的事件相关,称为有状态处理。任何重要的数据处理,例如基本聚合,通常都是有状态处理。Flink 一直认为,如果没有良好的状态支持,就不会有有效的流,因此,托管状态和状态 API 很早就被引入了。



点击并拖拽以移动

 通常,有状态处理是在流的上下文中考虑的,但是仔细看看它也会影响批处理。以窗口聚合的常见情况为例,如果批处理数据周期大于窗口,则可以忽略中间状态,用户逻辑容易忽略这个问题。然而,当批处理周期小于窗口时,批处理的结果实际上依赖于之前处理过的批处理。因为批处理引擎通常看不到这种需求,所以它们通常不提供内置状态支持,需要用户手动维护状态。例如,在窗口聚合的情况下,用户将需要一个中间结果表来存储不完整窗口的结果。因此,当用户缩短批处理周期时,处理逻辑就变得更加复杂。在结构化流发布之前,这是早期 Spark 流用户的一个常见问题。

另一方面,作为流媒体引擎的 Flink 从一开始就必须面对这个问题,并引入了托管状态作为通用解决方案。除了简化用户的工作之外,与用户实现的解决方案相比,内置解决方案还可以实现更好的性能。最重要的是,它可以提供更好的一致性保证。

简单地说,数据处理逻辑中存在一些固有的问题,在批处理中可以忽略或简化而不影响结果,但在流处理中会暴露并解决这些问题。因此,在流引擎中以有限流的形式实现批处理,自然会产生正确的结果,而主要的工作是为了优化而在某些领域进行专门的实现。相反,小批量模拟流场则会暴露出新的问题。当计算引擎没有一个问题的通用解决方案时,它需要用户自己解决它。除了状态之外,问题还包括维度表更改(如更新用户信息)、批处理数据边界、延迟到达的数据等等。

编程模型



点击并拖拽以移动

 Spark 最初的意图之一是提供一个统一的编程模型,能够解决不同用户的各种需求——这是它投入了大量精力的一个重点。Spark 最初的基于 rd 的 API 已经能够进行各种数据处理。后来,为了简化用户的开发,在 Spark 2.0 (DataFrame = Dataset [Row])中引入并整合了更高级别的 DataFrame(在 RDD 中向结构化数据中添加列)和 Dataset(向 DataFrame 列添加类型)。Spark SQL 支持也相对较早地引入。随着特定于场景的 api 的不断改进,比如结构化流以及与机器学习和深度学习的集成,Spark 的 api 变得非常容易使用,现在已经成为该框架最强大的方面之一。



点击并拖拽以移动

 Flink 的 API 遵循了一组类似的目标和开发路径。Flink 和 Spark 的核心 api 可以看作是粗略的对应。在过去的两年里,通过对机器学习和深度学习的集成,Spark 的 API 总体上更加完整。Flink 仍然领先于流相关方面,例如它对水印、窗口和触发器的支持。



点击并拖拽以移动

 要点

Spark 和 Flink 都是通用计算引擎,支持非常大规模的数据处理和各种类型的处理。每一篇文章都提供了很多这里没有涉及的内容,比如 SQL 优化和机器学习集成。这种比较的主要目的是回顾这两个系统的基本架构和设计特性。其基本原理是,更实际的做法是通过协作学习来赶上更高级别的功能,而在基本设计中进行更改往往代价更大,也更令人望而却步。

Spark 和 Flink 不同的执行模型之间的最大区别在于它们对流处理的支持。最初 Spark 流处理的方法过于简单,在更复杂的处理中出现了问题。Spark 2.0 中引入的结构化流,清理了流语义,并增加了对事件时处理和端到端一致性的支持。尽管在功能方面仍有许多限制,但它在过去的迭代中取得了相当大的进展。微批处理执行方法仍然存在一些问题,特别是在大范围内的性能问题。最近,由于应用程序要求开发一种连续处理模式,Spark 受到了刺激。

原创作者:南极真君


用户头像

关注尚硅谷,轻松学IT 2021.11.23 加入

还未添加个人简介

评论

发布
暂无评论
大数据开发之Spark和Flink的对比(转载)