定义

  • Kafka中的定义

exactly-once简称EOS,不管在处理的时候是否有错误发生,计算的结果(包括所有所改变的状态)都一样。

  • Flink中的定义

当我们说『Exactly-Once』时,指的是每个输入的事件只影响最终结果一次。即使机器或软件出现故障,既没有重复数据,也不会丢数据。

分类

  • Exactly-Once

保证所有记录仅影响内部状态一次。

  • End-TO-End Exactly-Once

保证所有记录仅影响内部和外部状态一次。
image.png

一致性比较

At most once < At least once < Exactly-Once < End-TO-End Exactly-Once

实现方式

(1).At least once+去重

  • 每个算子维护一个事务日志,跟踪已处理的事件;
  • 重放失败事件,在事件进入下个算子之前,移除重复事件。

示例:Google MillWheel
image.png

(2).At least once+幂等

这种实现方式依赖Sink端存储的去重性和数据特征。
示例:输出到数据库,通过replace into + unique key
image.png

(3).分布式快照

分布式快照算法(Chandy-Lamport):

  • 引入barrier,把输入流切分为preshot records和postshot records;
  • Operator收到所有上游barrier的时候做一个snapshot,继续往下处理
  • 当所有Sink Operator都完成了Snapshot,这一轮Snapshot就完成了

示例:Flink
image.png

EOS实现方式 优点 缺点
At least once+去重
- 故障对性能的影响是局部的
- 故障的影响不一定会随着拓扑的大小而增加

- 可能需要大量的存储和基础设施来支持
- 每个算子的每个事件都有一定的性能开销
At least once+幂等
- 实现简单,开销较低

- 依赖存储特性和数据特性
分布式快照
- 较小的性能和资源开销

- barrier同步
- 任何算子发生故障,都需要发生全局暂停和状态回滚
- 拓扑越大,对性能的潜在影响越大

Flink对EOS的支持

Flink1.4版本之前

  • 支持Exactly-Once语义,仅限于应用程序内部

Flink1.4版本之后

  • 通过两阶段提交(TwoPhaseCommitSinkFunction)支持End-To-End Exactly Once
  • 可支持Kafka 0.11+版本End-To-End Exactly Once集成

    Kafka结合flink实现端到端EOS

    1.png
    2.png
    用户只需要实现四个函数(继承TwoPhaseCommitSinkFunction抽象类),就能为数据输出端实现Exactly-Once语义:

  • 重写beginTransaction

在事务开始前,我们在目标文件系统的临时目录中创建一个临时文件。随后,我们可以在处理数据时将数据写入此文件。

  • 重写preCommit

在预提交阶段,我们刷新文件到存储,关闭文件,不再重新写入。我们还将为属于下一个checkpoint的任何后续文件写入启动一个新的事务。

  • 重写commit

在提交阶段,我们将预提交阶段的文件原子地移动到真正的目标目录。需要注意的是,这会增加输出数据可见性的延迟。

  • 重写abort

在中止阶段,我们删除临时文件。

Flink Kafka Consumer

Flink-Exactly Once方案 - 图7

Flink EOS支持列表

Flink支持的精确一次Source列表:

数据源 语义保证 备注
Apache Kafka exactly once 需要对应的Kafka版本
AWS Kinesis Streams exactly once
RabbitMQ at most once(v-0.10)/exactly once(v-1.0)
Twitter Streaming API at most once
Collections exactly once
Files exactly once
Sockets at most once

Flink支持的精确一次Sink列表:

数据源 语义保证 备注
HDFS rolling sink exactly once 依赖Hadoop版本
Elasticsearch at least once
Kafka producer at least once/exactly once 需要Kafka-0.11+版本
Cassandra sink at least once/exactly once 幂等更新
AWS Kinesis Streams at least once
File sinks at least once
Socket sink at least once
Standard output at least once

参考

【Apache Flink结合Kafka构建端到端的Exactly-Once处理】https://ververica.cn/developers/exactly-once
【Flink构建真正的End-To-End Exactly Once】https://blog.csdn.net/huonan_123/article/details/104224431
【Flink-Kafka端到端ExactlyOnce分析】https://ververica.cn/developers/flink-kafka-end-to-end-exactly-once-analysis/
【Kafka-0.11.0.0是如何实现Exactly-once语义的】https://www.jianshu.com/p/5d889a67dcd3
【Flink实战:结合Kafka构建端到端的Exactly-Once处理程序】https://my.oschina.net/u/992559/blog/1821399
【Flink实现Kafka到Mysql的Exactly-Once】https://www.jianshu.com/p/5bdd9a0d7d02
【kafka exactly once批处理】https://www.jianshu.com/p/19801ed5578e
【Kafka事务机制与Exactly Once语义实现原理】https://www.zybuluo.com/tinadu/note/949867
【RocketMQ使用Exactly-Once投递语义收发消息】https://help.aliyun.com/document_detail/102777.html
【Kafka+Flink+Mysql好的博客记录】https://blog.csdn.net/DreamWeaver_zhou/article/details/84856739
【一文搞懂Flink的ExactlyOnce和AtLeastOnce】https://ververica.cn/developers/flink-exactly-once-and-at-least-once/
【Flink Kafka Connector与ExactlyOnce剖析】https://ververica.cn/developers/anatomy-of-flink-kafka-connector-and-exactly-once/