Flink cdc3.0动态变更表结构——源码解析

文章目录

  • 前言
  • 源码解析
    • [1. 接收schema变更事件](#1. 接收schema变更事件)
    • [2. 发起schema变更请求](#2. 发起schema变更请求)
    • [3. schema变更请求具体处理](#3. schema变更请求具体处理)
    • [4. 广播刷新事件并阻塞](#4. 广播刷新事件并阻塞)
    • [5. 处理FlushEvent](#5. 处理FlushEvent)
    • [6. 修改sink端schema](#6. 修改sink端schema)
  • 结尾

前言

上一篇Flink cdc3.0同步实例 介绍了最新的一些功能和问题,本篇来看下新功能之一的动态变更表结构的具体实现。

在 Flink 中,应用程序由流数据流组成,这些数据流是由用户定义的Operators进行转换。

Flink CDC 3.0 框架中流动的数据类型被称为Event,代表外部系统产生的变更事件。每个事件都标有发生更改的表 ID 。事件分为SchemaChangeEvent和DataChangeEvent,分别代表表结构和数据的变化。处理schema变更的Operators对应图中的SchemaOperator。

(以下代码使用Flink Release 3.0.0)

源码解析

1. 接收schema变更事件

我们以添加字段触发的AddColumnEvent为例,它实现了SchemaChangeEvent。 SchemaOperator 当接收到有AddColumnEvent 事件时,会在processElement 中调用handleSchemaChangeEvent处理。

2. 发起schema变更请求

说明下这里的response实际是直接返回的new SchemaChangeResponse(true), 由于构造的shouldSendFlushEvent 直接传入true, 所以后续也会进入if条件。我们接着requestSchemaChange 方法看

由于知道response是直接创建的已知结果,因此responseFuture.get() 也不会阻塞。我们接着来看toCoordinator.sendRequestToCoordinator(getOperatorID(), new SerializedValue<>(request));的实现

3. schema变更请求具体处理

通过几层的调用,上述变更请求会走到 SchemaRegistry 的handleCoordinationRequest(CoordinationRequest request),我们的请求是SchemaChangeRequest,所以会调用requestHandler.handleSchemaChangeRequest(schemaChangeRequest);

这里可以看到response 是直接创建的SchemaChangeResponse(true)。 接着schemaManager.applySchemaChange(request.getSchemaChangeEvent());注册新的schema。

另外还有个重点,在startToWaitForReleaseRequest方法中会重置responseFuture, 原本的response通过return返回了。而PendingSchemaChange中的response重置,主要就是为了等schema变更完成设计。(主线程会再次发起请求调用responseFuture.get() ,忽略这里会不理解后面为什么会阻塞)

4. 广播刷新事件并阻塞

回到第二部分,因为response是一个明确对象没有阻塞,返回后会直接广播FlushEvent 和 schemaChangeEvent(再次发起schemaChangeEvent不是很理解)。之后requestReleaseUpstream 请求调用responseFuture.get()会阻塞,因为response在第三步已经重置为new CompletableFuture<>(), 利用的1.8的特性。这也是收到变更事件后要保证sink端变更才能发放数据。

5. 处理FlushEvent

FlushEvent 由什么Operator处理,在官方架构图中其实没有指出,但是图标可以看出是通过sink端完成,我们可以找到DataSinkWriterOperator类,有对FlushEvent的处理。

实际调用SchemaRegistry::handleEventFromOperator方法,重点在requestHandler.flushSuccess(flushSuccessEvent.getTableId(), flushSuccessEvent.getSubtask());

其中applySchemaChange 就是在具体的sink端变更,下面会展开。 当变更完成后会执行waitFlushSuccess.getResponseFuture().complete(wrap(new ReleaseUpstreamResponse()));,实际就通知第4部分的response这里处理完了,可以正常放开数据流。

6. 修改sink端schema

每个sink端有自定义的metadataApplier,

我们以DorisMetadataApplier为例,applyAddColumnEvent 会构造addFieldSchema,然后在schemaChangeManager 中转换为对应的sql执行。

结尾

以上就是这两天对源码跟进的记录,后续思考使用local环境Debug中间过程。

相关推荐
码爸12 小时前
多源异构数据库实时同步至 Doris
数据库·flink·scala
用户36105886261213 小时前
Flink Time 之时间语义深度剖析:从 Processing Time 到 Event Time 与 Watermark 机制
大数据·flink
用户36105886261217 小时前
Flink 窗口聚合函数详解及代码实现:从 ReduceFunction 到增量聚合 + ProcessWindowFunction 组合
大数据·flink
俊哥大数据20 小时前
基于 FlinkSQL + Paimon + Doris 的车联网流批一体湖仓实践 —— 第 2 章 流批一体湖仓总体架构与三条分区契约铁律
flink·doris·湖仓一体·paimon
俊哥大数据20 小时前
基于 FlinkSQL + Paimon + Doris 的车联网流批一体湖仓实践 —— 第 4 章 Kafka 企标报文入湖(ODS 表设计)
flink·doris·湖仓一体·paimon·流批一体
俊哥大数据21 小时前
基于 FlinkSQL + Paimon + Doris 的车联网流批一体湖仓实践 —— 第 3 章 Paimon 1.4 湖仓底座与 Catalog 配置
flink·doris·湖仓一体·paimon
starzy19902 天前
Flink ResourceManager启动流程源码深度剖析:从ClusterEntrypoint到Slot分配的完整链路
java·大数据·flink
I Am a robert girl2 天前
PhysStream 源码级拆解:流式视频生成如何做到“边生成边控制“
python·音视频·源码解析·视频生成·可控生成·流式生成·物理控制
starzy19903 天前
Flink ApplicationMaster启动流程源码深度剖析:从YARN提交到JobMaster启动的完整链路
大数据·flink
用户3610588626124 天前
Flink Sliding Window 详解及代码实现:从窗口重叠到状态爆炸防控
大数据·flink