Flink的checkpoint 源码分析(3)

332 阅读4分钟

Flink 1.10版本的checkpoint机制在StreamExecutionEnvironment中进行了修改。具体的实现可以参考Flink的官方文档。 在Flink 1.10版本中,StreamExecutionEnvironment中引入了一个新的CheckpointListener接口。这个接口用于监听checkpoint的状态变化,并在需要时触发checkpoint。具体来说,我们可以实现CheckpointListener接口,并在beginWindow()方法中注册自己的监听器。之后,每次执行窗口计算时,CheckpointListener接口中的监听器都会自动调用checkpoint()方法来触发一次checkpoint。 以下是一个简单的例子,演示了如何在StreamExecutionEnvironment中注册自己的CheckpointListener

typescript
Copy code
public class MyCheckpointListener implements CheckpointListener {

  @Override
  public void onCheckpoint(long checkpointId) {
    // 这里是具体的计算逻辑,如果出现问题,可以在这里触发checkpoint
  }
}

public class MyStreamExecutionEnvironment extends StreamExecutionEnvironment {

  private static final long serialVersionUID = 1L;

  private List<CheckpointListener> listeners = new ArrayList<>();

  @Override
  public void open(Configuration parameters) throws Exception {
    // 这里是通用的初始化逻辑,可以根据具体的需求进行初始化
  }

  @Override
  public void run(SourceFunction<Integer> sourceFunction) throws Exception {
    // 这里是具体的计算逻辑,同时也是需要进行checkpoint的地方
  }

  @Override
  public void cancel() {
    // 这里是取消checkpoint的逻辑
  }

  @Override
  public void onTimer(long timestamp, CheckpointMark checkpointMark) {
    // 这里是具体的时间触发逻辑
  }

  @Override
  public void onTrigger(ProcessingTimeService trigger) {
    // 这里是具体的窗口触发逻辑
  }

  @Override
  public void notifyCheckpointComplete(long checkpointId) {
    // 这里是通知所有的checkpoint listener进行checkpoint
  }

  @Override
  public void addCheckpointListener(CheckpointListener listener) {
    // 这里是注册checkpoint listener的逻辑
  }

  @Override
  public void removeCheckpointListener(CheckpointListener listener) {
    // 这里是注销checkpoint listener的逻辑
  }

  @Override
  public void clearState() throws Exception {
    // 这里是清除状态信息的逻辑,需要根据具体情况进行调整
  }
}

在上面的例子中,我们实现了一个MyCheckpointListener类来监听checkpoint的状态变化,并在需要时触发checkpoint。同时,我们还在MyStreamExecutionEnvironment类中注册了自己的CheckpointListener,并在run()方法中调用addCheckpointListener()方法来注册自己为checkpoint listener。 在使用MyCheckpointListener时,我们需要实现CheckpointListener接口中的方法,并在需要时触发checkpoint。具体来说,我们需要在计算逻辑中进行处理,如果出现问题,就在checkpoint()方法中进行处理,例如保存当前的状态信息等。 需要注意的是,在使用CheckpointListener时,我们需要注意处理状态信息的细节,以确保在程序出现问题时能够正确地处理状态信息。此外,在触发checkpoint时,我们需要考虑如何通知所有的checkpoint listener进行checkpoint。在Flink中,我们可以使用StreamTaskState来通知所有的checkpoint listener进行checkpoint。具体来说,我们可以在计算逻辑中设置isCheckpointed()标志,并在需要进行checkpoint时将isCheckpointed()标志设置为true,然后将当前的状态信息传递给所有的checkpoint listener进行处理。

checkpoint相关流程在StreamExecutionEnvironmentcheckpoint()方法中进行了定义。具体来说,我们可以通过调用checkpoint()方法来触发checkpoint,具体的流程如下:

  1. 如果当前的StreamExecutionEnvironment正在执行一个窗口,则会调用窗口计算任务的finishWindow()方法,并触发一次checkpoint。
  2. 如果当前的StreamExecutionEnvironment正在执行一个任务,则会通过StreamTaskState将当前任务的状态信息传递给所有的checkpoint listener,并触发一次checkpoint。
  3. 如果当前的StreamExecutionEnvironment正在等待一个任务完成,则会将当前任务的状态信息封装成CheckpointMark对象,然后调用awaitTermination()方法来等待任务完成。
  4. 在等待任务完成时,如果任务出现异常,则会调用getFailedTaskContexts()方法来获取未成功完成的任务的TaskAttemptContext对象,并将这些对象封装成FailedCheckpointContext对象。然后,会调用checkpointMarkProducer.sendCheckpointMark(FailedCheckpointContext checkpointContext)方法来将这些对象发送给checkpoint listener。
  5. 在调用checkpoint()方法时,会传递一个CheckpointMark对象作为参数。这个CheckpointMark对象包含了当前任务的状态信息,可以用于指示当前任务是否已经成功进行了checkpoint。 需要注意的是,在使用CheckpointMark对象时,需要根据具体的情况进行设置。例如,如果我们希望将checkpoint的状态信息记录到数据库中,我们需要使用CheckpointMark对象的getState()方法来获取状态信息。同时,如果我们需要在checkpoint之后执行某些特定的操作,我们可以在发送CheckpointMark对象时指定相关的参数。