Flink的“Exactly Once”语义指的是在流处理过程中,每条记录只被执行一次,没有重复执行和丢失。
Flink通过以下机制来保证Exactly Once语义:
- Checkpoint机制。将流处理状态和运算位置定期保存到Checkpoint,发生失败后可以从Checkpoint恢复继续执行。
- Write Ahead Log。将输出先写入WAL,然后再提交到下游系统。发生失败可以从WAL恢复丢失的数据。
- 事务提交协议。输出操作使用两阶段提交协议,要么完全成功要么完全失败,保证没有部分提交。
- 幂等Sink。使用可以重复调用的Sink,同一记录的多次输出只会执行一次。
下面通过一个例子来说明:
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.enableCheckpointing(5000); // 每5秒钟开启一次Checkpoint
DataStream<String> stream = env.socketTextStream("localhost", 9999);
// 用作Sink的Kafka Producer
FlinkKafkaProducer010<String> kafkaSink = new FlinkKafkaProducer010<String>("brokerList", "outputTopic",
new SimpleStringSchema());
stream.addSink(kafkaSink);
env.execute();
这个例子从Socket读取数据,发送到Kafka的outputTopic主题。它使用了:
- env.enableCheckpointing(5000)启用了5秒Checkpoint间隔,来保存状态和运算位置。
- FlinkKafkaProducer010这个Sink使用了两阶段提交和幂等语义,来保证Exactly Once输出。
- Kafka本身也具有异常时数据重复传输的机制,可以与Checkpoint机制互相配合。
这样,整个程序既具有Checkpoint来保证Exactly Once语义,又使用幂等Sink和Kafka来确保输出的Exactly Once。