Flink原理(一)——基础架构

本文深入解析Apache Flink的架构设计,包括JobManager和TaskManager的角色与职责,以及它们如何协同工作进行任务调度和资源分配。同时,介绍了Flink的批/流一体化处理能力,以及taskSlot的工作机制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Flink系列博客,基于Flink1.6,打算分为三部分:原理、源码、实例以及API使用分析,后期等系列博客完成后再弄一个目录。

该系列博客是我自己学习过程中的一些理解,若有不正确、不准确的地方欢迎大伙留言分享。文中引用均已标注,若有侵权,请联系我,立马删除!


 

1、前言

  在讲Flink基本结构之前,我们的先知道Flink是什么?中文官网上的解释是:Apache Flink 是一个框架和分布式处理引擎,用于在无边界和有边界数据流上进行有状态的计算[1]。关于无边界和有边界数据流的定义可以参考官网上的解释,从其解释上可以了解到Flink是一个框架和计算引擎,是用来处理数据流的。处理数据流并不意味着Flink仅仅能用于我们通常所说的流处理系统中,这里数据流主要是为了说明Flink处理数据的方式,是以流的形式进行的。其实不仅流处理,Flink也可以做到批处理,即Flink可以实现批/流一体化,至于如何实现的,这里仅提及相关概念,后续博客会慢慢道来。

2、Flink基本架构

  2.1、Flink的基本架构图[2]:

  从图中可知,Flink整个系统主要由两个组件组成:JobManager、TaskManager组件,其架构是遵循主-从设计原则的,JobManager为master结点、TaskManager为Slave结点(也称work结点),组件之间的通信是借助Akka Framework。

  1)JobManager:负责整个Flink集群任务的调度和资源分配。从client获取提交的任务后,JobManager根据TaskManager中资源(TaskSlots)使用的情况,分配资源并命令TaskManager启动任务。在这个过程中,JobManager会触发checkpoint操作,TaskManager执行checkpoint操作,其中所有的checkpoint协调的过程都在JobManager中完成的。此外,若是任务失败了,也由JobManager协调失败任务的恢复。

  2)TaskManager:负责具体的任务执行和结点上资源申请和管理,多结点之间的数据交换也是在TaskManager上执行。Flink集群中,每个worker(taskManager)对应的是一个JVM进程。

  换句话说,JobManager分配资源、任务,TaskManager拥有资源、启动任务。一般在生产环境中,JobManager和TaskManager所在结点应是分离的,其目的主要是为了保证TaskManager(基于内存的计算)不抢夺JobManager的资源。

  3)client客户端:不是runtime的一部分,换句话说,Flink集群启动client提交的任务之后,client客户端时可以断开的,是可以不需要的。client不像JobManager和TaskManager对应着 flink集群中的结点(或是物理机、或是虚拟机、或是容器),是触发执行的一个抽象化,若程序在JobManager所在结点执行,则称client在JobManager结点上,同样,其也可以在TaskManager结点上。

  提交一个任务的正常流程是:client与JobManager构建Akka连接,将任务提交到JobManager上,JobManager根据已经注册在JobManager中TaskManager的资源(TaskSlot)情况,将任务分配给有资源的TaskManager,并命令TaskManager启动任务,TaskManager则从JobManager接受需所部属的任务,使用slot资源启动task,建立数据接入的网络连接,然后接受数据并开始处理。

  2.2、taskSlot

  每个task slot是TaskManager的一部分,若一个taskManager有三个taskSlot,则这三个taskSlot会均分这个TaskManager的资源(仅内存,不包括CPU)。有多个slot意味着同一个JVM中会有多个子任务,这些任务会共享JVM的TCP连接和心跳信息。这里要说明的是,slot的个数不是subtask的个数是一一对应,一个slot中可以有多个subtask。在默认情况下,同一个job中的子任务(subtask)是可以共享一个slot的。这里涉及slot共享的概念,后续博客中分析。

 

参考: 

[1]https://flink.apache.org/zh/flink-architecture.html

[2]https://ci.apache.org/projects/flink/flink-docs-release-1.6/concepts/runtime.html

 

转载于:https://www.cnblogs.com/love-yh/p/11241765.html

<think>嗯,用户深入询问了Kafka与Flink在数据中台架构中实现Exactly-Once的原理。从对话历史看,用户对数据中台的技术实现有相当专业的了解,之前已经讨论过Kafka在数据中台中的核心作用,现在聚焦在事务致性这个高阶话题上。用户提供的引用资料很有价值,主要说明了三点:1)Kafka0.11+的事务支持是实现EE的基础[^1][^2];2)Flink实现EE需要sink端配合[^3];3)消费端也需要事务支持[^4]。这说明用户已经做了功课,需要的是系统化的原理剖析。这个问题可以拆解为三个层面来讲:首先是Flink内部检查点机制如何保障状态致性,这是基石;其次要说明Kafka作为消息系统如何参与分布式事务;最后需要解释数据中台场景下这种机制如何落地。用户特别强调"架构"视角,所以应该突出组件间的协作关系。注意到用户上次询问过"端到端致性",这次EE实现其实是延续话题。在数据中台语境下,需要强调SchemaRegistry的作用——它保存的数据格式定义也是事务致性的组成部分,虽然引用里没提这点,但根据之前的讨论应该补充。用户提供的引用[^3]中那个支持列表特别重要,要重点解释为什么有些sink只能做到at-least-once。不过技术细节容易枯燥,可以用那个Kafka生产者的配置案例来具象化,这样用户能立即联想到实际配置场景。最后那个自动偏移提交的对比很关键,用户引用[^2]提到了checkpoint禁用时的行为差异,这个对比能帮助理解EE和ALO的本质区别。可以用个简单表格归纳,避免技术叙述过于密集。</think> 在数据中台架构中,Kafka与Flink协同实现端到端的Exactly-Once语义需通过**分布式事务机制**完成,核心原理分为以下三部分: --- ### **Flink检查点机制(Checkpoint)** Flink通过**分布式快照**保障内部状态致性: 1. **屏障传播** JobManager周期性广播**Barrier**信号,当算子接收到所有输入的Barrier后,将自身状态快照写入**持久化存储(如HDFS)**[^2] $$ \text{Checkpoint}_n = \bigoplus_{i=1}^{k} S_i \quad (S_i\text{为算子状态}) $$ 2. **异步快照** 状态备份与数据处理并行执行,避免阻塞 3. **精准次恢复** 故障时从最近完整Checkpoint恢复,重放未确认数据 > ✅ **作用范围**:Flink计算拓扑内部状态致性 --- ### **二、Kafka事务生产与消费** #### 1. **生产者端(写入Sink)** - Kafka ≥0.11支持事务API - Flink Kafka Sink通过事务ID管理写入批次: ```java // KafkaSink配置事务参数 KafkaSink.<String>builder() .setProperty("transactional.id", "flink-job-001") // 唯ID .setProperty("enable.idempotence", "true") // 启用幂等 .build(); ``` - **两阶段提交逻辑**: - **预提交**:数据写入Kafka但标记为`未提交` - **Checkpoint完成**:Flink向Kafka发送`commitTransaction()`[^1] #### 2. **消费者端(Source)** - Flink Kafka Consumer绑定到Checkpoint: ```java env.addSource(new FlinkKafkaConsumer<>( "input_topic", new JSONKeyValueDeserializationSchema(), props).setCommitOffsetsOnCheckpoints(true) // 偏移量随Checkpoint提交 ); ``` - 偏移量提交由Flink控制,替代Kafka自动提交[^2] > ✅ **协作机制**:Offset提交与Checkpoint绑定,实现读取位置致性 --- ### **三、端到端事务链路(数据中台场景)** ```mermaid flowchart TD A[业务数据源] --> B(Kafka Topic A) B --> C{Flink Job} C -->|1. 消费Topic A| D[计算状态] D -->|2. 写入结果| E(Kafka Topic B) subgraph 事务控制点 C -- Checkpoint触发--> F[持久化状态/Offset] F -- 提交信号--> E end ``` 1. **原子性保障** - 当Checkpoint完成时: - Topic A偏移量提交 - Topic B事务提交 - 状态快照持久化 **三者原子执行**,否则整体回滚 2. **故障恢复流程** - 重启后加载最近Checkpoint $C_n$ - 重置Topic A消费偏移量至 $C_n$ 记录位置 - 回滚Topic B中$C_n$后写入的数据 3. **数据中台关键配置** ```properties # Flink检查点配置 execution.checkpointing.interval: 5000 # 5秒触发Checkpoint execution.checkpointing.mode: EXACTLY_ONCE # Kafka生产者 isolation.level: read_committed # 只读已提交数据 ``` > 🔐 **完整性与效率平衡**:事务周期与Checkpoint间隔需权衡,过短增加开销,过长扩大故障恢复范围 --- ### **与传统机制的对比** | **机制** | 偏移量提交方式 | 数据重复风险 | 故障恢复粒度 | |------------------|------------------------|--------------|--------------------| | 无Checkpoint | Kafka自动提交 | 高(至少次)| 偏移量区间 | | Checkpoint+ALO | Flink同步提交 | 中(至少次)| 单条数据 | | **Checkpoint+EE**| 事务绑定提交 | **零** | **原子事务批次** | --- ### **典型问题解决方案** > **Q:事务ID冲突导致数据丢失?** > A:为每个Flink Job配置唯`transactional.id`,Kafka根据ID保留未完成事务数据[^1] > **Q:Checkpoint超时影响吞吐?** > A:调整`state.backend`为RocksDB,增量快照可提升效率: > ```python > env.set_state_backend(RocksDBStateBackend()) > ``` > **Q:下游非事务系统如何保障致性?** > A:通过**两阶段提交抽象**实现: > - 实现`TwoPhaseCommitSinkFunction`接口 > - 示例代码参考:[Flink官方文档](https://nightlies.apache.org/flink/flink-docs-release-1.18/docs/dev/datastream/fault-tolerance/exactly_once/) ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值