一、下一代大数据计算引擎
自从数据处理需求超过了传统数据库能有效处理的数据量之后,Hadoop 等各种基于 MapReduce 的海量数据处理系统应运而生。从 2004 年 Google 发表 MapReduce 论文开始,经过近 10 年的发展,基于 Hadoop 开源生态或者其它相应系统的海量数据处理已经成为业界的基本需求。
但是,很多机构在开发自己的数据处理系统时都会发现需要面临一系列的问题。从数据中获取价值需要的投入远远超过预期。常见的问题包括:
- 非常陡峭的学习曲线。刚接触这个领域的人经常会被需要学习的技术的数量砸晕。不像经过几十年发展的数据库一个系统可以解决大部分数据处理需求, Hadoop 等大数据生态里的一个系统往往在一些数据处理场景上比较擅长,另一些场景凑合能用,还有一些场景完全无法满足需求。结果就是需要好几个系统来处理不同的场景。

(来源: https://mapr.com/developercentral/lambda-architecture/ )
上图是一个典型的 lambda 架构,只是包含了批处理和流处理两种场景,就已经牵涉到至少四五种技术了,还不算每种技术的可替代选择。再加上实时查询,交互式分析,机器学习等场景,每个场景都有几种技术可以选择,每个技术涵盖的领域还有不同方式的重叠。结果就是一个业务经常需要使用四五种以上的技术才能支持好一个完整的数据处理流程。加上调研选型,需要了解的数目还要多得多。
下图是大数据领域的全景。有没有晕?

开发和运行效率低下。因为牵涉到多种系统,每种系统有自己的开发语言和工具,开发效率可想而知。而因为采用了多套系统,数据需要在各个系统之间传输,也造成了额外的开发和运行代价,数据的一致也难以保证。在很多机构,实际上一半以上的开发精力花在了数据在各个系统之间的传输上。
复杂的运维。多个系统,每个需要自己的运维,带来更高的运维代价的同时也提高了系统出问题的可能。
数据质量难以保证。数据出了问题难以跟踪解决。
最后,还有人的问题。在很多机构,由于系统的复杂性,各个子系统的支持和使用落实在不同部门负责。
了解了这些问题以后,对 Spark 从 2014 年左右开始迅速流行就比较容易理解了。Spark 在当时除了在某些场景比 Hadoop MapReduce 带来几十到上百倍的性能提升外,还提出了用一个统一的引擎支持批处理,流处理,交互式查询,机器学习等常见的数据处理场景。看过在一个 Notebook 里完成上述所有场景的 Spark 演示,对比之前的数据流程开发,对很多开发者来说不难做出选择。经过几年的发展,Spark 已经被视为可以完全取代 Hadoop 中的 MapReduce 引擎。
正在 Spark 如日中天高速发展的时候,2016 年左右 Flink 开始进入大众的视野并逐渐广为人知。为什么呢?原来在人们开始使用 Spark 之后,发现 Spark 虽然支持各种场见场景,但并不是每一种都同样好用。数据流的实时处理就是其中相对较弱的一环。Flink 凭借更优的流处理引擎,同时也支持各种处理场景,成为 Spark 的有力挑战者。
Spark 和 Flink 是怎么做到这些的,它们之间又有那些异同,下面我们来具体看一下。
二、Spark 和 Flink 的引擎技术
这一部分主要着眼于 Spark 和 Flink 引擎的架构方面,更看重架构带来的潜力和限制。现阶段的实现成熟度和局限会在后续生态部分探讨。
2.1 数据模型和处理模型
要理解 Spark 和 Flink 的 引擎特点,首先从数据模型开始。
Spark 的数据模型是弹性分布式数据集 RDD(Resilient Distributed Datasets)。 比起 MapReduce 的文件模型,RDD 是一个更抽象的模型,RDD 靠血缘(lineage) 等方式来保证可恢复性。很多时候 RDD 可以实现为分布式共享内存或者完全虚拟化(即有的中间结果 RDD 当下游处理完全在本地时可以直接优化省略掉)。这样可以省掉很多不必要的 I/O,是早期 Spark 性能优势的主要原因。
Spark 用 RDD 上的变换(算子)来描述数据处理。每个算子(如 map,filter,join)生成一个新的 RDD。所有的算子组成一个有向无环图(DAG)。Spark 比较简单地把边分为宽依赖和窄依赖。上下游数据不需要 shuffle 的即为窄依赖,可以把上下游的算子放在一个阶段(stage) 里在本地连续处理,这时上游的结果 RDD 可以 省略。下图展示了相关的基本概念。更详细的介绍在网上比较容易找到,这里就不花太多篇幅了。

Flink 的基本数据模型是数据流,及事件(Event) 的序列。数据流作为数据的基本模型可能没有表或者数据块直观熟悉,但是可以证明是完全等效的。流可以是无边界的无限流,即一般意义上的流处理。也可以是有边界的有限流,这样就是批处理。
Flink 用数据流上的变换(算子)来描述数据处理。每个算子生成一个新的数据流。在算子,DAG,和上下游算子链接(chaining) 这些方面,和 Spark 大致等价。Flink 的节点(vertex)大致相当于 Spark 的阶段(stage),划分也会和上图的 Spark DAG 基本一样。

在 DAG 的执行上,Spark 和 Flink 有一个比较显著的区别。 在 Flink 的流执行模式中,一个事件在一个节点处理完后的输出就可以发到下一个节点立即处理。这样执行引擎并不会引入额外的延迟。与之相应的,所有节点是需要同时运行的。而 Spark 的 micro batch 和一般的 batch 执行一样,处理完上游的 stage 得到输出之后才开始下游的 stage。
在 Flink 的流执行模式中,为了提高效率也可以把多个事件放在一起传输或者计算。但这完全是执行时的优化,可以在每个算子独立决定,也不用像 RDD 等批处理模型中一样和数据集边界绑定,可以做更加灵活的优化同时可以兼顾低延迟需求。
Flink 使用异步的 checkpoint 机制来达到任务状态的可恢复性,以保证处理的一致性,所以在处理的主流程上可以做到数据源和输出之间数据完全不用落盘,达到更高的性能和更低的延迟。
2.2 数据处理场景
除了批处理之外,Spark 还支持实时数据流处理,交互式查询,和机器学习,图计算等。

(来源: https://databricks.com/spark/about )
实时数据流处理和批处理主要区别就是对低延时的要求。Spark 因为 RDD 是基于内存的,可以比较容易切成较小的块来处理。如果能对这些小块处理得足够快,就能达到低延时的效果。
交互式查询场景,如果数据能全在内存,处理得足够快的话,就可以支持交互式查询。
机器学习和图计算其实是和前几种场景不同的 RDD 算子类型。Spark 提供了库来支持常用的操作,用户或者第三方库也可以自己扩展。值得一提的是,Spark 的 RDD 模型和机器学习模型训练的迭代计算非常契合,从一开始就在有的场景带来了非常显著的性能提升。
从这些可以看出来,比起 Hadoop MapReduce, Spark 本质上就是基于内存的更快的批处理。然后用足够快的批处理来实现各种场景。

(来源: https://www.slideshare.net/ParisCarbone/state-management-in-apache-flink-consistent-stateful-distributed-stream-processing )
前面说过,在 Flink 中,如果输入数据流是有边界的,就自然达到了批处理的效果。这样流和批的区别完全是逻辑上的,和处理实现独立,用户需要实现的逻辑也完全一样,应该是更干净的一种抽象。后续会在深入对比流计算方面的时候做更深入的讨论。
Flink 也提供了库来支持机器学习,图计算等场景。从这方面来说和 Spark 没有太大区别。
一个有意思的事情是用 Flink 的底层 API 可以支持只用 Flink 集群实现一些数据驱动的分布式服务。有一些公司用 Flink 集群实现了社交网络,网络爬虫等服务。这个也体现了 Flink 作为计算引擎的通用性,并得益于 Flink 内置的灵活的状态支持。
总的来说,Spark 和 Flink 都瞄准了在一个执行引擎上同时支持大多数数据处理场景,也应该都能做到这一点。主要区别就在于因为架构本身的局限在一些场景会受到限制。比较突出的地方就是 Spark Streaming 的 micro batch 执行模式。Spark 社区应该也意识到了这一点,最近在持续执行模式(continuous processing)方面开始发力。 具体情况会在后面介绍。
2.3 有状态处理 (Stateful Processing)
Flink 还有一个非常独特的地方是在引擎中引入了托管状态(managed state)。要理解托管状态,首先要从有状态处理说起。如果处理一个事件(或一条数据)的结果只跟事件本身的内容有关,称为无状态处理;反之结果还和之前处理过的事件有关,称为有状态处理。稍微复杂一点的数据处理,比如说基本的聚合,都是有状态处理。Flink 很早就认为没有好的状态支持是做不好留处理的,因此引入了 managed state 并提供了 API 接口。

一般在流处理的时候会比较关注有状态处理,但是仔细看的话批处理也是会受到影响的。比如常见的窗口聚合,如果批处理的数据时间段比窗口大,是可以不考虑状态的,用户逻辑经常会忽略这个问题。但是当批处理时间段变得比窗口小的时候,一个批的结果实际上依赖于以前处理过的批。这时,因为批处理引擎一般没有这个需求不会有很好的内置支持,维护状态就成为了用户需要解决的事情。比如窗口聚合的情况用户就要加一个中间结果表记住还没有完成的窗口的结果。这样当用户把批处理时间段变短的时候就会发现逻辑变复杂了。这是早期 Spark Streaming 用户 经常碰到的问题。直到 Structured Streaming 出来才得到缓解。
而像 Flink 这样以流处理为基本模型的引擎,因为一开始就避不开这个问题,所以引入了 managed state 来提供了一个通用的解决方案。比起用户实现的特定解决方案,不但用户开发更简单,而且能提供更好的性能。最重要的是能更好地保证处理结果的一致性。
简单来说,就是有一些內秉的数据处理逻辑,在批处理中容易被忽略或简化处理掉也能得到可用的结果,而在流处理中问题被暴露出来解决掉了。所以流计算引擎用有限流来处理批在逻辑上比较严谨,能自然达到正确性。主要做一些不同的实现来优化性能就可以了。而用更小的批来模拟流需要处理一些以前没有的问题。当计算引擎还没有通用解决方案的时候就需要用户自己解决了。类似的问题还有维表的变化(比如用户信息的更新),批处理数据的边界和迟到数据等等。
2.4 编程模型

Spark 的初衷之一就是用统一的编程模型来解决用户的各种需求。在这方面一直很下功夫。最初基于 RDD 的 API 就可以做各种类型的数据处理。后来为了简化用户开发,逐渐推出了更高层的 DataFrame(在 RDD 中加了列变成结构化数据)和 Datasets(在 DataFrame 的列上加了类型),并在 Spark 2.0 中做了整合(DataFrame = DataSet[Row])。Spark SQL 的支持也比较早就引入了。在加上各个处理类型 API 的不断改进,比如 Structured Streaming 以及和机器学习深度学习的交互,到了今天 Spark 的 API 可以说是非常好用的,也是 Spark 最强的方面之一。

Flink 的 API 也有类似的目标和发展路线。Flink 和 Spark 的核心 API 可以说是可以基本对应的。今天 Spark API 总体上更完备一下,比如说最近一两年大力投入的和机器学习深度学习的整合方面。Flink 在流处理相关的方面还是领先一些,比如对 watermark,window,trigger 的各种支持。

2.5 小结
Spark 和 Flink 都是通用的能够支持超大规模数据处理,支持各种处理类型的计算引擎。两个系统都有很多值得探讨的方面在这里没有触及,比如 SQL 的优化,和机器学习的集成等等。这里主要是试图从最基本的架构和设计方面来比较一下两个系统。因为上层的功能在一定程度上是可以互相借鉴的,有足够的投入应该都能做好。而基本的设计改变起来会伤筋动骨,更困难一些。
Spark 和 Flink 的不同执行模型带来的最大的区别应该还是在对流计算的支持上。最开始的 Spark Streaming 对流计算想得过于简单,对复杂一点的计算用起来会有不少问题。从 Spark 2.0 开始引入的 Structured Streaming 重新整理了流计算的语义,支持按事件时间处理和端到端的一致性。虽然在功能上还有不少限制,比之前已经有了长足的进步。不过 micro batch 执行方式带来的问题还是存在,特别在规模上去以后性能问题会比较突出。最近 Spark 受一些应用场景的推动,也开始开发持续执行模式。2.3 里的实验性发布还只支持简单的 map 类的操作。从最近 Spark+AI Summit 大会上的介绍来看(下图),会发展成一个和 Flink 的流处理模式比较相似的执行引擎。不过从下图来看,主要的功能都还在开发中或者待开发。对将来能做到什么程度,和 Spark 原来的 batch 执行引擎怎么结合,我们拭目以待。

三、生态和未来
3.1 概况

Spark 是最活跃的 Apache 项目之一。从 2014 年左右开始得到广泛关注。Spark 的开源社区一度达到上千的活跃贡献者。最主要推动者是 Databricks,由最初的 Spark 创造者们成立的公司。今年 6 月的 Spark+AI 峰会参加人数超过 4000。 Spark 因为在引擎方面比 MapReduce 全面占优,经过几年发展和 Hadoop 生态结合较好,已经被广泛视为 Hadoop MapReduce 引擎的取代者。

Flink 也是 Apache 顶级项目,创始者们成立了 Data Artisans。社区规模还无法和 Spark 相比。不过在业界,特别是流处理方面,有不错的口碑。在大规模流处理方面走在最前沿,也是需求最强的几个美国公司,包括 Netflix、 LinkedIn、Uber、Lyft 等,除 LinkedIn 有自己的 Samza 外,都已经采用 Flink 作为流处理引擎或者有了较大投入。
阿里集团在 Flink 社区也有较大影响力。最近 Flink 1.3 到 1.5 里都有几个重磅功能是阿里和 Data Artisans 合作或者独立开发的。阿里还有可能是世界上最大的流计算集群,也是在 Flink 的基础上开发的。
3.2 Unified Analytic platform – 包含机器学习的统一分析平台
最近的 Spark+AI 峰会上, Databricks 主打的主题是统一分析平台(Unified Analytics Platform)。三大新发布:Databricks delta、Databricks Runtime for ML 和 ML flow,都是围绕这一主题。随着近年来机器学习(包括深度学习)在数据处理中占比越来越高,可以说 Databricks 又一次把握住了时代的脉搏。
统一分析平台回应了 Spark 的初衷。经过几年的探索,对初始问题,即用户可以在一个系统里解决绝大部分大数据的需求,有了一个比较明确具体的解决方案。

不过有意思的是可以看出 Databricks 在 AI 方面策略的转变。在深度学习流行前,Spark 自带的 MLLib 功能上应该是够用的,但是可能是由于兼容性原因并没有取得预期中的广泛采用。
对深度学习的新宠 TensorFlow,Spark 曾经推出过 TensorFrames 和 Spark 引擎做了一些集成。结果应该不是很成功,可能还没有 Yahoo 从外面搭建的 TensorFlowOnSpark 影响力大。
从这次来看,Spark 转向了集成的策略。Databricks Runtime for ML 实际上就是预装了各个机器学习框架,然后支持在 Spark 任务里启动一个比如 TensorFlow 自己的集群。Spark 引擎方面做的主要改进就是 gang scheduling,即支持一次申请多个 executor 以便 TensorFlow 集群能正常启动。
MLFlow 更是和 Spark 引擎无关。作为一个工作流工具,MLFlow 的目标是帮助数据科学家提高工作效率。主要功能是以项目为单位记录和管理所做的机器学习试验,并支持分享。设计要点是可重复试验,以及对各种工具的灵活易用的支持。看起来 Spark 暂时在作为 AI 引擎方面可能没什么大动作了。
Flink 的目标其实和 Spark 很相似。包含 AI 的统一平台也是 Flink 的发展方向。Flink 从技术上也是可以支持较好的机器学习集成和整条链路的,而且有一些大规模线上学习的使用实例。不过看起来在现阶段 Flink 这方面的平台化还没有 Spark 成熟。值得一提的是 Flink 由于流处理引擎的优势,在线上学习方面可能能支持得更好一些。
3.3 数据使用者
产品和生态归根结底是要解决大数据使用者的问题,从数据中产生价值。了解数据的使用者和他们的需求可以帮助我们在在讨论生态的各方面时有一个比较清晰的脉络。
数据相关的工作者大致可以分为以下角色。实际情况中一个组织里很可能几个角色在人员上是重合的。各个角色也没有公认的定义和明确的界限。

数据采集:在产品和系统中合适的地方产生或收集数据发送到数据平台。
平台:提供数据导入,存储,计算的环境和工具等等。
数据工程师:使用数据平台把原始数据加工成可以供后续高效使用的数据集。把分析师和数据科学家创建的指标和模型等等生产化成为高效可靠的的自动处理。
数据分析师和数据科学家(关于这两者的异同有很多讨论。感兴趣的可以自行搜索。 https://www.jianshu.com/p/cfd94d9e4466 这里的译文可以提供一个视角):为数据赋予意义,发现内含的价值。 下文再不特别区分的地方统称为数据分析。
产品经理,管理和决策层:根据以上产生的数据调整产品和组织行为。
这些构成了一个完整的环。上面的顺序是数据流动的方向,而需求的驱动是反过来的方向。
本文所说的 Spark 和 Flink 的生态主要是对应到数据平台这一层。直接面向的用户主要是数据工程师、数据分析师和数据科学家。好的生态能够大大简化数据平台和数据工程师的工作,并使得数据分析师和数据科学家更加自主化同时提高效率。
3.4 开发环境
API
从 API 上来看,Spark 和 Flink 提供的功能领域大致相当。当然具体看各个方向支持的程度会有差异。总体来看 Spark 的 API 经过几轮迭代,在易用性,特别是机器学习的集成方面,更强一些。Flink 在流计算方面更成熟一些。

支持的语言也大致相当。Spark 发展的时间长一些还是有优势,特别是数据分析常用的 Python 和 R。

Connectors
有了 API,再有数据就可以开工了。Spark 和 Flink 都能对接大部分比较常用的系统。如果暂时还没有支持的,也都能比较好地支持自己写一个 connector。

https://databricks.com/spark/about

https://www.slideshare.net/chobeat/data-intensive-applications-with-apache-flink
3.5 集成开发工具
这方面数据工程师和数据分析的需求有一些不同。
数据分析的工作性质比较偏探索性,更强调交互性和分享。Notebook 能比较好地满足这些需求,是比较理想的开发工具,用来做演示效果也相当不错。比较流行的 Notebook 有 Apache Zeppelin,Jupyter 等。Databricks 更是自己开发了 Databricks Notebook 并将之作为服务的主要入口。Zeppelin 支持 Spark 和 Flink,Jupyter 还只支持 Spark。
数据工程师的工作更倾向于把比较确定的数据处理生产化,能快速把代码写出来是一方面。另外还有项目管理,版本管理,测试,配置,调试,部署,监控等等工作,需求和传统的集成开发工具比较相似。 还经常出现需要复用已有的业务逻辑代码库的情况。Notebook 对其中一些需求并不能很好地满足。比较理想的开发工具可能是类似 IntelliJ 加上 Spark/Flink 插件,再加上一些插件能直接提交任务到集群并进行调试,并对接 Apache Oozie 之类的工作流管理等等。在开源社区还没有见到能把这些集成到一起的。在商业产品中倒是见过一些比较接近的。Spark 和 Flink 在这方面差不多。
3.6 运行环境
部署模式 / 集群管理 / 开源闭源
应用开发完后要提交到运行环境。Spark 和 Flink 都支持各种主流的部署环境,在这方面都算做得比较好的。

3.7 企业级平台
既然 Spark 和 Flink 都支持各种部署方式,那一个企业是否可以使用开源代码快速搭建一个支持 Spark 或者 Flink 的平台呢?
这个要看想要达到什么效果了。最简单的模式可能是给每个任务起一个独占集群,或着给小团队一个独立集群。这个确实可以很快做到,但是用户多了以后,统一运维的成本可能太高,需要用户参与运维。还有一个缺点是资源分配固定,而负载会有变化,导致资源利用率上不去。比较理想的是多租户的共享大集群,可以提高运维效率的同时最大限度地提高资源利用率。而这就需要一系列的工作,比如不同的作业提交方式,数据安全与隔离等等。对一些企业来说,可能利用托管服务(包括云服务)是一种值得考虑的开始方式。
3.8 社区
Spark 社区在规模和活跃程度上都是领先的,毕竟多了几年发展时间。而且作为一个德国公司,Data Artisans 想在美国扩大影响力要更难一些。不过 Flink 社区也有一批稳定的支持者,达到了可持续发展的规模。
在中国情况可能会不一样一些。比起美国公司,中国公司做事情速度更快,更愿意尝试新技术。中国的一些创新场景也对实时性有更高的需求。这些都对 Flink 更友好一些。
近期 Flink 的中国社区有一系列动作,是了解 Flink 的好机会。
Spark 的中文文档在 http://www.apachecn.org/bigdata/spark/27.html 。
Flink 的中文社区在 http://flink-china.org/ 。
另外,今年年底 Flink 中文社区也会在北京举办 Flink Forward China 大会,感兴趣的朋友可以关注。
3.9 未来发展趋势
近两年一个明显的趋势就是机器学习在数据处理中的比重增长。Spark 和 Flink 都能支持在一个系统中做机器学习和其它数据处理。谁能做得更好就能掌握先机。
另一个可能没有那么明显的趋势是,随着 IOT 的增长以及计算资源和网络的持续发展,实时处理需求会越来越多。现在其实真正对低延迟有很高追求的业务并没有那么多,所以每一次流计算新技术的出现都能看到那几家公司的身影。随着新应用场景的出现和竞争环境的发展,实时处理可能会变得越来越重要。Flink 现在在这方面是领先的,如果发挥得好可以成为核心优势。
还有一点值得一提的是,因为用户不想锁定供应商,担心持续的支持等原因,是否开源已经成为用户选择数据产品的一个重要考量。闭源产品如果没有决定性优势会越来越难和基于开源技术的产品竞争。
四、总结
Spark 和 Flink 都是通用的开源大规模处理引擎,目标是在一个系统中支持所有的数据处理以带来效能的提升。两者都有相对比较成熟的生态系统。是下一代大数据引擎最有力的竞争者。Spark 的生态总体更完善一些,在机器学习的集成和易用性上暂时领先。Flink 在流计算上有明显优势,核心架构和模型也更透彻和灵活一些。在易用性方面两者也都还有一些地方有较大的改进空间。接下来谁能尽快补上短板发挥强项就有更多的机会。
作者介绍: 王海涛,曾经在微软的 SQL Server 和大数据平台组工作多年。带领团队建立了微软对内的 Spark 服务,主打 Spark Streaming。去年加入阿里实时计算部门,参与改进阿里基于 Apache Flink 的 Blink 平台。
原文链接: