Keyboard shortcuts

Press ← or → to navigate between chapters

Press ? to show this help

Press Esc to hide this help

상태를 유지하는 스트리밍 변환

상태 기반 변환은 현재 출력이 이전에 처리한 행의 정보에 의존하는 변환입니다. 행 사이에 유지하는 정보를 상태(state)라고 하며, 새 행은 이를 읽거나 갱신할 수 있습니다. 상태 없는 변환은 행 하나만 보고 계산하지만 상태 기반 변환은 행별 처리를 유지하면서 과거 정보를 활용합니다.

누적 상태 예시

가상 센서 스트림에서 Day 값별로 hot이 나타난 횟수를 누적한다고 가정합니다. 표의 위쪽일수록 최근에 들어온 행이며 Timestamp 숫자는 예시의 처리 순서를 나타냅니다.

DaySensorReadingTimestamp
Mondayhot3
Mondaycold2
Mondayhot1

출력은 각 행을 처리했을 때의 누적 상태를 포함할 수 있습니다.

DaySensorReadingTimestampState
Mondayhot32
Mondaycold21
Mondayhot11

상태는 전체 행을 포함하여 직렬화할 수 있는 유형을 보관할 수 있습니다. Pipeline Builder의 기본 상태 변환은 상태 자료형과 그 변화 처리를 관리합니다.

모든 상태가 사용자에게 직접 노출되지는 않습니다. 예를 들어 Flink 입력은 파티션별 마지막 오프셋을 상태로 보관하여 실패나 재시작 뒤 마지막 성공 지점에서 복구할 수 있게 합니다.

정확히 한 번의 상태 반영

Foundry 스트리밍은 Flink를 이용하여 처리한 행을 다음 단계로 전달합니다. 기본 exactly-once 구성에서는 상태를 바꾸는 행의 효과가 키별 순서에 따라 정확히 한 번 반영되도록 합니다.

장애 후 다시 처리하더라도 합계가 중복 누적되지 않도록 할 수 있습니다. 정렬 중 일부 결과가 아직 공개되지 않은 상태에서 재시작하는 경우에도 입력당 하나의 출력이라는 처리 의미를 유지합니다. 이 보장은 원천에서 이미 뒤바뀐 업무 이벤트의 순서를 다시 만들어 주는 기능과는 다릅니다.

키별 상태

Pipeline Builder의 상태 기반 스트리밍 변환은 키별 상태를 사용합니다. 서로 다른 키 값은 독립적으로 계산할 수 있어 병렬로 처리하고 확장할 수 있습니다. 실제 키 지정 위치와 개별 인자의 필수 여부는 사용하는 변환의 계약을 따릅니다.

Day를 키로 사용한 가상 예시는 다음과 같습니다.

DaySensorReadingTimestampState
Tuesdayhot51
Mondayhot42
Tuesdaycold30
Mondaycold21
Mondayhot11

Tuesday의 행은 Monday의 상태를 바꾸지 않습니다. Wednesday라는 새 키가 들어와도 기존 두 키의 상태는 독립적으로 유지됩니다. 이 예시는 문자열 키별 누적을 보여 주며 날짜가 바뀌면 자동으로 상태를 초기화하는 설정을 뜻하지는 않습니다.

키 분포가 고르지 않으면 일부 연산자에 부하가 몰립니다. 파티션 키를 선택할 때 순서와 상태의 의미뿐 아니라 분산도 고려합니다.

이벤트 시각과 워터마크

시간 기반 상태 변환은 서로 가까운 시각의 행들을 묶어 처리합니다. 예를 들어 Outer Caching Join은 조인 키가 같고 두 행의 시각이 정해진 만료 구간 안에 있을 때 결합합니다.

Pipeline Builder는 이벤트 시각(event time)을 사용합니다. 시간 기반 연산 앞에는 Assign timestamps and watermarks를 추가해야 하며 없으면 그래프 검증 오류가 발생합니다. 이벤트 시각은 보통 행의 타임스탬프 열에서 가져옵니다. 지정한 타임스탬프가 null인 행은 이 변환에서 제외됩니다.

워터마크는 연산자가 어느 이벤트 시각까지 진행했다고 판단하는 값입니다. 단조 증가하며 관측한 최대 이벤트 시각을 뒤따릅니다. 한 입력이 여러 병렬 경로로 들어오면 연산자는 그 경로들의 워터마크 중 최솟값에 제한되고, 입력 스트림이 여러 개이면 각 입력 워터마크의 최솟값을 사용합니다.

예를 들어 Outer Caching Join은 워터마크가 항목의 만료 시각 이상인지 확인하여 만료 여부를 판단합니다. 벽시계 시간이 흘렀다는 사실만으로 이벤트 시각의 캐시가 만료되는 것은 아닙니다.

재생하면 같은 결과 또는 비슷한 결과를 얻도록 설계되어 있지만, 기본 처리에서 미세한 차이가 생길 수 있습니다. 키가 다른 병렬 인스턴스에 배치되거나 여러 상위 입력의 처리 속도가 달라질 수 있기 때문입니다. 워터마크 전파의 결정성 옵션과 비용은 해당 타임스탬프 지정 변환에서 확인합니다. 변환의 시간 기준으로 Flink processing time을 사용하는 방식은 지원하지 않으며 재생 결과도 크게 달라질 수 있습니다.

유휴 입력과 멈춘 워터마크

병렬 입력 하나가 레코드를 받지 않으면 새 워터마크를 내보내지 않아 전체 진행을 막을 수 있습니다. 키가 고르게 분산되지 않았을 때도 나타나며, 상태 만료와 시간 윈도 종료에 영향을 줍니다.

Assign timestamps and watermarks의 Idleness timeout unit과 Idleness timeout value로 유휴 판정 시간을 구성할 수 있습니다. 정해진 처리 시간 동안 레코드를 받지 않은 경로를 유휴로 판단하면 그 경로의 워터마크를 전체 계산에서 제외합니다. 여기서 유휴 여부를 재는 처리 시간과 변환 자체의 이벤트 시각 기준은 구분합니다.

시간을 너무 짧게 잡으면 단순히 느린 입력을 유휴로 오인할 수 있습니다. 빠른 입력만으로 워터마크가 진행한 뒤 느린 입력이 도착하면 허용 지연을 넘긴 행이 더 많이 제외될 수 있습니다.

상태 만료

큰 상태는 처리량, 지연과 체크포인트 시간에 부담을 주므로 상태 크기를 제한해야 합니다. 캐시 시간을 요구하는 변환은 일반적으로 키별 마지막 이벤트 시각에 만료 기간을 더한 지점까지 상태를 유지하고 워터마크가 그 범위를 지나면 정리합니다.

워터마크가 멈추면 상태를 제때 제거하지 못해 예상 밖의 출력이나 무제한 증가가 발생할 수 있습니다. 필요한 기간보다 긴 캐시를 두거나 개수 기반 윈도의 행 수를 과도하게 늘리지 않습니다.

윈도

Aggregate over window는 행과 상태를 묶는 윈도와, 집계 결과를 내보낼 시점을 정하는 트리거를 함께 사용합니다.

윈도묶는 기준
Tumbling event time고정 길이의 연속된 비중첩 시간 구간입니다. 같은 키이며 이벤트 시각이 같은 구간에 있는 행을 묶습니다. 예를 들어 같은 날짜의 같은 한 시간 구간을 집계할 수 있습니다.
Count키마다 사용자가 지정한 최근 n개 행을 묶습니다.
Session같은 키의 행 사이에서 이벤트 시각의 공백이 지정한 session gap보다 길어지기 전까지 하나의 세션으로 묶습니다. 사용자 활동 뒤 일정 시간의 휴식으로 세션을 구분하는 경우에 사용할 수 있습니다.

시간 기반 윈도는 워터마크가 충분히 진행하면 닫힙니다.

  • 허용 지연이 없거나 0이면 워터마크가 윈도 끝을 지나면 창을 닫고 필요에 따라 결과를 출력한 뒤 상태를 삭제합니다.
  • 허용 지연이 있으면 윈도 끝에 허용 지연을 더한 시점까지 상태를 유지하여 늦거나 순서가 어긋난 행도 반영할 수 있습니다.
  • 워터마크가 윈도 끝과 허용 지연을 모두 지난 뒤 도착한 행은 창이 이미 닫히고 상태가 삭제되었으므로 제외합니다.

워터마크가 멈추면 창이 예상보다 오래 열려 있어 출력이 나오지 않거나, 상태가 계속 증가하거나, 트리거가 발동하지 않을 수 있습니다.

출력 트리거

트리거출력 시점
After watermark trigger워터마크가 윈도 끝을 지날 때 출력합니다. 끝에 도달하기 전의 조기 출력과 허용 지연 중 늦은 입력에 대한 출력 트리거도 별도로 구성할 수 있습니다.
Count trigger키마다 받은 행 수가 지정한 n의 배수가 될 때 출력합니다.
Window close trigger상태를 삭제하면서 윈도가 최종적으로 닫힐 때만 출력합니다. 윈도마다 한 번만 발생합니다.

예를 들어 처음에는 출력을 내지 않고 윈도 끝에 한 번 출력한 뒤, 허용 지연 중에는 늦게 들어온 각 변경을 다시 출력하는 구성을 선택할 수 있습니다. 창을 묶는 기준과 출력을 내는 기준을 구분하여 정합니다.

큰 상태를 사용하는 파이프라인

큰 상태가 필요한 경우 Flink 작업의 병렬성을 늘리면 데이터 처리와 상태 읽기 및 쓰기를 분산할 수 있습니다. 스트리밍 파이프라인 설정에서 병렬성을 조정하되 키가 충분히 분산되어야 효과가 있습니다.

키 종류가 지나치게 많거나 특정 키에 행이 몰리면 상태 크기와 처리량에 병목이 생길 수 있습니다. 만료 정책을 가능한 한 짧고 명확하게 정하고, 처리량 및 지연과 함께 체크포인트 소요 시간도 모니터링합니다.