信息技术和互联网技术的发展,带来了全球数据的爆发式增长。超大规模的数据计算问题成为各大科技公司急需解决的世界级难题。2004年谷歌的MapReduce论文给出了一个可行的大数据计算模型,给大数据并行处理带来了巨大的革命性影响。随后大数据计算取得了飞速发展,针对更细化的大数据应用场景,各种优秀的大数据引擎不断涌现,呈现出百花齐放百家争鸣的景象。在国外一些社区,很多人将大数据的计算引擎分成了四代(如下图所示)。
第一代:MapReduce
大数据计算之所以困难,是因为数据规模超出了单机硬件的物理极限。面对TB级、PB级甚至EB级以上的数据规模,单机是无能为力的(延伸阅读《分布式系统缘起及理论》)。MapReduce采用分治策略,将大规模数据集拆分多个独立分片,这些分片可在分布式计算节点上并行计算,最后对各个计算结果进行规约完成整个计算任务输出。MapReduce用无限可扩展的机器来对抗无限增长的数据规模,在理论上解决了大规模数据的计算问题。
MapReduce虽然解决了大数据的能计算问题,但它的速度不够快,一个MapReduce任务通常需要秒级别甚至分钟级别才能跑完。这个速度对于离线计算场景还能接受,但对于实时计算场景显然太慢了。于是为了解决大数据的快计算问题,工业界又开始了对大数据计算引擎的设计探索。
第二代:任务的DAG(Tez, Ozzie)
第二代计算引擎本质上没有引入新的计算思想,主要是在工程设计上对MapReduce的任务调度过程作了优化。
MapReduce将一个Job(计算任务)分解为Map和Reduce两个阶段。对于复杂算法来说,通过一个MR过程无法实现,需要拆分成多个Job串联运行。但是在MR框架里,Job是最小的调度单位,不同Job彼此独立运行。后一个Job必须等前一个Job跑完才能开始。单个Job本身运行就慢,多个Job串联跑完就更慢了。在编写算法代码时,改一个参数要等几分钟、几十分钟才能看到运行结果,这种开发效率没有一个程序员可以接受。
那有没有办法提供多任务的执行效率呢?第二代计算引擎从这个角度做了工程优化。核心思想是对Job做进一步细化拆分,基于DAG(Directed Acyclic Graph, 有向无环图)工作流对Job调度进行优化,来提高多Job的运行效率。典型代表是Tez和Oozie。
Tez最早是Hortonworks开发的,后捐献给Apache开源。官网地址:https://tez.apache.org/ 。官网介绍如下:
The Apache TEZ® project is aimed at building an application framework which allows for a complex directed-acyclic-graph of tasks for processing data. It is currently built atop Apache Hadoop YARN.
Tez将MapReduce做了进一步拆分:Map拆成Input, Processor, Sort, Merger和Output;Reduce拆成Input, Shuffle, Sort, Merger, Processor和Output。拆分后的单元可以任意组合,组装成大的DAG作业。现在Tez已被Hortonworks用于Hive和Pig任务执行引擎的优化(如下图所示),经测试,性能提升约100倍。
Oozie是Cloudera公司贡献给Apache的基于工作流引擎的开源框架,是用来管理Hadoop作业的工作流调度引擎。与Tez不同,Ozzie没有对MR做细化拆分,只是通过DAG工作流来优化Hadoop上的作业调度。Ozzie抽象了控制流节点(Control Flow Nodes)和动作节点(Action Nodes)。动作节点可以是MR任务,也可以是其他脚本任务,比如shell脚本、Pig脚本。通过灵活的控制流组装,Ozzie可以实现多种脚本任务的高效调度。Oozie的官网地址:http://oozie.apache.org/ 。官网介绍如下:
Oozie is a workflow scheduler system to manage Apache Hadoop jobs. Oozie Workflow jobs are Directed Acyclical Graphs (DAGs) of actions.
第三代:Spark
第二代计算引擎以提高多任务运行效率为主要切入点,虽然对Job作了更细粒度的拆分,但是单个Job的数据处理过程的本质不变,依然是基于磁盘IO的批处理方式。Spark使用内存计算来代替磁盘IO,内存计算速度比磁盘IO速度要快4~5个数量级,它将单Job的运行时长从秒、分钟级别一下子降低到毫秒级别。这个速度量级开辟了大数据实时计算的应用场景。针对实时场景,Spark采用微批(micro-batch)方式模拟实现了流处理过程。(关于实时计算的延伸阅读《大数据平台架构及主流技术栈》)
Spark最早诞生于加州大学伯克利分校的AMPLab实验室,2013年开源给Apache进入高速发展期,迅速成为Apache的*项目(官网地址 http://spark.apache.org/ )。发展至今Spark已包含了大数据领域常见的各种计算框架:
-
Spark Core用于离线计算
-
Spark SQL用于交互式查询
-
Spark Streaming用于实时流计算
-
Spark MLlib用于机器学习
-
Spark GraphX用于图计算
传统的MapReduce中每个过程都需要磁盘IO,数据流无法循环使用。Spark抽象了RDD(Resilient Distributed Dataset, 弹性分布式数据集)数据模型作为通用计算单元。RDD是存储在内存中的数据结构,在并行环境中可以被重复使用,减少了中间数据的磁盘IO操作。RDD之间存在依赖关系(使用DAG描述),当某一部分丢失或者出错,只需根据血缘关系进行局部计算来重建。MapReduce的话容错需要重新计算,成本较高。
和Tez一样,Spark也细化了对数据的操作,在Spark中称为算子。Spark算子分为两类:Transform和Action。Transform算子是一种延迟性操作,也就是把一个RDD转换成另外一个RDD而不是马上执行,不会提交job。常用的有:map,flatmap,join,groupBykey等。Action算子会对RDD 计算出一个结果,并把结果返回到驱动器程序中,或把结果存储到外部存储系统(如 HDFS)中。每个action都会提交一个job。常用的action有reduce,collect,count,take等。Spark的完整计算过程也是用DAG来构建,DAG中的点是RDD,线是算子。通过灵活的组装,可以实现复杂的算法过程。
第四代:Flink
Spark虽然也支持流计算,但它是用微批(micro-batch)来模拟流实现的,本质上还是批处理,实时处理速度在百毫秒到秒这个级别,这个速度只能满足近实时的统计分析场景。对于实时性要求更高的连续流场景,Spark就不太适用了。这类场景就需要使用第四代计算引擎Flink了。
Flink诞生于欧洲的一个大数据研究项目,原名 StratoSphere。该项目是柏林工业大学的一个研究性项目,早期专注于批计算。2014 年,StratoSphere 项目中的核心成员孵化出 Flink,并在同年将 Flink 捐赠 Apache,后来成为 Apache 的*大数据项目。其官方地址是https://flink.apache.org/ 。官网介绍如下:
Apache Flink is a framework and distributed processing engine for stateful computations over unbounded and bounded data streams. Flink has been designed to run in all common cluster environments, perform computations at in-memory speed and at any scale.
Flink是面向连续流设计的计算引擎。在Flink中,一切都是流,数据流是Flink基本处理模型。Flink从设计之初秉持了一个观点:批是流的特例(批是一种有边界的数据流),它的批处理也是通过流来模拟实现的。
为了描述数据处理过程,Flink在数据流上使用操作符,每个操作符生成一个新的数据流。从操作符、DAG和上下游操作符的连接来看,整体模型和Spark大体相同。Flink的定点相当于Spark中的stage,将操作符划分为定点的过程和Spark DAG中划分为stage的过程基本相同。但是在DAG执行上,Flink和Spark有一个显著的区别:在Flink的流执行模式中,事件在一个节点上处理后的输出可以发送到下一个节点进行即时处理,这样,执行引擎就不会有任何的延迟。相应地,所有的节点都需要同时运行。相反,Spark的微批执行和其正常的批量执行没有区别,因为只有在上游阶段完成微批量处理之后,下游阶段才开始处理其输出。这是Spark实时性不如Flink的一个根本原因。
除了流批计算,Flink还有一些高级功能,比如精密的状态管理、事件时间支持以及精确一次(Exactly-Once)的状态一致性保障等。
总结
虽然业内把大数据计算引擎分为四代,但他们并不是针对同一个场景的技术更新换代,而是各有各的使用场景,新代计算引擎并不能完全取代旧的计算引擎。比如基于内存计算的Spark,虽然速度快,但是内存资源比磁盘资源成本更高,对于离线计算场景秒级别分钟级别的计算速度完全可以接受,为了节省资源,还是会选择MapReduce引擎。
延伸阅读