1. Flink简介与Exactly Once概述

各位同学好,我是老张。做实时数据处理这些年,踩过的坑比写过的代码还多。今天咱们开始聊Flink实时ETL链路中的Exactly Once实现——这可能是整个流处理领域最硬核的话题之一。

先别急着上代码。咱们得先把基础打牢。什么是Flink?什么是Exactly Once?为什么实时ETL场景下它这么重要?这些搞不清楚,后面写再多代码也是空中楼阁。

1.1 Flink到底是什么

Flink,说白了就是一个分布式流处理引擎。它能处理无界数据流,也能处理有界数据集。我习惯把它理解成「数据流水线上的智能机器人」——数据流过来,它能在毫秒级完成清洗、转换、聚合、输出。

你可能会问:Spark Streaming不也能做吗?嗯,这里要注意——Flink是真正的逐条处理,而不是微批次。微批次意味着延迟至少几百毫秒,而Flink可以做到毫秒级。我在2018年做过一个金融风控项目,要求延迟低于50ms,当时选型对比了一圈,最后只有Flink能满足。

Flink核心特性:

  • 真正的流处理:逐条处理,不是微批次
  • 有状态计算:可以记住历史数据做复杂计算
  • 精确一次语义:数据不丢不重,这是咱们这门课的核心
  • 事件时间处理:能处理乱序数据,这在实时ETL中太重要了
  • 高可用与容错:基于Checkpoint的故障恢复机制

1.2 实时ETL场景:为什么需要Flink

传统ETL是跑批的——每天凌晨跑一次,把数据从A库搬到B库,顺便做清洗转换。但现在的业务场景变了:

  • 用户下单后,风控系统需要秒级判断这笔交易是否异常
  • 电商大促时,实时大屏要展示每秒的GMV
  • 推荐系统需要实时更新用户画像

这些场景,批处理搞不定。实时ETL应运而生。

我举个例子。之前做过一个电商实时数仓项目,数据链路是这样的:

业务日志(Kafka)→ Flink清洗 → Flink维表关联 → Flink聚合 → 写入ClickHouse

这条链路里,Flink承担了清洗、转换、关联、聚合全部工作。如果中间任何一个环节出问题,数据要么丢,要么重复,下游报表就全乱了。

这就是为什么我们需要Exactly Once——保证数据不丢不重。

1.3 Exactly Once语义定义

Exactly Once,直译就是「精确一次」。意思是每条数据在整个处理链路中,恰好被处理一次,不多不少。

咱们先看三种语义的对比:

语义级别 含义 典型场景 代价
At Most Once 最多一次,可能丢数据 监控告警(丢几条无所谓) 低延迟,低开销
At Least Once 至少一次,可能重复 日志收集(重复可接受) 中等开销
Exactly Once 精确一次,不丢不重 金融交易、实时报表 较高开销,需要端到端保障

你想想看,如果做的是实时交易风控,一条数据重复处理两次,可能就把正常交易误判为异常了。反过来,丢了一条数据,可能就漏掉了一笔欺诈交易。所以金融场景必须Exactly Once。

注意:Flink自身的Exactly Once和「端到端Exactly Once」是两回事。Flink内部可以保证不丢不重,但数据写到Kafka、MySQL、HBase这些外部系统时,还需要额外的机制来保证。这也是咱们这门课要重点解决的问题。

1.4 端到端一致性挑战

为什么端到端Exactly Once这么难?我画了一张图,你看完就明白了。

端到端Exactly Once一致性挑战 数据源 Kafka / MySQL Flink 计算 清洗 · 转换 · 聚合 外部存储 MySQL / HBase / ES 三大核心挑战 挑战1:故障恢复 Flink宕机后重启 如何保证状态一致? Checkpoint机制 挑战2:外部幂等 写入外部存储时 如何避免重复数据? 幂等写入 / 事务 挑战3:多流对齐 多数据源Join时 如何保证一致性? Barrier对齐 解决方案:两阶段提交 + 幂等写入 + Checkpoint

从图上你能看到,端到端一致性面临三个主要挑战:

  1. 故障恢复:Flink任务挂了,重启后状态怎么恢复?Checkpoint怎么保证不丢不重?
  2. 外部幂等:数据写到MySQL,如果重复写入怎么办?需要幂等机制或者事务支持。
  3. 多流对齐:两个Kafka Topic做Join,一个流快一个流慢,怎么保证一致性?

我曾经在一个项目中踩过这个坑。当时做实时订单宽表,订单流和支付流做Join。Flink任务重启后,部分支付数据重复写入,导致订单金额翻倍。排查了两天才发现是Sink端没有做幂等处理。从那以后,我养成了一个习惯——所有外部写入必须先考虑幂等性。

我的经验:做实时ETL链路设计时,先把「如果任务重启会怎样」这个问题想清楚。不要等到线上出问题了再补救。端到端Exactly Once不是Flink单方面能搞定的,需要数据源、Flink、外部存储三方配合。

1.5 本章小结

咱们这一章把基础概念理清了:

  • Flink是真正的流处理引擎,不是微批次
  • 实时ETL场景对一致性要求极高
  • Exactly Once意味着不丢不重
  • 端到端一致性需要解决故障恢复、外部幂等、多流对齐三大挑战

后面的章节,我会带着大家一步步实现这个目标。从Checkpoint原理开始,到两阶段提交,再到Kafka、MySQL、HBase等外部系统的Exactly Once写入。每个方案都是我亲自验证过的,坑也帮你们踩过了。

准备好了吗?咱们开始吧。