状态一致性保证
flink的状态一致性分为at most once、at least once、exactly once三种等级,状态一致性是指flink内部计算的结果一致性,
at most once
每条数据最多会被统计一次到结果中,即某条数据对应的task失败后flink appliation就会失败退出,此时这条数据也因为没有统计到结果中而丢失;如果task均正常则会统计一次到结果中,所以称作at most once
# 假设dataStream数据结构为String
dataStream.addSink(new FlinkKafkaProducer[String]("broker_list", "topic", new SimpleStringSchema()))
at least once
每条数据最少会被统计一次到结果中,即某条数据对应的task失败后flink会从checkpoints中恢复上一次checkpoints的计算状态并且从这次checkpoints的offset重新从source中获取过来,此时这个checkpoints期间的数据会统计一次到结果中,但这个checkpoints期间上一次失败时,有一部分数据task是已经成功的,那些数据已经被统计到结果中,所以那些数据是重复统计的,所以称作at least once
# 需要开启checkpoints并设置CheckpointingMode为AT_LEAST_ONCE,在task失败时能进行source重放,因此需要source端支持重放才能实现at least once sink
streamEnv.enableCheckpointing(1000, CheckpointingMode.AT_LEAST_ONCE)
# 假设dataStream数据结构为String
dataStream.addSink(new FlinkKafkaProducer[String]("broker_list", "topic", new SimpleStringSchema()))
exactly once
每条数据会且仅会被统计一次到结果中,,即某条数据对应的task失败后flink会从checkpoints中恢复上一次checkpoints的计算状态并且从这次checkpoints的offset重新从source中获取过来,==并且把统计结果也恢复到上一次checkpoints成功的状态==,所以这个checkpoints期间上一次失败时已经统计到结果中的数据也会被抹去,所以不会有重复统计,所以称作exactly once
# 需要开启checkpoints并设置CheckpointingMode为EXACTLY_ONCE,在task失败时能进行source重放,因此需要source端支持重放才能实现exactly once sink
streamEnv.enableCheckpointing(1000, CheckpointingMode.EXACTLY_ONCE)
# 假设dataStream数据结构为String
dataStream.addSink(new FlinkKafkaProducer[String]("broker_list", "topic", new SimpleStringSchema()))
端到端一致性
一条数据会且仅会正确处理并且有效sink到下游系统一次,需要实现flink状态一致性 + 写入一致性。
写入一致性有三种方法:1. 幂等写入 2. wal写入 3. 二阶段提交写入
幂等写入
需要下游系统有良好的支持,即对于同一条数据无论写入多少次,结果都一样,flink本身只需要实现状态一致性即可
- 优点:简单,无需flink做其他支持
- 缺点:对下游系统要求高,需要下游系统支持幂等写入
wal写入
配合flink的checkpoint功能,每次checkpoint完成时就对这次checkpoint的数据进行写入,这样一旦某批checkpoint的数据在处理时失败,则这个checkpoint就会失败并从上一个checkpoint完成点重试,所以不会有checkpoint期间那些已经成功的数据被写入到下游系统
- 优点:简单,且对下游系统无任何要求
- 缺点:分批写入,存在写入波峰问题;如果写入的时候发生故障了,则数据会丢失,因为checkpoint已经完成了,flink认为这批数据已经处理成功
二阶段写入
配合flink的checkpoint功能,在一次checkpoint期间,处理成功的数据会通过事务预提交到下游系统,等到这次checkpoint成功完成了,再正式提交到下游系统,即preCommit -> commit, (if failed -> rollback),无论在数据处理期间、预提交期间、正式提交期间失败,均会rollback到上一个checkpoint成功点,重新开始这次checkpoint,所以不会有checkpoint期间那些已经成功的数据被写入到下游系统,实现真正可靠的端到端一致性
- 优点:可靠的端到端一致性,非分批写入(正式提交时不要写入数据,而且修改数据标识为committed)
- 缺点:实现复杂,需要实现TwoPhaseCommitSinkFunction;要求下游系统支持事务性写入;下游系统的消费者也需要注意仅能消费状态为committed的数据,否则消费者仍有可能会消费到uncommitted的数据(比如kafka)