一、传统数据处理架构
1. 事务处理
(1)简介:存算分离,实时与关系型数据库进行交互,并将处理结果响应给用户。
(2)优点:实时性高。
(3)缺点:能够同时处理的数据量有限,并发能力不足。
2. 分析处理
(1)简介:对业务数据库的数据进行ETL清洗、整合、提取,统一放到数据仓库中去,然后用数据分析的引擎进行查询分析处理,最后将结果生成报表或进行Ad Hoc(即席查询,是指用户根据自己的需求,灵活的选择查询条件,系统能够根据用户的选择生成相应的统计报表)。
(2)优点:离线分析处理、分布式处理、高吞吐量、可应对高并发。
(3)缺点:实时性不高、延迟高。
二、流处理框架的演进
流处理框架的演进过程大致可以分为四个阶段,分别是:① 实时阶段(如Storm);② Lambda架构阶段(兼顾实时性和准确性,Hadoop+Storm);③ 微批处理阶段(引入状态和exactly-once语义,如Spark Streaming);④ 全能阶段(如Flink)。
1. 实时阶段
在开源世界里,Apache Storm 项目(以下简称 Storm)是流处理先锋。Storm最早由Nathan Marz和创业公司BackType(后来被Twitter收购)的一个团队开发,后来才被Apache软件基金会接纳。
Storm提供了低延迟的流处理,但是它为实时性付出了一些代价:很难实现高吞吐
。Storm的流处理是乱序
的,不能保证结果是正确的。换句话说,它并不能保证exactly-once
,只能保证at-least-once。
2. Lambda架构阶段
对低成本规模化的需求促使人们开始使用分布式文件系统,例如HDFS和基于批量数据的计算系统(MapReduce作业)。但是这种系统很难做到低延迟
。
用 Storm 开发的实时流处理技术可以帮助解决延迟性的问题,但并不完美。其中的一个原因是,Storm 不支持 exactly-once
语义, 因此不能保证状态数据的正确性
,另外它也不支持基于事件时间
的处理。有以上需求的用户不得不在自己的应用程序代码中加入这些功能。
这时,一种混合分析的方法出现了——Lambda架构,它将上述两个方案结合起来,兼顾了流处理的实时性
和批处理的准确性
。Lambda架构同样是由Storm的作者Nathan Marz提出的一个实时大数据处理框架,是其根据多年进行分布式大数据系统的经验总结提炼而成。
Lambda架构通过批量MapReduce作业提供了虽有些延迟但是结果准确的计算,同时通过Storm将最新数据的计算结果初步展示出来。如上图所示,Lambda架构分批处理层和流处理层两套处理,流处理会实时地让用户得到一个近似正确的结果存入Real-time View,批处理会将数据进行积攒,到了一定批量后执行计算得到一个精确的结果,并将其存入Batch View。由应用程序判断什么时候拿Real-time View中的近似正确结果,什么时候拿Batch View中的精确结果。这样用户侧的感受是,发出请求后,会立即得到一个近似正确的结果,过一段时间后再看,会得到百分百正确的结果。
Lambda 架构是构建大数据应用程序的一种很有效的框架,但它还不够好:
(1)基于MapReduce和HDFS的Lambda系统有一个长达数小时的时间窗口,在这个窗口内,实时处理的不准确结果
会一直存在。
(2)Lambda 架构需要在两个不同的 API(application programming interface,应用程序编程接口)中对同样的业务逻辑进行两次编程
:一次为批量计算的系统,一次为流式计算的系统。针对同一个业务问题产生了两个代码库,各有不同的漏洞。这种系统实际上非常难维护
。
3. 微批处理阶段
Lambda架构虽然兼顾了实时性和准确性,但是对于有状态
的流处理应用却束手无策(因为此时的Storm框架并未实现状态管理)。状态数据是流处理框架在处理流数据时产生的,如计数值、最大值、最小值、当前Kafka消费偏移量等。准确处理状态对于计算结果的一致性至关重要。在故障或中断之后能够继续准确地更新状态是容错
的关键。
在低延迟和高吞吐的流处理系统中维持良好的容错性是非常困难的,但是为了得到有保障的准确状态,人们想出了一种替代方法:将流数据看作是一种特殊的批数据,分割成一系列微小的批量作业
(即微批处理作业
)。如果分割得足够小,计算就几乎可以实现真正的实时处理。因为存在延迟,所以不可能做到完全实时,但是每个简单的应用程序都可以实现秒级的延迟。这就是在 Spark 批处理引擎上运行的 Apache Spark Streaming所使用的方法。
更重要的是,使用微批处理方法,可以实现 exactly-once
语义,从而保障状态的一致性。如果一个微批处理作业失败了,它可以重新运行,保证同一个微批处理作业的处理结果仅输出一次。这比连续的流处理方法更容易。Storm Trident 是对 Storm 的延伸,它的底层流处理引擎就是基于微批处理方法来进行计算的,从而实现了 exactly-once 语义。
微批处理需要先缓存一批数据,然后再统一处理,用牺牲实时性的代价换来高吞吐性能
。用这种方法的计算有着糟糕的用户体验,尤其是那些对延迟比较敏感的作业,而且人们需要在写业务代码时花费大量精力来提升性能。
为了实现理想的功能,人们继续改进已有的处理器(比如 Storm Trident 的开发初衷就是试图克服 Storm 的局限性)。当已有的处理器不能满足需求时,产生的各种后果则必须由应用程序开发人员面对和解决
。以微批处理方法为例,人们往往期望根据实际情况分割事件数据,而处理器只能根据批量作业时间(恢复间隔)的倍数进行分割。当灵活性和表现力都缺乏的时候,开发速度变慢,运维成本变高。
4. 全能阶段
Storm 实现了低延迟,但是在作者撰写本书时还做不到高吞吐,也不能在故障发生时准确地处理计算状态;Spark Streaming 通过采用微批处理方法实现了高吞吐和容错性,但是牺牲了低延迟和实时处理能力,也不能使窗口与事件时间相匹配,并且表现力欠佳。
Flink框架可以避免上述弊端,并且拥有所需的诸多功能,如下图所示。与 Storm 和 Spark Streaming 类似,其他流处理技术同样可以提供一些有用的功能,但是没有一个像 Flink 那样功能如此齐全。举例来说,Apache Samza(以下简称 Samza)是早期的一个开源流处理器,它不仅没能实现 exactly-once 语义,而且只能提供底层的 API;同样,Apache Apex 提供了与 Flink 相同的一些功能,但不全面(比如只提供底层的 API,不支持事件时间,也不支持批量计算)。这些项目没有一个能和 Flink 在开源社区的规模上相提并论。
参考:
[1] 埃伦·弗里德曼, 科斯塔斯·宙马斯. Flink基础教程[M]. 1. 北京:人民邮电出版社, 2018 :6-9.
[2] 流式处理框架的演变