本文整理自阿里云的高级技术专家、Apache Flink PMC 成员李麟老师在 Flink Forward Asia 2025 新加坡站 ------ 实时 AI 专场中的分享。将带来关于 Flink 2.1 版本中 SQL 在实时数据处理和 AI 方面进展的话题。
Flink 2.1 SQL 的关键进展
本篇将探讨三个部分:
Data + AI:在 Flink SQL 中连接实时数据处理与AI能力
首先,将介绍 Flink SQL 2.1 如何连接实时数据处理与AI能力。您将看到我们如何增强对 AI 函数的支持,从模型注册到通过ML_PREDICT
与 SQL 的无缝集成,支持大模型文本生成和RAG工作流等任务。
优化 Join:解决 Flink 流式 Join 中的关键挑战
接下来,了解一下解决流式连接中的一个关键挑战。深入探讨两个关键改进:Delta Join,通过结合索引和变更日志处理来消除状态存储;以及 Multi-way Join,在保持低延迟的同时减少多流连接中的冗余。
未来展望:Flink SQL 在数据与 AI 方面的持续增强和路线图
最后,将分享未来的路线图,包括 RAG 管道中的向量搜索支持和扩展的AI函数支持。
接下来我将展示 Flink 2.1 如何让您无缝构建可扩展的实时 AI 管道。在深入 Flink AI 函数之前,让我们先从一个现实世界的问题开始。
案例:实时产品合规性

想象一下您正在运营一个全球电商平台。平台卖家每天会发布数百万个产品。但问题是:您需要确保每一个产品发布都符合您运营的每个国家的当地法律。
例如,一个标题为"含微量酒精的葡萄汁饮料"的产品在特定国家违反了政策,因为它包含"酒精"。
目前,团队使用 Flink SQL 构建管道来帮助人工审核:
-
首先从 Kafka 主题读取产品列表数据
-
使用自定义 UDF 如
keyword_match
,根据禁用关键词列表检查标题 -
输出风险列表供人工审核
但问题是------基于规则的系统非常僵化。
基于规则的关键词匹配的挑战:误报和漏报

好的,让我们看两个基于规则的关键词匹配失败的具体例子。
案例1:过度阻拦案例(误报)
想象一个标题为"葡萄汁(无酒精)"的产品。关键词"酒精"触发了规则,系统将其标记为风险。但它明确说了"无酒精"!这是一个误报------我们阻拦了一个安全的产品,浪费了人工审核时间,并可能导致客户不满。
案例2:阻拦不足案例(漏报)
现在,看看这个标题:"天然香草提取物"。我们的关键词列表包括"酒精"和"酒",但香草提取物通常含有酒精!规则完全遗漏了它------这是一个漏报。这可能导致严重的处罚。
那么...我们如何解决这个问题?这就需要比关键词匹配更智能的检测能力。
利用AI的语义分析实现更智能的合规性
让我们测试一下 AI 是否更优秀。这里有一个 ChatGPT 的简单例子------这可以是您训练的任何 LLM 或自定义模型。

步骤1:教AI任务
我们给模型一个清晰的提示,包括角色、规则和示例。
步骤2:用我们的问题案例测试
当我们输入棘手的"天然香草提取物"案例时,AI推导出它"含有酒精"。这正是我们需要的。
现在,让我们尝试将其集成到 UDF 中。
Flink 自定义 AI UDF 的隐性成本
我们构建了一个直接连接到 LLM 的新 UDF,管道看起来几乎和以前一样。相同的流程:
-
Kafka 输入(产品标题流入)
-
升级到新 UDF 后,决策现在更加智能
-
Kafka 输出(结果进入相同的审核主题------下游无需更改)
看起来完美...但是等等。

虽然这对小规模测试有效,但现实的挑战很快就会出现。

构建自定义 LLM UDF一开始感觉很棒,但现实情况是
-
代码重写:如果我们想从 OpenAI 切换到阿里云,我们需要重写 UDF 代码。测试不同的模型?更多的代码更改。这种方法无法扩展。每次新模型或 API 更改时重写 UD F代码是不高效的。
-
同步请求 = 交通堵塞 :每个产品标题都会触发对 LLM 的同步 API 调用。每次调用需要1-3秒------那么吞吐量将非常低。所以如果我们想要使用异步请求获得更高的吞吐量,我们需要通过使用
AsyncScalarFunction
再次重写 UDF。现在我们应该更多地关注异步回调和错误处理。这不有趣,必须有更好的方法。
让我们看看 Flink 2.1 如何解决这个问题。
Apache Flink SQL 原生 AI 函数:简化AI集成

以下是利用 Flink SQL 原生 AI 函数的工作流程:
使用CREATE MODEL
通过简单的 SQL 命令注册需要的 LLM。需要切换模型?只需更改MODEL
参数------无需重写代码。模型管理变得如此简单。
Flink 2.1 中的新ML_PREDICT()
函数已为这些用例做好准备:
-
聊天/生成式任务:对于产品合规性检查、情感分析等场景,只需将文本传递给模型,它就会返回分析结果。
-
embedding:进行特征提取,通过从文本生成向量嵌入来为您的 RAG 管道提供支持。
一切都直接在 SQL 中工作。启用异步处理:只需添加一个简单的参数。切换模型:在 SQL 查询中引用MODEL
名称,无需 UDF 代码更改。
使用 Flink SQL AI 函数的实时产品合规性:具体示例
让我们通过一个具体的示例将所有内容整合在一起。以下是 Flink AI 函数如何解决我们的产品合规性挑战:

首先,我们使用CREATE MODEL
语法创建一个合规性模型------需要指定提供商(这里是阿里云的百炼平台)、模型名称qwen-turbo
,以及告诉AI其作为产品列表审核专家角色的系统提示。
当像"天然香草提取物"这样的产品标题到达时,Flink 通过ML_PREDICT
函数将其发送到AI模型。这是一个异步请求以确保高吞吐量。模型分析它并返回 JSON 响应。
最后,当risk_rate
超过定义的阈值时,我们将结果插入风险输出 topic。
优化 Flink SQL AI 函数:异步调优和资源规划以提升性能

让我们深入了解两个关键优化:异步配置和资源设置。
-
异步执行是首选 :在
ML_PREDICT()
调用中启用异步执行可以是首选。与增加任务并行度相比,这更具成本效益。对于仅追加的流,使用allow_unordered output_mode
,这样Flink可以处理得更快。设置max-concurrent-operations
以匹配您的 LLM 容量。如果您不想触发任务失败,可以将异步超时参数设置得比 AI 的最大延迟更大。有关异步操作的更多详细信息,请参考Flink文档。 -
基于 Little 定律进行资源规划:应用此公式进行容量规划:
-
L:队列槽位(对应
max-concurrent-operations
) -
λ:请求速率(对应预期的QPS)
-
W:平均延迟(对应模型的响应时间)
-
例如:对于目标100 QPS和1.2秒的99百分位延迟,我们需要120个最大并发请求(max-concurrent-operations
)。此外,考虑到队列长度和平均行大小,我们需要更多关注 TaskManager 中的内存设置。适当的调优可能显著提升运行AI函数的吞吐量和稳定性。
JSON 无处不在:从大数据到AI工作流
在深入了解 Join 之前,先聊一聊一个基础的数据类型:JSON。

让我们从一个简单的事实开始:JSON 无处不在。从传统数据管道到新的 AI 工作流,JSON 是表示结构化和半结构化数据的重要格式。我们在事件日志、搜索文档、API 负载中看到它。RAG 管道依赖 JSON 来存储和查询文档。甚至 LLM 提示和输出通常也格式化为 JSON。
到目前为止,Flink SQL 已经支持许多内置的 JSON 函数。但随着 JSON 变得更深入和更动态,这里有一个性能挑战。
过去 Flink 中 JSON 解析的隐性成本

表面上,JSON_VALUE
和类似的函数使得访问 JSON 字符串内的数据变得容易。但在底层,每次调用都会触发完整的JSON 解析。每次都是如此,对每一行都是如此。这对简单情况可能工作得很好,但在处理大型数据集、嵌套结构或深度查询路径时------比如 JSON 路径$.metadata.device
------性能会快速下降。
没有schema感知,JSON 内部没有索引,所以 SQL 优化器无法优化访问。
Flink SQL 的新 VARIANT 类型:高效的半结构化数据处理

Flink 2.1 引入了新的VARIANT
类型,这是一个原生的、二进制编码的半结构化类型。与普通的JSON字符串不同,VARIANT
以结构化方式存储元数据和值。因此访问data.metadata.device
只是一个直接的偏移查找,不再是完整的解析。
因为它是感知 schema 的,SQL 规划器可以在未来版本中应用查询优化。这使其非常适合数据管道。VARIANT
为大规模处理 JSON 解锁了性能和灵活性。了解更多关于Flink VARIANT类型的信息。
优化连接:解决 Flink 流处理中的关键挑战
现在让我们转向流式连接,这是实时处理中的另一个核心挑战。Flink SQL 支持丰富的连接类型:Regular Join、Interval Join、Temporal Join、Lookup Join 等等。每种都是为特定用例设计的。其中,regular join 是最直观的------它看起来完全像传统的 SQL 连接,使其易于编写和理解。
Flink 流式连接的限制:大规模可扩展性
让我们看看 Regular Join 是如何工作的:我们有两个输入流:页面浏览和订单从 Kafka 到达,它们将通过product_id
列实现 Join。Join 操作符有两个状态存储,左状态和右状态,都按product_id
分组存储。当新事件到达时,Flink 在对端的状态表中查找匹配的条目,执行连接逻辑并输出。

Regular Join 严重依赖 Flink 的状态后端来缓冲输入流。当正确使用时,这提供了高吞吐量和低延迟,特别是对于小到中等大小的数据流。但随着流大小的增长,Regular Join 开始出现问题。连接节点每一侧维护的状态变得越来越大。最终,这导致状态访问缓慢、检查点时间长和恢复时间长。您可能开始看到延迟峰值、背压,甚至检查点失败。这是一个经典的权衡------简单性和灵活性以可扩展性为代价。
那么我们如何解决 Regular Join 的大状态问题呢?
Delta Join:无状态 Join 的全新范式
这就是 Delta Join 的用武之地------它带来了一种截然不同的设计思路。与传统 Join 方式将所有数据缓存在 Flink 状态后端不同,Delta Join 转而依赖外部存储系统(例如基于 RocksDB 构建的 Apache Fluss),将数据存于外部,实现真正的无状态计算。
其工作原理如下:

Fluss 会持续发送变更日志(changelog)更新,确保 Join 数据始终最新。每当有新事件到达时,Delta Join 只需在 Fluss 中执行一次索引查询------就像访问一个键值存储(key-value store)一样简单高效。
可以看到,现在的 Delta Join 已经完全无状态。此前困扰流处理的各种"大状态"问题也随之消失。这使得过去难以实现的大规模 Join 任务,如今成为可能。
Delta Join 实战表现:真实场景下的性能飞跃
在生产环境中的实际表现印证了 Delta Join 的巨大价值。
传统的流式 Join 在数据规模扩大后迅速变得难以维系:状态体积膨胀至 100TB 以上,检查点耗时极长,故障恢复复杂且耗时。而通过 Delta Join,我们将状态外卸至 Fluss 等外部存储系统,实现了秒级检查点,CPU 与内存使用降低超 80%,启动冷启时间缩短 87%,并首次实现了 Join 算子的实时可追溯性。这使得 Flink 在处理超大规模 Join 任务时,变得更加稳定、高效、可扩展。

级联 Regular Join vs. Multi-way Join:从冗余中突围
让我们深入看看传统 Join 的一个"隐形陷阱"------尤其是在多流关联场景下的性能瓶颈。
Flink 的 Regular Join 是一个二元操作:一次只能连接两条流。如果我们想关联 T1、T2 和 T3 三张表,系统必须构建一个级联式执行计划:先将 T1 与 T2 关联,再将结果与 T3 关联。

这种模式带来了严重的效率问题:
每个 Join 阶段都需要维护自己完整的状态;
中间结果(如 T1 与 T2 的关联结果)会被重复存储;
整体状态体积呈倍数增长,检查点时间急剧上升。
虽然 FLIP-415的mini-batch join 能缓解部分中间结果输出的压力,但无法解决状态重复存储的根本问题。
那么,如何破局?
答案就是:Multi-Way Join。
流式 Multi-Way Join:高效 Join 的新范式

Multi-Way Join 是一种全新的 Join 策略,从设计源头就杜绝了冗余。
它允许使用同一个关联键,在单个算子内同时关联多条流。不同于级联式的二元 Join,Multi-Way Join 为每条输入流维护一个独立的索引状态表,不再生成中间 Join 结果,也无需嵌套存储。
这意味着:
-
没有中间状态复制
-
没有嵌套检查点延迟
关联的流越多,优势越明显。尤其在复杂事件处理、多维事实表关联等场景下,性能提升显著。
未来展望:Flink SQL 的 AI 与数据融合之路
接下来,让我们看看 Flink SQL 的未来发展方向。
Flink SQL 支持端到端 RAG 流水线

一个重要的短期目标是:在 SQL 中原生支持端到端的 RAG(检索增强生成)流程。
目前,用户可以使用 Flink 生成嵌入向量并写入 Milvus 等系统,但检索环节仍无法通过 SQL 直接处理。
未来,我们将引入 VECTOR_SEARCH
函数,直接在 Flink SQL 中实现向量检索,并结合 ML_PREDICT
完成嵌入与生成,实现完全声明式的 RAG 流水线:
-
数据摄入与向量化
-
通过向量检索获取 top-k 相似结果
-
将检索结果用于下游模型推理
整个流程无需编写 Java/Python 代码,真正实现"用 SQL 写 AI 流水线"。
AI 能力扩展:支持多模态与评估函数

我们也在持续拓展 Flink SQL 的 AI 能力边界。除了现有的文本处理和嵌入函数,未来将支持:
-
多模态处理:支持图像、音频等非文本输入;
-
评估函数(Evaluation Functions):在流水线执行过程中,实时评估模型输出的质量(如相关性、毒性、重复率等)。
这些能力将帮助用户在数据流中直接集成、监控和调优模型行为,实现更完整的智能处理。
持续优化:流式 Join 性能再突破

Join 性能始终是流式计算的核心课题。Delta Join 已通过解耦了 Flink Task 与本地状态的强绑定,有效解决了大数据量 Join 的扩展性难题。未来,我们将进一步支持更多存储引擎(如 Apache Paimon),以实现近实时 Delta Join。同时,我们也在增强对复杂多流 Join 的支持,包括:
-
放宽 Schema 对齐要求;
-
支持更丰富的查询模式;
目标是让 Flink 在面对复杂关联场景时,更加灵活、高效、易用。
要点总结:Flink 2.1 SQL 的三大关键点

最后,总结本次分享的三大关键点:
-
Flink SQL 融合 AI:让数据与智能无缝集成 原生支持模型管理与 AI 函数,让 AI 流水线在 SQL 中更统一、更易用; 新增
VARIANT
类型,高效处理 JSON 等半结构化数据,为未来 Planner 优化奠定基础。 -
攻克流式 Join 顽疾 Delta Join:通过状态卸载,彻底摆脱本地大状态束缚,提升稳定性与资源效率; Multi-Way Join:消除多流关联中的冗余状态,实现更轻量、更快速的 Join 处理。
-
未来路线图:更智能、更灵活 扩展 AI 支持:集成向量检索、多模态处理; 持续优化 Join 性能:支持更多存储、更复杂查询。
所有这些努力,都是为了一个目标:让 Flink SQL 成为构建实时、智能数据流水线的终极利器。