Blog
trinofault-tolerant-executionetlexchange-managerdata-platform

Trino Fault-tolerant Execution 심화 — Exchange Manager 와 재시도 정책

장시간 ETL 배치 도중 워커가 죽어도 쿼리를 살리는 Trino 의 FTE 를 깊게 들여다봅니다. QUERY vs TASK 재시도 정책, exchange manager(스풀 저장소) 구성, 스팟 인스턴스 운영, 그리고 대화형 쿼리에서 켜면 안 되는 이유까지.

Data Dynamics2026년 6월 5일12 min read

Trino 의 기본 실행 모델은 "all-or-nothing" 입니다. 쿼리를 구성하는 태스크 중 하나라도 실패하면 쿼리 전체가 실패합니다. 짧은 대화형 쿼리에서는 다시 던지면 그만이지만, 몇 시간짜리 ETL 배치가 마지막 단계에서 워커 한 대가 죽어 통째로 날아간다면 이야기가 다릅니다.

Fault-tolerant Execution(FTE) 은 이 문제를 해결합니다. 중간 결과를 외부 스토리지에 스풀해 두고, 실패한 단위만 다른 워커에서 재시도합니다. 이 글은 FTE 가 내부적으로 어떻게 동작하는지, 어떻게 설정하는지, 그리고 언제 켜고 언제 꺼야 하는지를 정리합니다.

1. 왜 FTE 가 필요한가 — 기본 실행 모델의 한계

일반 모드에서 Trino 는 스테이지 간 데이터를 메모리/네트워크로 직접 스트리밍(streaming exchange)합니다. 빠르지만, 중간 데이터가 어디에도 보존되지 않습니다.

[일반 모드] Stage1 ──메모리 스트리밍──> Stage2 ──> Stage3
            워커 한 대라도 죽으면 → 전체 쿼리 FAIL → 처음부터 다시

데이터 규모가 크고 실행이 길수록 "도중에 워커가 죽을 확률"이 올라갑니다. 스팟 인스턴스를 쓰면 회수(reclaim)로 워커가 수시로 사라지므로 이 확률은 더 커집니다. 긴 배치를 매번 처음부터 재실행하는 것은 비용과 시간 모두 낭비입니다.

2. FTE 의 핵심 아이디어 — 중간 결과 스풀

FTE 는 스테이지 간 데이터를 직접 스트리밍하는 대신, exchange manager 를 통해 외부 스토리지(S3/GCS/HDFS 등)에 스풀합니다. 중간 결과가 보존되므로, 워커가 죽어도 그 지점부터 다시 시작할 수 있습니다.

[FTE 모드] Stage1 ──> [Exchange: S3 스풀] ──> Stage2 ──> [Exchange: S3 스풀] ──> Stage3
           워커가 죽으면 → 스풀된 중간 결과로 실패한 부분만 재시도
일반(streaming)FTE(spooling)
스테이지 간 데이터메모리/네트워크 직접 전달exchange manager 가 외부 스토리지에 스풀
워커 소실 시쿼리 전체 실패실패 단위만 재시도
지연(latency)낮음스풀 I/O 만큼 증가
적합대화형 쿼리장시간 ETL 배치

3. 두 가지 재시도 정책 — QUERY vs TASK

FTE 는 retry-policy 로 재시도 단위를 정합니다.

# etc/config.properties
retry-policy=TASK
정책재시도 단위동작적합
QUERY쿼리 전체실패 시 쿼리를 통째로 다시 실행짧은 쿼리가 많은 대화형 클러스터
TASK개별 태스크실패한 태스크만 다른 워커에서 재시도장시간·대규모 ETL 배치

QUERY 정책

쿼리가 실패하면 코디네이터가 자동으로 전체를 재실행합니다. 사용자는 실패를 모르고 결과만 받습니다. 짧은 쿼리에 적합하고, exchange manager 없이도(작은 결과는 코디네이터 메모리에) 동작할 수 있지만, 큰 쿼리에는 exchange manager 가 권장됩니다.

TASK 정책

쿼리를 구성하는 개별 태스크 단위로 재시도합니다. 반드시 exchange manager 가 필요합니다. 장시간 배치에서 한 워커가 죽어도 그 워커가 하던 태스크만 살아있는 다른 워커로 넘겨 재실행하므로, 전체를 다시 돌리지 않습니다. 또한 TASK 모드는 적응형 태스크 스케줄링이 가능해, 워커 수가 변해도(오토스케일·스팟) 유연하게 대응합니다.

규칙: 대화형 클러스터는 QUERY, ETL/배치 클러스터는 TASK. 하나의 클러스터에서 둘을 섞고 싶다면 세션 레벨로 전환할 수 있습니다 — SET SESSION retry_policy = 'TASK'.

4. Exchange Manager 구성

TASK 정책(그리고 큰 QUERY)에는 exchange manager 가 필수입니다. 스풀 저장소를 지정합니다.

# etc/exchange-manager.properties
exchange-manager.name=filesystem
exchange.base-directories=s3://trino-exchange/spool
exchange.encryption-enabled=true

S3 자격증명·엔드포인트는 파일시스템 설정을 따릅니다.

# 같은 파일 또는 config 에서 S3 접근 설정
exchange.s3.region=ap-northeast-2
exchange.s3.endpoint=https://s3.ap-northeast-2.amazonaws.com

스풀 저장소 선택

저장소장점고려사항
S3 / GCS / Azure Blob무제한 용량, 클러스터와 분리네트워크 지연, 요청 비용
HDFS온프레미스 기존 자산 활용NameNode 부하
로컬 디스크(여러 워커 공유 X)빠름워커 소실 시 스풀도 소실 → FTE 무의미

핵심: 스풀 저장소는 워커와 생명주기가 분리되어야 합니다. 워커가 죽었을 때 스풀이 남아있어야 재시도가 가능하기 때문에, 로컬 디스크는 부적합하고 오브젝트 스토리지가 정석입니다.

여러 저장소 분산

대규모 클러스터에서는 스풀 I/O 가 병목이 될 수 있어, 여러 디렉터리/버킷에 분산합니다.

exchange.base-directories=s3://trino-exchange-1/spool,s3://trino-exchange-2/spool

5. 관련 튜닝 파라미터

FTE 의 동작을 세밀하게 조정하는 옵션들입니다.

파라미터역할
fault-tolerant-execution-task-memoryTASK 모드에서 태스크당 메모리 추정치(스케줄링 단위)
fault-tolerant-execution-target-task-input-size태스크 입력 목표 크기 (태스크 분할 입도)
fault-tolerant-execution-target-task-split-count태스크당 split 목표 수
fault-tolerant-execution-max-task-split-count태스크당 split 상한
exchange.compression-enabled스풀 데이터 압축으로 I/O·비용 절감
query.low-memory-killer.policy메모리 부족 시 죽일 대상 선정 정책

압축은 거의 항상 켜는 것이 이득입니다(네트워크·스토리지 비용 절감). 태스크 입력 크기는 너무 작으면 오버헤드가, 너무 크면 재시도 비용이 커지므로 워크로드에 맞춰 조정합니다.

6. FTE 와 스팟 인스턴스 — 비용 절감의 핵심

FTE 의 가장 강력한 활용처는 스팟 인스턴스로 워커를 운영하는 것입니다.

온디맨드 워커 100%        →  안정적이지만 비쌈
스팟 워커 + FTE(TASK)     →  회수돼도 태스크 재시도로 완주, 비용 최대 70~90% 절감

스팟 회수로 워커가 갑자기 사라져도, 스풀된 중간 결과 덕분에 살아있는 워커가 태스크를 이어받습니다. Kubernetes 환경이라면 코디네이터는 온디맨드, 워커는 스팟 + FTE 조합이 정석입니다. (Kubernetes 배포는 별도 글 "Trino 를 Kubernetes 에 배포하기"에서 다뤘습니다.)

7. 트레이드오프 — FTE 를 켜면 잃는 것

FTE 는 공짜가 아닙니다.

  • 지연 증가: 모든 스테이지 경계에서 외부 스토리지에 쓰고 다시 읽으므로, 짧은 쿼리는 오히려 느려집니다. 밀리초~초 단위 대화형 쿼리에는 부적합합니다.
  • 스토리지 비용/요청: S3 PUT/GET 요청과 저장 용량 비용이 발생합니다. 압축으로 완화하세요.
  • 운영 복잡도: exchange manager, 스풀 버킷, 권한, 정리(lifecycle) 정책을 관리해야 합니다.
워크로드권장
BI 대시보드, 대화형 분석FTE 끄기 (streaming)
짧은 쿼리 다수QUERY (선택)
장시간 ETL, 대규모 조인/집계TASK + exchange manager
스팟 워커 클러스터TASK + exchange manager (필수에 가까움)

8. 검증 — FTE 가 실제로 동작하는지

-- 현재 세션의 재시도 정책 확인
SHOW SESSION LIKE 'retry_policy';
 
-- 세션 단위로 전환 (대화형 클러스터에서 무거운 배치 하나만 FTE 로)
SET SESSION retry_policy = 'TASK';

실행 후 코디네이터 Web UI 의 Query Detail 에서 재시도된 태스크가 있었는지, exchange 가 spooling 으로 동작했는지 확인할 수 있습니다. 스팟 회수 테스트로 워커를 의도적으로 죽여보고 쿼리가 완주하는지 검증하는 것을 권장합니다.

9. 스풀 저장소 정리 (Lifecycle)

스풀 데이터는 쿼리 종료 시 Trino 가 정리하지만, 비정상 종료·중단으로 고아 객체가 남을 수 있습니다. 버킷에 lifecycle 정책(예: prefix spool/ 의 객체를 1~3일 후 자동 삭제)을 걸어 비용 누수를 막으세요.

S3 Lifecycle Rule: prefix "spool/", expire after 2 days

10. 정리

항목일반 모드FTE 모드
실패 처리쿼리 전체 실패태스크/쿼리 단위 재시도
중간 데이터메모리 스트리밍exchange manager 스풀
지연낮음스풀 I/O 만큼 증가
스팟 운영위험안전 (큰 비용 절감)
적합 워크로드대화형장시간 배치

FTE 는 "안정성을 위해 약간의 지연을 지불"하는 기능입니다. 대화형 클러스터에는 켜지 말고, 장시간 ETL 과 스팟 기반 배치 클러스터에는 TASK 정책 + 오브젝트 스토리지 exchange manager 로 구성하세요. 스풀 압축을 켜고 버킷에 lifecycle 정책을 걸면, 안정성과 비용 두 마리를 모두 잡을 수 있습니다.


이 글은 Trino 440번대 기준으로 작성되었습니다. 대규모 배치의 안정화나 스팟 기반 비용 최적화가 필요하시면 언제든 문의해 주세요.

— Data Dynamics 엔지니어링 팀