当前位置: 首页 > news >正文

从零开始学Flink:Flink 双流 JOIN 实战详解

在前一篇 《Flink SQL 窗口(Window)操作详解》 中,我们已经打好了时间与窗口的基础。
但在真实业务里,单条流上的聚合往往只是第一步,更常见的需求是把多条业务流关联起来一起看,例如:

  • 订单流 + 支付流:衡量下单到付款的转化效果
  • 浏览流 + 下单流:分析从曝光、点击到下单的完整漏斗
  • 用户行为流 + 用户画像维表:驱动推荐、风控等在线决策

这些需求背后的共性能力就是:双流 JOIN

本文以「订单流 + 支付流」为主线,从环境准备、建表、造数到 JOIN 查询,一步步带你搞懂 Flink SQL 中的双流 JOIN 思路与实践。

一、双流 JOIN 适用的典型场景

  • 订单与支付关联:找出已下单但未支付、支付失败等情况
  • 广告曝光与点击关联:计算点击率、转化路径
  • 日志与告警规则关联:实时检测异常行为

这些场景有两个共同特征:

  • 两条都是事实流(不断追加的新事件)
  • 需要在时间范围内去匹配事件(谁先发生、允许多长时间内匹配)

因此在流计算中做 JOIN,一定绕不开时间字段水位线(Watermark)

在 Flink SQL 的流模式下,常见的双流关联方式有:

  • 普通 JOIN:基于等值条件 + 时间字段的 JOIN
  • Interval Join:基于「时间区间」的双流 JOIN
  • Temporal Join:一条流 + 维表(变更流)的时态关联

本篇主要聚焦前两种,更贴近「订单流 + 支付流」这样的事实双流场景。

三、准备示例数据表

安装 Kafka(环境前提)

在 WSL2 的 Ubuntu 环境中安装并启动 Kafka,请参考 《从零开始学Flink:数据源》。

需要把 Flink 的 Kafka SQL Connector JAR 包,放到 $FLINK_HOME/lib 目录下。

以本系列示例使用的 Flink 1.20.1 + Kafka 3.4.0-1.20 为例,可以这样操作:

  1. 确认你的 Flink 安装目录(假设为 /opt/flink):

    export FLINK_HOME=/opt/flink
    

  1. 下载 Kafka SQL Connector JAR 到 Flink 的 lib 目录:

    cd $FLINK_HOME/lib
    wget https://repo1.maven.org/maven2/org/apache/flink/flink-sql-connector-kafka/3.4.0-1.20/flink-sql-connector-kafka-3.4.0-1.20.jar
    

    如果你是 Windows + WSL2,可以在 WSL2 里执行同样的命令;或者用浏览器下载后手动拷贝到 lib 目录。

  2. 如果你使用的是独立集群或远程集群,需要重启 Flink 集群,让新 JAR 在 JobManager/TaskManager 上生效:

    cd $FLINK_HOME
    bin/stop-cluster.sh
    bin/start-cluster.sh
    

    如果只是本地直接运行 bin/sql-client.sh 启动内嵌 mini-cluster,则只需重启 SQL Client 即可。

  3. 启动 Flink SQL Client,然后执行本文后续的建表与查询示例:

    cd $FLINK_HOME
    bin/sql-client.sh
    

准备 Kafka 中的示例数据表

我们假设已经从 Kafka 中读取两条流:

  • orders:订单流
  • payments:支付流

并在建表时定义了事件时间和水位线:

CREATE TABLE orders (order_id     STRING,user_id      STRING,order_amount DECIMAL(10, 2),order_time   TIMESTAMP_LTZ(3),WATERMARK FOR order_time AS order_time - INTERVAL '5' SECOND
) WITH ('connector' = 'kafka','topic' = 'orders','properties.bootstrap.servers' = '127.0.0.1:9092','properties.group.id' = 'flink-orders','scan.startup.mode' = 'earliest-offset','format' = 'json','json.timestamp-format.standard' = 'ISO-8601'
);CREATE TABLE payments (pay_id     STRING,order_id   STRING,pay_amount DECIMAL(10, 2),pay_time   TIMESTAMP_LTZ(3),WATERMARK FOR pay_time AS pay_time - INTERVAL '5' SECOND
) WITH ('connector' = 'kafka','topic' = 'payments','properties.bootstrap.servers' = '127.0.0.1:9092','properties.group.id' = 'flink-payments','scan.startup.mode' = 'earliest-offset','format' = 'json','json.timestamp-format.standard' = 'ISO-8601'
);

有了时间字段和水位线,Flink 才能在流模式下安全地做双流 JOIN,并在「时间窗」关闭后清理状态。

使用 Kafka Console Producer 造测试数据

上面的 DDL 建好了 orderspayments 两张表,对应的是 Kafka 中的两个 Topic。接下来我们用 Kafka 自带的命令行工具写入几条 JSON 测试数据。

假设你已经在 WSL2 的 Ubuntu 中启动好了 Kafka(包括 ZooKeeper 或 KRaft),进入 Kafka 安装目录,执行:

1. 往订单 Topic 写入数据

bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic orders

在命令行中输入几条 JSON 数据(按回车发送一条):

{"order_id":"o_1","user_id":"u_1","order_amount":100.00,"order_time":"2026-02-16T14:41:00Z"}
{"order_id":"o_2","user_id":"u_2","order_amount":200.00,"order_time":"2026-02-16T14:42:00Z"}
{"order_id":"o_3","user_id":"u_1","order_amount":150.00,"order_time":"2026-02-16T14:45:00Z"}

2. 往支付 Topic 写入数据

新开一个终端,同样进入 Kafka 安装目录,执行:

bin/kafka-console-producer.sh --bootstrap-server 127.0.0.1:9092 --topic payments

输入对应的支付 JSON 数据:

{"pay_id":"p_1","order_id":"o_1","pay_amount":100.00,"pay_time":"2026-02-16T14:41:00Z"}
{"pay_id":"p_2","order_id":"o_2","pay_amount":200.00,"pay_time":"2026-02-16T14:42:00Z"}

这里的字段名、时间格式都要和前面建表时定义的一致,这样 Flink 才能正确反序列化 JSON 并进行双流 JOIN。

四、基于时间条件的普通双流 JOIN

先来看最直观的一种写法:同时指定「关联键」和「时间范围」。

需求:统计订单在下单后 15 分钟内完成支付的记录。

SELECTo.order_id,o.user_id,o.order_amount,o.order_time,p.pay_id,p.pay_amount,p.pay_time
FROM orders AS o
JOIN payments AS p
ON o.order_id = p.order_id
AND p.pay_time BETWEEN o.order_time AND o.order_time + INTERVAL '15' MINUTE;

双流join

这里有几点非常关键:

  • o.order_id = p.order_id:以订单号作为两条流的业务主键
  • pay_time BETWEEN order_time AND order_time + INTERVAL '15' MINUTE:明确限定“下单后 15 分钟内支付”这类时间约束
  • 使用事件时间字段配合水位线,可以在保证计算正确性的前提下控制状态大小,并处理一定范围内的迟到数据

如果你希望保留那些下单了但超时未支付的记录,可以将上面的 JOIN 改为 LEFT JOIN,然后在下游以 p.pay_id IS NULL 作为“未支付/超时”的判断条件。

五、Interval Join:显式时间区间的双流 JOIN

普通 JOIN 中的时间条件本质上就是一种「区间约束」。
在 Flink Table API 中,有一个更明确的概念:Interval Join

等价的 Interval Join 写法大致如下(Table API 伪代码,仅作为概念理解):

SELECTo.order_id,o.order_time,p.pay_id,p.pay_time
FROM orders AS o
JOIN payments AS p
ON o.order_id = p.order_id
AND p.pay_time BETWEEN o.order_time AND o.order_time + INTERVAL '15' MINUTE;

无论是普通 JOIN 还是 Interval Join,本质上都是:

  • 以某个时间字段作为「对齐基准」
  • 设定一个前后允许的时间区间
  • 在这个区间内匹配到的记录会输出为 JOIN 结果

六、迟到数据与状态清理

在流式 JOIN 中,最容易被忽略但又非常重要的一点就是:状态会不断累积

Flink 会根据时间条件和水位线来决定:

  • 某条历史事件是否还有可能再匹配到另一条流的事件
  • 超出时间范围且水位线已推进时,可以安全地清理对应状态

设计双流 JOIN 时,建议考虑:

  • 时间窗口不要设置得过大,否则状态会膨胀
  • 根据业务的真实延迟来设置水位线与时间区间
  • 对于极端迟到的数据,是丢弃、旁路输出,还是通过补偿机制处理

七、一个完整的小结

通过本文,你需要记住下面几点:

  • 双流 JOIN 场景非常常见,本质是两条事实流在时间上的匹配
  • 流式 JOIN 一定要依赖事件时间 + 水位线来控制状态和迟到数据
  • 常见的方式包括基于时间条件的普通 JOIN 和 Interval JOIN
  • 设计时间区间时,要在「业务容忍度」和「资源消耗」之间做权衡

在下一篇中,我们可以继续围绕「实时数仓」或「维表时态 Join」展开,把事实流与维度数据关联起来,构建更真实的 Flink SQL 实战项目。


原文来自:http://blog.daimajiangxin.com.cn

http://www.jsqmd.com/news/387556/

相关文章:

  • 2026推荐几家研磨仪生产厂家:实验室/盘式/切割式/食品/土壤样品研磨仪厂家推荐,满足您的研磨需求 - 品牌推荐大师1
  • Tauri vs Electron一篇尽量“把话说满”的客观对比
  • 2026冷冻研磨仪和常温研磨仪区别及选购:国产/矿石/臼式研磨仪全面解读,明智之选 - 品牌推荐大师1
  • 月薪35-50k16薪,大模型时代来了!收藏这份高薪AI算法工程师培养计划,小白也能逆袭成高薪程序员!
  • 直接上结论:9个降AIGC工具测评!研究生降AI率必备指南
  • 小白程序员必备:收藏这份AI大模型学习路线,抢占风口先机!_AI大模型学习路线
  • HUSKY——物理感知全身控制人形滑板系统 第三章:实验验证与深度分析
  • 城市郊野公园管理系统|基于java+ vue城市郊野公园管理系统(源码+数据库+文档)
  • 大学生心理测评与分析系统|基于springboot + vue大学生大学生心理测评与分析系统(源码+数据库+文档)
  • 新年特别版|PyCharm 效率翻倍指南:新手必装的 5 个神级插件推荐(建议收藏)
  • DeepBear-Health:基于迁移学习和可解释时频分析的滚动轴承故障诊断(Python)
  • 30:【uv + torch】2026最快安装GPU PyTorch 避开conda坑
  • 2026年行业内服务好的安检仪供应商怎么找,安检机/安检设备/金属探测门/安检仪/智能安检/安检门,安检仪产品推荐榜单 - 品牌推荐师
  • 大学生创业信息管理系统|基于java + vue大学生创业信息管理系统(源码+数据库+文档)
  • 基于YOLOv5的食物识别在Xilinx平台上的实现之旅
  • 看完就会:一键生成论文工具,继续教育首选千笔AI VS 锐智 AI
  • 2026超离心研磨仪品牌选购指南:全球粗铜样品/刀式/颚式/高速旋转/高通量组织研磨仪市场占有率TOP实测对比 - 品牌推荐大师1
  • 网上书店系统|基于springboot + vue网上书店系统(源码+数据库+文档)
  • OpenCV 第15课 图像处理之人脸检测(三)
  • 中老年人文化活动平台系统|基于java+ vue中老年人文化活动平台系统(源码+数据库+文档)
  • 大模型开发8步详解:小白也能轻松入门,掌握Prompt工程开启高薪AI之路
  • 毕业论文神器!降AIGC工具 千笔 VS 文途AI,本科生专属首选
  • 商场自动引导购物车,跟随主人,避人群,商场导览,输出跟随行进。
  • ZEST:零样本具身技能迁移算法 第三章:实验验证与部署实践
  • 导师推荐 9个 AI论文软件:专科生毕业论文写作全测评
  • 2005-2024年上市公司企业资源配置效率Richardson模型
  • 拖延症福音 AI论文软件 千笔·专业学术智能体 VS 学术猹 研究生必备
  • 辞旧迎新|2025除夕夜:以奋斗为笔,共绘2026新篇章 - 奋飞咨询ecovadis
  • 2000-2024年地级市人口流动率测算数据
  • 2026软件开发变革:DeepSeek从“编写代码”到“表达意图”,缩短交付周期实战