流处理的前世今生(四)真流处理Apache Flink的登基之路

B站影视 韩国电影 2025-09-29 03:32 1

摘要:Apache Flink代表了统一流处理和批处理的范式转变,实现了具有Exactly Once语义的真正流处理,同时保持亚秒级延迟和线性可扩展性。通过架构创新,包括基于信用的流量控制、复杂的状态管理和流优先的设计理念,Flink已成为企业级实时数据平台的事实标

Apache Flink代表了统一流处理和批处理的范式转变,实现了具有Exactly Once语义的真正流处理,同时保持亚秒级延迟和线性可扩展性。通过架构创新,包括基于信用的流量控制、复杂的状态管理和流优先的设计理念,Flink已成为企业级实时数据平台的事实标准,在阿里巴巴、Netflix和Uber等公司每日处理数万亿事件。

我们之前提到,大数据的核心是要解决两个问题,存储和计算。在流数据处理也不例外。流式数据的存储被一个叫Apache Kafka的开源项目所解决。Kafka本质上解决了如何在分布式环境下高效存储和传输大规模流式数据,这一根本问题,将传统的"消息传递"升级为"流式数据平台",为现代实时数据架构奠定了基础。它不仅是消息队列,更是流式数据的持久化存储层和分发中心。

而Flink则是着眼解决流式数据计算的难题。但是流式数据计算为什么这么难呢?

流式计算本质上是要在数据持续流动、系统可能故障、时间概念模糊的环境下,实现准确、及时、可靠的计算结果。这种"在运动中解决问题"的特性,使得流式计算比批处理复杂了一个数量级。

这些困难点包含:

时间复杂性问题, 事件时间 vs 处理时间:数据产生时间、到达系统时间、被处理时间三者不一致乱序数据:网络延迟导致后发生的事件先到达水印机制:如何判断某个时间窗口的数据已经"完整"?无界数据流的挑战,无法等待全量数据:批处理可以看到全部数据再计算,流处理必须在数据到达时立即处理增量计算:如何基于部分数据得出正确结果?状态管理:需要维护历史状态用于后续计算,状态可能无限增长容错与一致性难题,精确一次(Exactly Once)语义:系统故障时如何保证数据既不丢失也不重复处理?分布式快照:在数据持续流动中创建一致性检查点状态恢复:故障恢复时如何准确恢复到之前的计算状态?实时性与准确性权衡 ,低延迟要求毫秒级响应需求 vs 复杂计算逻辑背压处理:上游数据过快时如何避免系统崩溃?资源调度:动态负载下的计算资源分配窗口计算的复杂性,数据分组与聚合滑动窗口、滚动窗口、会话窗口等不同语义迟到数据处理:窗口已关闭后到达的数据如何处理?窗口触发:基于时间、数据量还是自定义逻辑?

而Flink大概是第一个系统性的解决这些流式数据处理问题的开源项目。

在介绍Flink的技术架构之前,我们先来看看Flink这个项目发展的历史。

Apache Flink最初于2010年起源于德国柏林工业大学的Stratosphere研究项目,由Volker Markl教授领导的数据库系统和信息管理小组开发。这个学术项目旨在构建下一代大数据分析平台,重点关注内存计算和迭代算法优化。

2014年,Stratosphere项目进入Apache软件基金会孵化器,并正式更名为Apache Flink(德语中"flink"意为"快速、敏捷")。2014年12月,Flink成为Apache顶级项目。

Flink的核心开发者们于2014年在德国柏林创立了Data Artisans公司,包括:Stephan Ewen(现Flink PMC主席),Kostas Tzoumas,Fabian Hueske,Aljoscha Krettek等, Data Artisans专注于为Flink提供企业级支持、咨询服务和托管平台。公司获得了总计约1400万美元的融资。

2019年1月,阿里巴巴以约9000万欧元(约1.03亿美元)收购了Data Artisans,这标志着中国科技巨头对开源流处理技术的重大投资。收购后,核心团队继续维护开源Flink项目,同时为阿里云开发企业级Flink服务。

2021年,原Data Artisans的核心团队从阿里巴巴独立出来,重新创立了Ververica公司。这次独立主要是为了:

重新专注于开源Flink生态面向全球市场提供Flink企业服务摆脱大厂内部限制,推动Flink创新

Ververica继承了原Data Artisans的技术积累和客户资源,继续提供Ververica Platform云原生流处理平台。

2021,与Ververica几乎同期,Flink社区的资深贡献者和前Data Artisans员工Robert Metzger,创办了Immerok,并于2023年5月被Confluent以约约1.75亿美元收购。

而Confluent正是构建在Apache Kafka之上,统治流式数据存储市场的行业大佬,在纳入Immerok的Flink团队之后,可以正式宣布,流式数据处理的两大问题方案,都已经纳入Confluent麾下。

好了,现在让我们回到Flink本身,来看看它的设计和架构。

Flink被称为是真流处理,那么何为真?谁又是假的呢?

其实这里只要就是针对的Spark的微批,虽然我说过,当你的微批足够小的时候,他和流没有区别。但是在一般以一下,这个微批都不可能非常小。

微批处理的"假流":

将连续数据流切分为小批次(微批),每个批次单独处理数据到达 → 等待批次时间窗口 → 批量处理 → 输出结果本质上仍是批处理思维,只是批次变小了

Flink的"真流":

逐条处理:数据一条一条地流过处理管道,无需等待数据到达 → 立即处理 → 立即输出纯事件驱动,没有人为的批次边界

Flink中数据以StreamRecord形式在算子间流动,无需序列化成批次,直接在JVM堆内传递,多个算子同时处理不同阶段的数据。每个事件都可能触发状态更新,状态变化连续可观测。Flink的分布式快照不依赖批次边界,可以在任意时刻创建全局一致的状态快照。

Flink的高级时间语义区分了事件时间(事件发生时间)、处理时间(系统处理时间)和摄入时间(事件进入Flink的时间)。水位线机制(Watermark注意不要错误的翻译成水印,跟水印没半毛钱关系)通过表示事件时间推进的特殊时间戳来协调并行流的进度,实现对乱序和延迟到达数据的精密处理。

Flink通过多个精密组件的协调实现端到端精确一次处理(exactly once)。基于Chandy-Lamport并具有Flink特定优化的分布式快照算法,使用流经数据流的检查点屏障来确保一致的快照。异步检查点在持久化状态的同时防止阻塞数据处理,增量检查点仅存储自上次快照以来的变更,适用于大状态应用程序。对于外部系统,两阶段提交协议原子性地提交整个管道的变更,即使使用外部接收器也能保证精确一次语义。

我们简单看看这个算法:

每个分布式系统都有许多进程运行在不同的物理服务器上。这些进程通过通信通道使用文本消息相互通信。这些进程既没有共享内存也没有公共的物理时钟,这使得确定瞬时全局状态的过程变得困难。

一个进程可以在给定时间记录自己的本地状态,但正在传输中的消息(正在传递途中的消息)不会包含在记录的状态中,因此在传输中的消息被交付后,系统的实际状态会变得不正确。

ChandyLamport(注意他们是两个人是最早提出算法来捕获分布式系统一致全局状态的人。所提出算法背后的主要思想是,如果我们知道一个进程发送的所有消息都已被另一个进程接收,那么我们就可以记录系统的全局状态。

分布式系统中的任何进程都可以使用称为MARKER的特殊消息来启动这个全局状态记录算法。这个标记遍历分布式系统中的所有通信通道,并使每个进程记录自己的状态。最终,整个系统的状态(全局状态)被记录下来。该算法不会干扰进程的正常执行。

算法的假设:

分布式系统中有有限数量的进程,它们不共享内存和时钟。有有限数量的通信通道,它们是单向的且遵循FIFO顺序。系统中任意两个进程之间都存在通信路径在一个通道上,消息的接收顺序与发送顺序相同。

算法:

进程P的标记发送规则:进程P记录自己的本地状态对于来自进程P的每个出站通道CP在沿着C发送任何其他消息之前,先沿着C发送标记。(**注意:**进程Q将在其入站通道C1上收到此标记。)进程Q的标记接收规则:如果进程Q尚未记录自己的本地状态,则将入站通道C1的状态记录为空序列或null。记录入站通道C1的状态后,进程Q遵循标记发送规则如果进程Q已经记录了其状态将入站通道C1的状态记录为在Q的状态被记录之后且在Q从进程P沿着C1接收到标记之前,沿着通道C1接收到的消息序列。

大家看不懂也没有关系,总之应用了这个算法,Flink实现了数据处理的Exactly Once!每一条数据保证会被处理,且仅处理一次。

Flink于1.5版本引入基于信用的流量控制系统。该机制通过每个通道的专用独占缓冲区和用于处理流量突发的共享浮动缓冲池来防止缓冲区溢出并实现精确的背压传播。与传统系统中背压影响所有复用连接不同,Flink的方法提供通道特定的背压,避免级联故障。背压处理性能包括缓冲区去膨胀以最小化传输中的数据量、并行度调优以实现最优任务分布,以及对持续背压条件的自动扩展响应。系统即使在背压情况下也能维持检查点性能,确保在不同负载条件下的系统行为一致性。

下面再看看Flink的架构:

Flink核心分布式架构围绕三个主要组件展开精密协调。JobManager作为主协调器,包含专门的子组件:Dispatcher提供REST接口和作业提交,ResourceManager通过任务槽处理集群资源分配,JobMaster协调分布式执行包括检查点和故障恢复。TaskManager执行实际的数据流操作,具有先进的内部组织结构,包括用于资源调度的任务槽、带有网络缓冲区的自定义内存管理,以及通过RocksDB集成的堆外状态存储。

Flink的执行图转换管道通过多个阶段优化性能。初始的StreamGraph代表来自DataStream API的逻辑操作,通过算子链和资源优化转换为JobGraph,然后扩展为ExecutionGraph用于物理并行执行,最终部署为可用槽(Slot)上的具体任务。这种精密的转换实现了算子链优化,连续的算子在同一线程中协同定位,大幅减少算子间通信开销。

source https://substackcdn.com/image/fetch/$s_!rYIV!,f_auto,q_auto:good,fl_progressive:steep/https://substack-post-media.s3.amazonaws.com/public/images/fe3c3766-cdf6-4e68-b000-cc0c32b0188b_2307x2225.png

相比Apache Spark Streaming,Flink的流式架构实现了25-85%更高的可持续吞吐量和显著更低的延迟。

Apache Flink代表了当前流处理框架架构的巅峰之作,结合了真正的流处理能力与复杂的状态管理、精确一次处理保证,以及针对互联网规模工作负载的经过验证的可扩展性。其流优先的理念、先进的网络机制和全面的生态系统集成,使其成为需要低时延有状态实时应用的最优选择。

当然,Flink也并非完美,他也面临着一些挑战和问题:

陡峭的学习曲线:需要深度理解流处理概念(事件时间、水印、窗口等)状态管理、检查点配置需要专业知识相比Kafka Streams等轻量级方案,入门门槛高运维复杂:集群管理、资源调优需要专业运维团队内存管理复杂,需要精细调节堆内外内存分配故障排查困难,分布式状态调试挑战大资源消耗问题,内存开销大:RocksDB状态后端需要大量内存和快速SSDJVM调优复杂,GC压力在大状态场景下明显相比无状态处理框架,资源需求更高部署成本高:需要专门的集群资源,不适合轻量级应用高可用部署需要至少3个JobManager节点存储成本:检查点和保存点需要持久化存储工具链不足:可视化监控工具相对简单调试工具不如传统批处理框架成熟IDE集成和本地开发体验有待改善特定场景,尤其是小规模应霞:对于简单的ETL任务,Flink过于"重型"冷启动时间较长,不适合短期任务批处理性能:虽然支持批处理,但在纯批处理场景下性能不如Spark机器学习生态不如Spark MLlib成熟大规模历史数据处理效率相对较低

这些无疑给Flink自己和其他诸多的挑战者机会。

这里有两个源自Flink的开源项目值得大家去关注一下。

Apache Paimon - 流式湖仓一体化存储, 原名Flink Table Store,是一个流式数据湖存储项目,专为流批一体化场景设计的新一代湖仓存储引擎。

解决的核心问题:

传统数据湖的实时性痛点:传统数据湖(如基于Parquet的存储)主要为批处理优化,流式写入性能差小文件问题:频繁的流式写入产生大量小文件,影响查询性能数据新鲜度:从写入到可查询存在较长延迟流批存储的统一挑战:需要维护两套存储系统:流式存储(如Kafka)+ 批式存储(如Hive)数据一致性:流批两条链路的数据同步复杂成本问题:重复存储导致成本高昂

Apache Fluss - 流式存储系统,是一个专为流处理优化的分布式存储系统,提供类似Kafka但功能更强的流式数据存储能力。

解决的核心问题:

Kafka的功能局限性:查询能力弱:只支持顺序消费,缺乏随机查询存储模型简单:基于日志,不支持复杂数据操作状态存储分离:流处理的状态需要额外存储系统流处理的存储需求:低延迟读写:支持毫秒级的数据存取状态查询:支持流处理中的状态查询需求水平扩展:支持PB级数据存储

总之,新王登基,但是江山仍存隐患。

来源:闻数起舞

相关推荐