Task Failure Recovery
Task Failure Recovery (태스크 장애 복구)
태스크 장애가 발생하면 Flink는 실패한 태스크와 영향을 받은 다른 태스크를 재시작하여 잡을 정상 상태로 복구해야 해요. 재시작 전략과 장애 조치(failover) 전략이 태스크 재시작을 제어해요.
본문
태스크 장애가 발생하면 Flink는 실패한 태스크와 영향을 받은 다른 태스크를 재시작하여 잡을 정상 상태로 복구해야 해요.
재시작 전략(Restart strategies)과 장애 조치 전략(Failover strategies)이 태스크 재시작을 제어하는 데 사용돼요. 재시작 전략은 실패한/영향을 받은 태스크를 재시작할 수 있는지 그리고 언제 재시작할지 결정해요. 장애 조치 전략은 잡을 복구하기 위해 어떤 태스크를 재시작해야 하는지 결정해요.
재시작 전략 (Restart Strategies)
클러스터는 잡 특정 재시작 전략이 정의되지 않았을 때 항상 사용되는 기본 재시작 전략으로 시작할 수 있어요. 잡이 재시작 전략과 함께 제출되면 이 전략이 클러스터의 기본 설정을 재정의해요.
기본 재시작 전략은 [Flink 구성 파일]({{< ref "docs/deployment/config#flink-configuration-file" >}})로 설정돼요. 구성 매개변수 restart-strategy.type이 어떤 전략을 사용할지 정의해요. 체크포인팅이 활성화되지 않으면 no restart 전략이 사용돼요. 체크포인팅이 활성화되고 재시작 전략이 구성되지 않으면 exponential-delay 재시작 전략과 exponential-delay 관련 구성 옵션의 기본값이 사용돼요. 지원되는 값을 배우려면 아래의 사용 가능한 재시작 전략 목록을 참조하세요.
각 재시작 전략은 동작을 제어하는 자체 매개변수 집합을 가져요. 이 값들도 구성 파일에 설정돼요. 각 재시작 전략의 설명에는 해당 구성 값에 대한 더 많은 정보가 포함돼 있어요.
{{< generated/restart_strategy_configuration >}}
기본 재시작 전략을 정의하는 것 외에도 각 Flink 잡에 대해 특정 재시작 전략을 정의할 수 있어요.
다음 예제는 잡에 고정 지연 재시작 전략을 설정하는 방법을 보여줘요. 실패 시 시스템은 잡을 3번 재시작하려 시도하고 연속 재시작 시도 사이에 10초를 기다려요.
Configuration config = new Configuration();
config.set(RestartStrategyOptions.RESTART_STRATEGY, "fixed-delay");
config.set(RestartStrategyOptions.RESTART_STRATEGY_FIXED_DELAY_ATTEMPTS, 3); // number of restart attempts
config.set(RestartStrategyOptions.RESTART_STRATEGY_FIXED_DELAY_DELAY, Duration.ofSeconds(10)); // delay
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(config);
config = Configuration()
config.set_string('restart-strategy.type', 'fixed-delay')
config.set_string('restart-strategy.fixed-delay.attempts', '3') # number of restart attempts
config.set_string('restart-strategy.fixed-delay.delay', '10000 ms') # delay
env = StreamExecutionEnvironment.get_execution_environment(config)
다음 섹션은 재시작 전략 특정 구성 옵션을 설명해요.
고정 지연 재시작 전략 (Fixed Delay Restart Strategy)
고정 지연 재시작 전략은 주어진 횟수만큼 잡을 재시작하려 시도해요. 최대 시도 횟수를 초과하면 잡은 결국 실패해요. 두 연속 재시작 시도 사이에 재시작 전략은 고정된 시간을 기다려요.
이 전략은 [Flink 구성 파일]({{< ref "docs/deployment/config#flink-configuration-file" >}})에서 다음 구성 매개변수를 설정하여 기본값으로 활성화돼요.
restart-strategy.type: fixed-delay
{{< generated/fixed_delay_restart_strategy_configuration >}}
예를 들어:
restart-strategy.fixed-delay.attempts: 3
restart-strategy.fixed-delay.delay: 10 s
고정 지연 재시작 전략은 프로그래밍 방식으로도 설정할 수 있어요:
Configuration config = new Configuration();
config.set(RestartStrategyOptions.RESTART_STRATEGY, "fixed-delay");
config.set(RestartStrategyOptions.RESTART_STRATEGY_FIXED_DELAY_ATTEMPTS, 3); // number of restart attempts
config.set(RestartStrategyOptions.RESTART_STRATEGY_FIXED_DELAY_DELAY, Duration.ofSeconds(10)); // delay
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(config);
config = Configuration()
config.set_string('restart-strategy.type', 'fixed-delay')
config.set_string('restart-strategy.fixed-delay.attempts', '3') # number of restart attempts
config.set_string('restart-strategy.fixed-delay.delay', '10000 ms') # delay
env = StreamExecutionEnvironment.get_execution_environment(config)
지수적 지연 재시작 전략 (Exponential Delay Restart Strategy)
두 연속 재시작 시도 사이에 지수적 지연 재시작 전략은 최대 값에 도달할 때까지 계속 지수적으로 증가시켜요. 그런 다음 지연을 최대 값으로 유지해요.
잡이 올바르게 실행되면 지수적 지연 값은 일정 시간 후에 재설정돼요. 이 임계값은 구성할 수 있어요.
restart-strategy.type: exponential-delay
{{< generated/exponential_delay_restart_strategy_configuration >}}
예를 들어:
restart-strategy.exponential-delay.initial-backoff: 10 s
restart-strategy.exponential-delay.max-backoff: 2 min
restart-strategy.exponential-delay.backoff-multiplier: 1.4
restart-strategy.exponential-delay.reset-backoff-threshold: 10 min
restart-strategy.exponential-delay.jitter-factor: 0.1
restart-strategy.exponential-delay.attempts-before-reset-backoff: 10
지수적 지연 재시작 전략은 프로그래밍 방식으로도 설정할 수 있어요:
Configuration config = new Configuration();
config.set(RestartStrategyOptions.RESTART_STRATEGY, "exponential-delay");
config.set(RestartStrategyOptions.RESTART_STRATEGY_EXPONENTIAL_DELAY_INITIAL_BACKOFF, Duration.ofMillis(1));
config.set(RestartStrategyOptions.RESTART_STRATEGY_EXPONENTIAL_DELAY_MAX_BACKOFF, Duration.ofMillis(1000));
config.set(RestartStrategyOptions.RESTART_STRATEGY_EXPONENTIAL_DELAY_BACKOFF_MULTIPLIER, 1.1); // exponential multiplier
config.set(RestartStrategyOptions.RESTART_STRATEGY_EXPONENTIAL_DELAY_RESET_BACKOFF_THRESHOLD, Duration.ofMillis(2000)); // threshold duration to reset delay to its initial value
config.set(RestartStrategyOptions.RESTART_STRATEGY_EXPONENTIAL_DELAY_JITTER_FACTOR, 0.1); // jitter
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(config);
Still not supported in Python API.
예제
지수적 지연 재시작 전략이 어떻게 작동하는지 설명하는 예제가 있어요.
restart-strategy.exponential-delay.initial-backoff: 1 s
restart-strategy.exponential-delay.backoff-multiplier: 2
restart-strategy.exponential-delay.max-backoff: 10 s
# For convenience of description, jitter is turned off here
restart-strategy.exponential-delay.jitter-factor: 0
initial-backoff = 1s는 예외가 처음 발생하면 잡이 재시도 전에 1초 지연된다는 뜻이에요.backoff-multiplier = 2는 잡에 연속 예외가 있으면 지연 시간이 매번 두 배가 된다는 뜻이에요.max-backoff = 10 s는 재시도 지연이 최대 10초라는 뜻이에요.
이 매개변수를 기반으로:
- 예외가 발생하고 잡을 1번째로 재시도해야 할 때, 잡은 1초 지연된 후 재시도해요.
- 예외가 발생하고 잡을 2번째로 재시도해야 할 때, 잡은 2초 지연된 후 재시도해요.
- 예외가 발생하고 잡을 3번째로 재시도해야 할 때, 잡은 4초 지연된 후 재시도해요.
- 예외가 발생하고 잡을 4번째로 재시도해야 할 때, 잡은 8초 지연된 후 재시도해요.
- 예외가 발생하고 잡을 5번째로 재시도해야 할 때, 잡은 10초 지연된 후 재시도해요 (두 배로 늘리면 상한을 초과하므로 상한인 10초가 지연 시간으로 사용됨)..
- 5번째 재시도에서 지연 시간이 상한(max-backoff)에 도달했으므로, 5번째 재시도 후 지연 시간은 항상 10초예요. 각 실패 후 10초 지연된 후 재시도해요.
restart-strategy.exponential-delay.jitter-factor: 0.1
restart-strategy.exponential-delay.attempts-before-reset-backoff: 8
restart-strategy.exponential-delay.reset-backoff-threshold: 6 min
jitter-factor = 0.1은 각 지연 시간에 임의 값이 더해지거나 빼지며, 임의 값의 비율 범위는 0.1 이내라는 뜻이에요. 예를 들어:- 3번째 재시도에서 잡 지연 시간은 3.6초와 4.4초 사이예요 (3.6 = 4 * 0.9, 4.4 = 4 * 1.1).
- 4번째 재시도에서 잡 지연 시간은 7.2초와 8.8초 사이예요 (7.2 = 8 * 0.9, 8.8 = 8 * 1.1).
- 임의 값은 여러 잡이 동시에 재시작되는 것을 방지할 수 있으므로, 프로덕션 환경에서 jitter-factor를 0으로 설정하는 것은 권장되지 않아요.
attempts-before-reset-backoff = 8은 잡이 8번 연속 재시도 후에도 예외를 만나면 실패한다는 뜻이에요 (더 이상 재시도하지 않음).reset-backoff-threshold = 6 min은 잡이 예외 없이 6분간 실행되면 지연 시간과 재시도 카운터가 재설정된다는 뜻이에요. 즉 잡에서 예외가 발생했을 때 마지막 예외가 6분 전이라면 재시도 지연 시간은 1초로 재설정되고 현재 재시도 카운터는 1로 재설정돼요.
실패율 재시작 전략 (Failure Rate Restart Strategy)
실패율 재시작 전략은 실패 후 잡을 재시작하지만, failure rate(시간 간격당 실패)를 초과하면 잡은 결국 실패해요. 두 연속 재시작 시도 사이에 재시작 전략은 고정된 시간을 기다려요.
이 전략은 [Flink 구성 파일]({{< ref "docs/deployment/config#flink-configuration-file" >}})에서 다음 구성 매개변수를 설정하여 기본값으로 활성화돼요.
restart-strategy.type: failure-rate
{{< generated/failure_rate_restart_strategy_configuration >}}
restart-strategy.failure-rate.max-failures-per-interval: 3
restart-strategy.failure-rate.failure-rate-interval: 5 min
restart-strategy.failure-rate.delay: 10 s
실패율 재시작 전략은 프로그래밍 방식으로도 설정할 수 있어요:
Configuration config = new Configuration();
config.set(RestartStrategyOptions.RESTART_STRATEGY, "failure-rate");
config.set(RestartStrategyOptions.RESTART_STRATEGY_FAILURE_RATE_MAX_FAILURES_PER_INTERVAL, 3); // max failures per interval
config.set(RestartStrategyOptions.RESTART_STRATEGY_FAILURE_RATE_FAILURE_RATE_INTERVAL, Duration.ofMinutes(5)); // time interval for measuring failure rate
config.set(RestartStrategyOptions.RESTART_STRATEGY_FAILURE_RATE_DELAY, Duration.ofSeconds(10)); // delay
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(config);
config = Configuration()
config.set_string('restart-strategy.type', 'failure-rate')
config.set_string('restart-strategy.failure-rate.max-failures-per-interval', '3') # max failures per interval
config.set_string('restart-strategy.failure-rate.failure-rate-interval', '5 min') # time interval for measuring failure rate
config.set_string('restart-strategy.failure-rate.delay', '10 s') # delay
env = StreamExecutionEnvironment.get_execution_environment(config)
재시작 없음 전략 (No Restart Strategy)
잡이 직접 실패하고 재시작이 시도되지 않아요.
restart-strategy.type: none
재시작 없음 전략은 프로그래밍 방식으로도 설정할 수 있어요:
Configuration config = new Configuration();
config.set(RestartStrategyOptions.RESTART_STRATEGY, "none");
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(config);
config = Configuration()
config.set_string('restart-strategy.type', 'none')
env = StreamExecutionEnvironment.get_execution_environment(config)
폴백 재시작 전략 (Fallback Restart Strategy)
클러스터에 정의된 재시작 전략이 사용돼요. 이는 체크포인팅을 활성화하는 스트리밍 프로그램에 유용해요. 기본적으로 다른 재시작 전략이 정의되지 않으면 지수적 지연 재시작 전략이 선택돼요.
기본 재시작 전략
체크포인트가 활성화되고 사용자가 재시작 전략을 지정하지 않으면, [Exponential delay restart strategy]({{< ref "docs/ops/state/task_failure_recovery" >}}#exponential-delay-restart-strategy)가 현재 기본 재시작 전략이에요. Flink 사용자에게 지수적 지연 재시작 전략을 강력히 권장하는데, 이 전략을 사용하면 예외가 드물게 발생할 때 잡이 빠르게 재시도될 수 있고, 예외가 자주 발생할 때는 외부 구성 요소의 눈사태(avalanche)를 피할 수 있기 때문이에요. 이유는 다음과 같아요:
- 모든 재시작 전략은 잡을 재시작할 때 일정 시간 지연하여 잦은 재시도가 외부 구성 요소에 더 큰 압력을 주는 것을 피해요.
- 지수적 지연 재시작 전략을 제외한 모든 재시작 전략의 지연 시간은 고정돼요.
- 지연 시간이 너무 짧게 설정되면 짧은 시간 안에 예외가 자주 발생할 때 외부 서비스의 마스터 노드에 자주 접근하여 외부 서비스의 눈사태를 일으킬 수 있어요. 예: 많은 Flink 잡이 Kafka를 소비하고 있는데 Kafka 클러스터가 충돌하면 많은 Flink 잡이 동시에 자주 재시도되어 눈사태를 일으킬 가능성이 있어요.
- 지연 시간이 너무 길게 설정되면 예외가 드물게 발생할 때 잡이 재시도하기 전에 오래 기다려야 하므로 잡 가용성이 낮아져요.
- 지수적 지연 재시작 전략의 각 재시도 지연 시간은 최대 지연 시간에 도달할 때까지 지수적으로 증가해요.
- 지연 시간의 초기 값이 더 짧으므로, 예외가 드물게 발생할 때 잡이 빠르게 재시도되어 잡 가용성을 높여요.
- 짧은 시간 안에 예외가 자주 발생하면 지수적 지연 재시작 전략이 재시도 빈도를 줄여 외부 서비스의 눈사태를 피해요.
- 게다가 지수적 지연 재시작 전략의 지연 시간은 jitter-factor 구성 옵션을 지원해요.
- 지터 팩터는 각 지연 시간에 임의 값을 더하거나 뺀다.
- 여러 잡이 지수적 지연 재시작 전략을 사용하고 모든 구성 옵션 값이 정확히 같더라도 지터 팩터는 이 잡들이 서로 다른 시간에 재시작되게 해요.
장애 조치 전략 (Failover Strategies)
Flink는 [Flink 구성 파일]({{< ref "docs/deployment/config#flink-configuration-file" >}})에서 구성 매개변수 jobmanager.execution.failover-strategy로 구성할 수 있는 다양한 장애 조치 전략을 지원해요.
| Failover Strategy | jobmanager.execution.failover-strategy 값 |
|---|---|
| Restart all | full |
| Restart pipelined region | region |
모든 재시작 장애 조치 전략 (Restart All Failover Strategy)
이 전략은 태스크 장애를 복구하기 위해 잡의 모든 태스크를 재시작해요.
파이프라인 영역 재시작 장애 조치 전략 (Restart Pipelined Region Failover Strategy)
이 전략은 태스크를 분리된 영역으로 그룹화해요. 태스크 장애가 감지되면 이 전략은 장애를 복구하기 위해 재시작해야 하는 가장 작은 영역 집합을 계산해요. 일부 잡의 경우 이는 Restart All 장애 조치 전략에 비해 재시작되는 태스크가 더 적을 수 있어요.
영역은 파이프라인 데이터 교환을 통해 통신하는 태스크 집합이에요. 즉 배치 데이터 교환이 영역의 경계를 나타내요.
DataStream/Table/SQL 잡 데이터 교환은 [ExecutionConfig]({{< ref "docs/dev/datastream/execution/execution_configuration" >}})를 통해 설정할 수 있는 ExecutionMode에 의해 결정되며, 스트리밍 모드에서는 파이프라인이고 배치 모드에서는 기본적으로 배치예요.
재시작할 영역은 다음과 같이 결정돼요:
- 실패한 태스크를 포함하는 영역이 재시작돼요.
- 재시작될 영역이 결과 파티션을 필요로 하는데 사용할 수 없으면, 결과 파티션을 생성하는 영역도 재시작돼요.
- 영역이 재시작되면 해당 영역의 모든 소비 영역도 재시작돼요. 이는 비결정적 처리나 파티셔닝이 다른 파티션을 초래할 수 있으므로 데이터 일관성을 보장하기 위해서예요.