flink 中的一个大的特性就是exactly-once的特性,我们在一般的流处理程序中,会有三种处理语义

  • at most once : 至多一次,表示一条消息不管后续处理成功与否只会被消费处理一次,那么就存在数据丢失可能
  • exactly once : 精确一次,表示一条消息从其消费到后续的处理成功,只会发生一次
  • at least once :至少一次,表示一条消息从消费到后续的处理成功,可能会发生多次

我们在程序处理中,通常要求程序满足exactly-once,就是确保数据的准确性,不丢失,不重复,但是实现这样的功能是比较复杂的,在flink中,是如何提供精确一次的特性呢?

我觉得应该有两方面的因素,一个是flink的checkpoint特性,另外一个是两阶段提交,这两方面的组合,让flink有了精确一次的能力。

flink的checkpoint机制是把程序处理的中间状态保存下来,当程序失败可以从最新的checkpoint中恢复,通过checkpoint的机制,flink可以实现精确一次和至少一次的语义。

barrier对齐发生在一个处理节点需要接收上游不同处理节点的数据,由于不同的上游节点数据处理速度不一致,那么就会导致下游节点接收到 barrier的时间点也会不一致,这时候就需要使用barrier对齐机制:在同一checkpoint中,先到达的barrier是否需要等待其他处理节点barrier达到后在发送后续数据,barrier将数据流分为前后两个checkpoint(chk n,chk n+1)的概念,如果不等待那么就会导致chk n的阶段处理了chk n+1阶段的数据,但是在source端所记录的消费偏移量又一致,如果chk n成功之后,后续的任务处理失败,任务重启会消费chk n+1阶段数据,就会到致数据重复消息,如果barrier等待就不会出现这样情况,因此barrier需要对齐那么就是实现exectly once语义,否则实现的是at least once语义。由于状态是属于flink内部存储,所以flink 仅仅满足内部exectly once语义。