Checkpoint檢查點:使Flink的狀態具有良好的容錯性,通過checkpoint機制,Flink可以在JOB發生錯誤時對作業的狀態和計算位置進行恢復。
示例環境
java.version: 1.8.x
flink.version: 1.11.1
示例數據源 (項目碼雲下載)
Checkpoint.java
import com.flink.examples.DataSource;
import com.google.gson.Gson;
import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.restartstrategy.RestartStrategies;
import org.apache.flink.api.common.time.Time;
import org.apache.flink.api.java.tuple.Tuple3;
import org.apache.flink.runtime.state.StateBackend;
import org.apache.flink.runtime.state.filesystem.FsStateBackend;
import org.apache.flink.streaming.api.CheckpointingMode;
import org.apache.flink.streaming.api.datastream.DataStream;
import org.apache.flink.streaming.api.environment.CheckpointConfig;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* @Description Checkpoint使Flink的狀態具有良好的容錯性,通過checkpoint 機制,Flink可以在JOB發生錯誤時對作業的狀態和計算位置進行恢復。
*/
public class Checkpoint {
/**
* Checkpoint 在默認的情況下僅用於恢復失敗的作業,並不保留,當程序取消時 checkpoint 就會被刪除。
* Checkpoint 由元數據文件、數據文件(與 state backend 相關)組成
* 可通過配置文件中 “state.checkpoints.dir” 配置項來指定元數據文件和數據文件的存儲路徑,另外也可以在代碼中針對單個作業特別指定該配置項。
* 命令行恢復作業:bin/flink run -s :checkpointMetaDataPath [:runArgs] appJob.jar
* Checkpoint機制參見官方:https://ci.apache.org/projects/flink/flink-docs-release-1.11/zh/ops/state/checkpoints.html
* Task故障恢復參見官方:https://ci.apache.org/projects/flink/flink-docs-release-1.11/zh/dev/task_failure_recovery.html
*/
public static void main(String[] args) throws Exception {
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//設置並行度爲1
env.setParallelism(1);
//啓用對數據流作業的檢查快照。數據流的分佈狀態將被定期進行快照。執行Checkpointing的時間間隔爲1分鐘。
env.enableCheckpointing(1000);
//設置檢查點數據存儲的文件系統和位置。
//flink支持的各種文件系統參見:https://ci.apache.org/projects/flink/flink-docs-release-1.13/zh/docs/deployment/filesystems/overview/
//hdfs://是以hadoop做爲文件系統存放flink的checkpoint快照數據
//env.setStateBackend(new FsStateBackend("hdfs://localhost:9000/flink/checkpoint"));
//file:///是以主機本地文件目錄存放flink的checkpoint快照數據(在該目錄下會寫入窗口數據,當發生錯誤job退出再次重後,會從最新快照恢復緩存的數據流重新丟入算子中計算)
env.setStateBackend((StateBackend)new FsStateBackend("file:///test/checkpoint/"));
/*
固定間隔 (Fixed Delay) 重啓策略:
如果沒有啓用checkpointing,則使用無重啓(no restart)策略。
如果啓用了checkpointing,但沒有配置重啓策略,則使用固定間隔(fixed-delay)策略,其中 Integer.MAX_VALUE 參數是嘗試重啓次數。
*/
//配置固定間隔自動重啓策略:失敗後最多重啓3次,每次重啓等待10000ms(10秒)
//env.setRestartStrategy(RestartStrategies.fixedDelayRestart(3, Time.of(10, TimeUnit.SECONDS)));
/*
失敗率 (Failure Rate) 重啓策略:
當超過 failure rate (一個時間段內的失敗次數) 時工作宣告失敗。
在連續兩次重啓嘗試中,該重啓策略會等待一端固定的時間。
*/
//配置失敗率自動重啓策略:時間段內最多3次失敗,5分鐘內(時間段),每次重啓等待10000ms(10秒)
env.setRestartStrategy(RestartStrategies.failureRateRestart(3, Time.of(5, TimeUnit.MINUTES), Time.of(10, TimeUnit.SECONDS)));
/*
無重啓 (No Restart) 策略:
沒有任何工作重啓,若工作失敗則直接宣告失敗。
*/
//配置無自動重啓策略
//env.setRestartStrategy(RestartStrategies.noRestart());
//檢查快照配置
CheckpointConfig config = env.getCheckpointConfig();
// 1分鐘內完成快照生成,否則超時,超時取消本次快照檢查點
config.setCheckpointTimeout(60 * 1000);
//【checkpoint最小間隔】單位:毫秒,設置檢查點之間的最小暫停時間。此設置定義了要使用多久後在觸發另一個檢查點
config.setMinPauseBetweenCheckpoints(500);
//ExternalizedCheckpointCleanup 配置項定義了當作業取消時,對作業 checkpoint 的操作:
//ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION:當作業取消時,保留作業的 checkpoint。注意,這種情況下,需要手動清除該作業保留的 checkpoint。
//ExternalizedCheckpointCleanup.DELETE_ON_CANCELLATION:當作業取消時,刪除作業的 checkpoint。僅當作業失敗時,作業的 checkpoint 纔會被保留。
config.enableExternalizedCheckpoints(CheckpointConfig.ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION);
//設置檢查點模式(exactly-once 或 at-least-once)。
config.setCheckpointingMode(CheckpointingMode.EXACTLY_ONCE);
//設置可同時進行的最大檢查點嘗試次數。
config.setMaxConcurrentCheckpoints(1);
//測試數據集
List<Tuple3<String, String, Integer>> tuple3List = DataSource.getTuple3ToList();
//流數據處理
DataStream<String> dataStream = env.fromCollection(tuple3List).flatMap(new FlatMapFunction<Tuple3<String,String,Integer>, String>() {
@Override
public void flatMap(Tuple3<String, String, Integer> value, Collector<String> out) throws Exception {
System.out.println(new Gson().toJson(value));
if (!value.f1.equals("man")){
String msg = value.f0 + " sex is not 'man' , throw error!";
System.out.println(msg);
throw new RuntimeException(msg);
}
out.collect(value.f0);
}
});
//打印
dataStream.print().name("Checkpoint");
//執行job
env.execute("flink Checkpoint job");
}
}
打印結果
{"f0":"張三","f1":"man","f2":20}
張三
{"f0":"李四","f1":"girl","f2":24}
李四 sex is not 'man' , throw error!
{"f0":"張三","f1":"man","f2":20}
張三
{"f0":"李四","f1":"girl","f2":24}
李四 sex is not 'man' , throw error!
{"f0":"張三","f1":"man","f2":20}
張三
{"f0":"李四","f1":"girl","f2":24}
李四 sex is not 'man' , throw error!
Exception in thread "main" java.util.concurrent.ExecutionException: org.apache.flink.runtime.client.JobExecutionException: Job execution failed.
...略