定义
- Kafka中的定义
exactly-once简称EOS,不管在处理的时候是否有错误发生,计算的结果(包括所有所改变的状态)都一样。
- Flink中的定义
当我们说『Exactly-Once』时,指的是每个输入的事件只影响最终结果一次。即使机器或软件出现故障,既没有重复数据,也不会丢数据。
分类
- Exactly-Once
保证所有记录仅影响内部状态一次。
- End-TO-End Exactly-Once
一致性比较
At most once < At least once < Exactly-Once < End-TO-End Exactly-Once
实现方式
(1).At least once+去重
- 每个算子维护一个事务日志,跟踪已处理的事件;
- 重放失败事件,在事件进入下个算子之前,移除重复事件。
(2).At least once+幂等
这种实现方式依赖Sink端存储的去重性和数据特征。
示例:输出到数据库,通过replace into + unique key
(3).分布式快照
分布式快照算法(Chandy-Lamport):
- 引入barrier,把输入流切分为preshot records和postshot records;
- Operator收到所有上游barrier的时候做一个snapshot,继续往下处理
- 当所有Sink Operator都完成了Snapshot,这一轮Snapshot就完成了
示例:Flink
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
用户只需要实现四个函数(继承TwoPhaseCommitSinkFunction抽象类),就能为数据输出端实现Exactly-Once语义:重写beginTransaction
在事务开始前,我们在目标文件系统的临时目录中创建一个临时文件。随后,我们可以在处理数据时将数据写入此文件。
- 重写preCommit
在预提交阶段,我们刷新文件到存储,关闭文件,不再重新写入。我们还将为属于下一个checkpoint的任何后续文件写入启动一个新的事务。
- 重写commit
在提交阶段,我们将预提交阶段的文件原子地移动到真正的目标目录。需要注意的是,这会增加输出数据可见性的延迟。
- 重写abort
Flink Kafka Consumer
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/