728x90
Stream 처리란
- 스트림 처리는 신규 데이터를 끊임없이 처리해 결과를 만들어내는 행위
- 입력 데이터는 무한하며 시작과 끝을 사전에 정의하지 않음
- 스트림 처리 시스템에 도착한 일련의 이벤트(신용카드 전표 정보, 웹사이트 클릭(행동 로그), IoT 장비 센서 데이터)
1) 스트림 처리 사례
통보와 알림
- notification과 alerting은 가장 흔한 스트림 처리 사례
- 연속적인 이벤트에서 특정 이벤트나 이벤트의 패턴을 탐지했을 때 발생
실시간 리포트
- 기업에서 직원을 위한 실시간 대시보드를 만들 때에 사용
- 플랫폼 전체 사용량, 시스템 부하, 실행 시간, 신규 기능의 사용량
증분형 ETL
- 웨어하우스에서 정보를 얻는 시간을 줄이기 위해 사용
- 신규 데이터(증분 데이터)에 대해서 바로바로 반영할 수 있음
- 데이터 중복 저장이나 유실 방지를 위해, exactly once 처리해야 하는데, 삭제 감지에 대한 대책이 필요함(CDC 반영, Iceberg 등)
- 트랜잭션을 보장하면서 데이터 웨어하우스를 갱신해야 함
실시간 제공용 데이터 갱신
- 다른 application의 서비스용 데이터를 만들기 위해 사용(서비스 데이터로써 활용)
- ex) google analytics 서비스
실시간 의사결정
- 신규 입력을 분석하고 자동으로 비즈니스 로직에 따라 처리
- ex) 신용카드 고객의 최근 이력을 기준으로 카드 트랜잭션이부정행위에 속하는지 여부를 자동 판단해 부정행위로 의심되는 경우 카드 트랜잭션을 거부하는 상황
온라인 머신러닝
- 여러 사용자의 실시간 데이터와 이력 데이터를 조합해 모델을 학습
- ex) 학습자의 실시간 실력 level 계산
2) 스트림 처리의 장점 & 단점
장점
- 대기 시간이 짧다(빠르게 응답해야 하는 성능에 적합)
- 자동으로 연산 결과의 증분을 생성하므로 반복적인 배치 작업보다 결과를 수정하는데 효율적
단점
- 비용이 대체로 비싸다
- 배치 형태의 처리 보다는 낮은 처리량이다
- 데이터가 지연되거나 재전송되면 시간이 뒤섞여 도착할 수 있음
3) 스트림 처리의 과제
- application timestamp(event time) 기준으로 순서가 뒤섞인 데이터 처리하기
- 대규모의 상태 정보 유지하기
- 높은 데이터 처리량 보장하기
- 장애 상황에서도 정확히 한번 처리하기(exactly once)
- 부하 불균형과 뒤처진 서버 다루기
- 이벤트에 빠르게 응답하기
- 다른 저장소 시스템의 외부 데이터와 조인하기
- 신규 이벤트 도착 시 출력 싱크의 갱신 방법 결정하기
- 출력 시스템에 데이터 저장 시 트랜잭션 보장하기
- 런타임에 비즈니스 로직 변경하기
스트림 처리의 핵심 설계 개념
1) 레코드 단위 처리와 선언형 API
- 가장 간단한 방법은 각 이벤트를 application에 전달하고 사용자 코드에 반응하도록 만드는 것
- ex) apache storm
- 레코드 단위 처리 API를 사용하는 스트리밍 시스템은 application 내부에서 여러 처리 파이프라인을 연결하는 기능만 제공 → 상태 관리 같은 앞서 나열했던 복잡한 문제점을 가지고 있음
- ex) 레코드 단위 처리 API를 사용하려면 사용자가 직접 상태를 추적해야 함, 메모리 확보를 위한 상태 제거와 중복 처리 방지 등의 기능을 직접 구현해야 함
- 최신 스트리밍 시스템에서는 선언형 API를 제공
- application을 정의할 때 어떻게 신규 데이터를 처리하고 장애 상황에서 복구할지 지정하는 대신 무엇을 처리할지 지정
- DStream API
- map, reduce, filter 같은 연산을 기반으로 하는 함수형 API를 제공
- 내부적으로 각 연산자의 데이터 처리량과 연산 관련 상태 정보를 자동으로 추적하고 관련 상태를 신뢰도 있게 저장
- 장애 지점부터 연산을 복구 가능
- Structured Streaming
- 별도의 프로그래밍 없이 함수형 연산을 훨씬 효율적으로 처리할 수 있는 SQL 형태의 관계형 연산으로 변환해 개념을 한 단계 발전 시킴
2) 이벤트 시간과 처리 시간
- 선언형 API를 사용하는 시스템을 구현하려면 자체적으로 이벤트 시간 처리 지원여부가 중요
- 이벤트 시간 처리: 원천 시스템에서 각 레코드에 기록한 타임스탬프를 기반으로 데이터를 처리하는 방식
- 처리 시간 기준 처리: 스트리밍 application에 레코드가 도착한 시간을 기반으로 처리하는 방식을 의미
- 스트리밍 레코드는 순서가 뒤섞여(다른 네트워크 경로를 타고 왔을 수 있음) 들어오거나 여러 원천 시스템 사이의 순서가 뒤 섞일 수 (동일한 이벤트 시간을 가진 레코드가 다른 것에 비해 일부 늦게 들어올 수 있음) 있음
- 이벤트 시간 처리를 하지 않으면 일부 데이터가 늦게 도착했을 때 중요한 패턴을 인식 할 수 없을 수 있으므로 매우 중요함
3) 연속형 처리와 마이크로 배치 처리
연속형 처리(Continuous Processing)
- 각 노드는 다른 노드에서 전송하는 메시지를 끊임없이 수신하고 새로 갱신된 정보를 자신의 하위 노드로 전송
- 입력 스트림에 맵리듀스 연산을 수행하는 애플리케이션이 있다고 가정
- 각 노드가 신규 메시지에 즉시 반응하기 때문에 전체 입력량이 비교적 적을 때 가장 빠르게 응답
- 레코드 단위 부하가 매우 크기 때문에 최대 처리량이 적음
- ex) 다음 처리 노드로 메시지 패킷을보내기 위해 OS를 호출하는 연산 부하가 발생하고, 고정형 연산 토폴로지를 사용하므로 전체 시스템을 중지해야 애플리케이션을 변경할 수 있음 → 부하 분산 문제가 발생할 수 있음
마이크로 배치 처리(Micro-batch Processing)
- 입력 데이터를 작은 배치로 모으기 위해 기본적으로 대기(500ms 정도)시간 존재
- batch job 실행 방식과 유사하게 다수의 분산 태스크를 이용해 각 배치를 병렬로 처리
- 배치 시스템의 최적화 기법을 사용할 수 있음
- ex) 벡터화 처리 최적화 기법 → 더 높은 노드당 처리량을 얻을 수 있음, 추가적인 레코드별 부하가 없음
- 더 적은 노드로 같은 양의 데이터를 처리할 수 있음
- 워크로드 변화에 대응할 수 있도록 태스크 수를 늘리거나 줄이는 방식인 부하 분산 기술을 동적으로 사용할 수 있음
- 운영 환경에서 연산을 분산시켜야 할 만큼 큰 규모의 스트리밍 시스템은 처리량을 중시하는 경향이 있음
- 지연 시간 요건과 총 운영비용을 고려하여 선택
저 수준 API: DStream API
- 실시간으로 들어오는 데이터 스트림을 **작은 시간 단위(마이크로 배치)**로 잘라서 RDD(Resilient Distributed Dataset)로 처리
- 연속적인 RDD의 시퀀스로 구성
각 RDD는 특정 시간 간격(예: 1초, 5초 등)에 들어온 데이터를 담고 있으며, Spark의 분산 처리 엔진을 사용해 병렬로 처리
- 연속적인 RDD의 시퀀스로 구성
- 많은 장점을 제공하는 구조적 테이블 개념의 DataFrame이나 Dataset과 달리 자바나 파이썬의 객체와 함수에 매우 의존적 → 스트림 처리 엔진이 제공하는 최적화 기법을 적용하지 못함
- DStream API는 기본적으로 처리 시간을 기준으로 동작함 → 이벤트 시간 기준으로 처리하고 싶은 경우에는 자체적으로 구현해야 함
- DStream API는 마이크로 배치 형태로만 동작 → 다른 처리 모드를 지원할 수 없음
처리 모드 | 설명 | 지연 | 처리 방식 |
Micro-batch Processing | 데이터를 일정 주기로 배치 단위로 나누어 처리 | 수 초(초 단위) | DStream, Structured Streaming |
Continous Processing | 이벤트 발생 즉시 데이터를 처리 | 1~10ms(밀리초) | Structured Streaming |
고 수준 API: Structured Streaming
- DataFrame이나 Dataset에(구조적 데이터 모델) 직접 통합할 수 있는 구조적 스트리밍 API
- 처음부터 배치 애플리케이션 뿐만 아니라 나머지 컴포넌트와 쉽게 연동할 수 있도록 설계 됨
- continous application(micro batch)의 개념이나, micro-batch processing 도 지원
- spark 2.2 기준으로 micro-batch processing만 지원하지만 2.3부터는 continous processing 기능 사용 가능
- Scala, Java, Python, R 그리고 SQL을 사용해 구조적 처리를 할 수 있는 모든 환경에서 사용 가능
- 이벤트 시간 데이터 처리를 지원함 (모든 윈도우 연산에서 자동으로 이벤트 시간 처리를 지원)
- 데이터가 도착할 때마다 자동으로 증분 형태의 연산 결과를 만들어 냄 → 통합형 application을 작성할 때 큰 도움이
- 서로 다른 처리 시스템에 대한 배치와 스트리밍용 코드를 별도로 관리할 필요가 없음
- 동기화하지 않을 때 발생할 수 있는 위험성을 제거할 수 있음
참조:
spark definitive guide 도서
728x90
댓글