주요 컨텐츠로 이동

Translated by HaUn Kim - Original Blog Post

대부분의 비즈니스 의사결정은 시간에 민감하며, 여러 종류의 소스에서 실시간 데이터를 활용해야 합니다. 적절한 시기에 적절한 데이터를 확보하는 것이 중요한 의사결정을 시기적절하게 내리는 열쇠입니다. 시간에 민감한 데이터 소스는 IoT 센서, 소셜 미디어, 클릭 스트림, 데이터베이스의 변경 데이터 캡처 등 다양한 기술에서 분산되어 있습니다. 이런 데이터에서 핵심적인 인사이트를 뽑아내기 위해서는 먼저 레이크하우스에 데이터를 모아야 합니다. 이런 데이터의 주요 특징은 스트리밍, 즉 무제한적으로 계속 도착한다는 점입니다. 이 블로그에서는 스트리밍 데이터를 레이크하우스로 모으는 방법에 대해 상세히 설명합니다.

데이터 수집 흐름의 개요

여러 데이터 소스에서 온 스트리밍 데이터는 메시지 버스 시스템이나 클라우드 객체 저장소에서 스테이징되고, 이후 레이크하우스로 수집됩니다. 스테이징 영역의 데이터는 Apache Spark의 구조화된 스트리밍(SS) 파이프라인이 레이크하우스에 기록하는 역할을 합니다. 스테이징 환경에는 클라우드 객체 저장소와 메시지 버스 시스템이라는 두 가지 주요한 환경이 있습니다. 각각에 대해 아래에 설명하겠습니다.

  • 클라우드 오브젝트 스토리지는 클라우드에서 안전하고 안정적이며 확장 가능한 저장 및 지속성 계층을 제공합니다. Amazon S3, Azure ADLS/Blob 스토리지, Google 클라우드 스토리지(GCS) 등이 클라우드에서 널리 사용되는 오브젝트 스토리지의 예입니다. 일반적으로 이벤트는 배치로 캡처되어 클라우드 객체 스토리지에 파일로 저장되며, 이 파일들은 거의 실시간으로 수집되어야 합니다. 통신 통화 데이터 기록, IoT 이벤트 로그 등이 클라우드 스토리지에서 거의 실시간으로 데이터를 수집해야 하는 사례입니다.
  • 메시지 버스 시스템은 퍼블리셔/구독자 모델에서 동작하는 느슨하게 연결된 데이터 버퍼를 제공합니다. Apache Kafka, Apache Pulsar, Azure EventHub, AWS Kinesis, GCP Pub/Sub 등이 오픈 소스 및 클라우드의 메시지 버스 시스템의 몇 가지 예입니다. 메시지 버스 시스템은 게시 지연 시간이 짧고, 여러 소비자를 지원할 수 있는 더 넓은 팬아웃을 보장하므로, 실시간 이벤트 캡처에 적합합니다. 클릭 스트림, 신용카드 사기 탐지 등이 메시지 버스를 사용하여 스테이징하는 애플리케이션의 예입니다. 이런 애플리케이션에서는, 다운스트림 처리가 즉시 인사이트를 제공할 수 있도록, 데이터를 실시간으로 수집해야 합니다.

이 두 가지 주요 데이터 스테이징 환경에서 레이크하우스로 스트리밍 데이터를 수집하는 개요적인 아키텍처는 그림 1에 나와 있습니다.

Figure 1. High level view of streaming data ingestion into delta lake
Figure 1. High level view of streaming data ingestion into delta lake

그림에서 보시다시피, 다양한 소스 시스템에서의 데이터는 먼저 오브젝트 저장소나 메시지 버스 중 하나의 스테이징 영역에 도착합니다. 이 데이터는 메시지 버스용 스트리밍 커넥터나 객체 저장소용 오토 로더를 통해 레이크하우스로 수집됩니다. 델타 라이브 테이블(DLT)은 안정적인 데이터 파이프라인을 구축하기 위한 간결한 선언적 방법을 제공하며, 대규모 배치 및 스트리밍 데이터에 대한 기본 인프라를 완벽하게 관리합니다. 또한 Spark Structured 스트리밍을 기반으로 하지만, 이 블로그에서는 이에 대해 다루지 않습니다. 다음 섹션에서는 이러한 소스에서 스트리밍 데이터를 수집할 때 발생할 수 있는 몇 가지 문제에 대해 상세히 설명하겠습니다.

객체 저장소에서 데이터 수집을 위한 오토 로더

일반적으로 파일은 배치 데이터 수집과 연관되어 있습니다. 그러나 다양한 소스에서 파일 형태의 클라우드 기반 객체 저장소로 데이터를 지속적으로 수집하는 것이 일반적인 패턴입니다. 이 패턴은 실시간에 가까운 처리가 필요한 경우에 선호되며, 예상 지연 시간은 몇 분 정도입니다. 또한 정확히 한 번의 처리, 실패한 수집 작업의 재처리, 시간 이동 및 스키마 변화 등의 비기능적 요구 사항도 필요합니다.

클라우드 객체 저장소에서 레이크하우스로 로드하는 과정에서 발생할 수 있는 어려움을 설명하기 위해, 고객 경험을 향상시키고 결제 사기를 탐지하는 데 필요한 실시간 신용카드 결제 처리 시스템을 예로 들어 보겠습니다. 일반적으로 여러 결제 채널의 거래는 객체 저장소의 파일로 배치 처리됩니다. 이러한 파일은 추가적인 다운스트림 처리를 위해 레이크하우스로 수집되어야 합니다. 이러한 거래는 결제 거래이므로, 실패한 거래를 중복 없이 재처리하는 조항을 통해 정확히 한 번만 처리되도록 해야 합니다. 이를 AWS 클라우드에서 처리하려면 다음과 같은 복잡한 아키텍처가 필요합니다:

  • Amazon SQS(Simple Queue Service) 알림을 사용하여 Amazon S3에 도착하는 결제 거래 파일을 확장 가능한 방식으로 추적
  • Amazon SQS에서 작업을 검색하고 다운스트림 처리를 트리거하는 Amazon Lambda 함수
  • 결제 거래 파일의 상태를 감사하기 위한 제어 테이블 사용 주요 과제는 오브젝트 스토어에 도착하는 수많은 파일을 추적하여 해당 파일의 데이터를 정확히 한 번만 처리하고, 다양한 결제 채널의 서로 다른 스키마를 관리하는 것입니다.

Figure 2. Event Based file processing in the AWS Cloud
Figure 2. Event Based file processing in the AWS Cloud

주요 과제는 오브젝트 스토리지에 도착하는 수많은 파일을 추적하고, 해당 파일의 데이터를 정확하게 한 번만 처리하며, 다양한 결제 채널의 서로 다른 스키마를 관리하는 것입니다.

오토 로더는 클라우드 오브젝트 스토리지에 도착하는 새 데이터 파일을 점진적으로 처리하여 스트리밍 데이터 수집을 간소화하며, 사용자가 사용자 지정 애플리케이션을 작성할 필요가 없습니다. 내부 상태를 유지하여 지금까지 처리된 파일을 추적합니다. 장애가 발생하면 이 상태를 사용해 마지막으로 처리된 파일부터 다시 시작합니다. 또한 데이터를 재생하거나 재처리할 필요가 있는 경우 디렉토리에 있는 기존 파일을 처리하는 옵션도 제공합니다. 오토 로더의 주요 이점은 다음과 같습니다:

  • 수십억 개의 파일을 처리할 수 있는 능력
  • 컴퓨팅 리소스를 최적으로 활용하는 비동기 백필 기능
  • 최적화된 디렉토리 목록으로 성능 향상
  • 스키마 추론 및 스키마 변화 처리 지원
  • 자동 파일 알림 서비스를 활용한 비용 효율적인 파일 알림

오토 로더는 어떻게 작동하나요?

오토 로더는 새 파일을 감지하는 두 가지 방식인 파일 알림과 디렉터리 목록을 지원합니다.

파일 알림: 오토 로더는 입력 디렉터리에서 파일 이벤트를 구독하는 알림 및 대기열 서비스를 자동으로 설정할 수 있습니다. 파일 알림 모드는 파일이 많은 입력 디렉터리에 대해 더 우수한 성능과 확장성을 보장하지만, 추가적인 클라우드 권한이 필요합니다. 이 옵션은 파일이 사전식 순서대로 도착하지 않을 때 특히 효과적이며, 대기열 및 알림을 별도로 설정할 필요가 없습니다. 이 모드를 사용하려면 cloudFiles.useNotifications 옵션을 true로 설정하고 클라우드 리소스 생성에 필요한 권한을 제공해야 합니다. 파일 알림에 대한 자세한 정보는 해당 문서를 참조하세요.

디렉토리 목록: 새 파일을 찾는 또 다른 방법은 오토 로더가 설정된 입력 디렉터리를 나열하는 것입니다. 디렉토리 목록 모드를 사용하면 데이터 접근 권한 외에 추가적인 권한 설정 없이 오토 로더 스트림을 시작할 수 있습니다. 데이터브릭스 런타임 9.1부터 오토 로더는 파일이 사전식 순서대로 클라우드 스토리지에 도착하는지 여부를 자동으로 판별하여, 새 파일 감지에 필요한 API 호출 횟수를 크게 줄일 수 있습니다. 기본 설정에서는 7번의 증분 디렉터리 목록이 연속으로 생성될 때마다 전체 디렉터리 목록이 트리거됩니다. 하지만 전체 디렉터리 목록의 생성 빈도는 cloudFiles.backfillInterval 설정을 통해 조정할 수 있습니다. cloudFiles.useIncrementalListing 설정을 통해 증분 목록을 명시적으로 활성화 또는 비활성화할 수 있습니다. 이 설정을 명시적으로 활성화하면 오토 로더가 전체 디렉터리 목록을 생성하지 않습니다. 디렉터리 목록에 대한 자세한 정보는 해당 문서를 참조하세요.

새 파일이 발견되면, 그 파일의 메타데이터는 오토 로더 파이프라인의 체크포인트 위치에 있는 확장 가능한 키-값 저장소(RocksDB)에 저장됩니다. 이는 지금까지 처리된 파일을 추적하는 상태를 유지하는 역할을 합니다. 파이프라인은 기존 파일이 포함된 디렉터리에 대한 백필 작업을 진행하는 동안, 동시에 파일 알림을 통해 발견되는 새 파일을 처리할 수 있습니다.

Figure 3. Autoloader simplifies data ingestion from the Cloud Storage using RockDB based file metadata management and Structured Streaming
Figure 3. Autoloader simplifies data ingestion from the Cloud Storage using RockDB based file metadata management and Structured Streaming

메시지 버스에서 데이터 수집

스트리밍 데이터는 본질적으로 무제한이며, 이 데이터는 메시지 버스라는 버퍼에 저장됩니다. 메시지 버스는 여러 생산자들이 데이터를 입력하고, 다수의 소비자들이 이를 읽을 수 있는 비동기 통신 방식을 제공합니다. 이는 사기 탐지, 금융 자산 거래, 게임 등의 지연 시간이 짧아야 하는 사용 사례에 주로 사용됩니다. Apache Kafka, Apache Pulsar, Azure EventHubs, Amazon Kinesis, Google Cloud Pub/Sub 등이 대표적인 메시지 버스 서비스입니다. 하지만, 지속적인 데이터 수집은 확장성, 복원력, 내결함성 등의 문제를 야기할 수 있습니다.

레이크하우스로의 데이터 수집을 위해, 메시지 버스에 적합한 소스 커넥터와 레이크하우스에 적합한 싱크 커넥터를 사용해 명시적인 Spark 구조화된 스트리밍(SS) 파이프라인을 구성합니다. 이 과정에서 처리량과 내결함성이 핵심적인 과제로 등장합니다.

이러한 소스의 일반적인 수집 패턴에 대해 알아보고자 합니다. 메시지 버스는 실시간 처리 사용 사례에 적합하지만, 대부분의 애플리케이션은 지연 시간, 처리량, 내결함성 요구 사항 및 비용 간의 균형을 맞추는 설계가 필요합니다. 이에 대한 선택 사항을 살펴보면 다음과 같습니다:

1. 지연 시간: 지연 시간을 줄이는 것이 항상 좋은 것은 아닙니다. 오히려 적절한 지연 시간, 정확도 및 비용 사이의 절충을 선택함으로써 비용을 줄일 수 있습니다. 스파크 구조화 스트리밍은 데이터 처리 타이밍을 정의하는 트리거에 의해 데이터를 점진적으로 처리합니다. 트리거 간격을 줄이면 Spark Structured Streaming 작업의 지연 시간을 줄일 수 있습니다. 소스에 데이터가 도착하는 속도와 지연 시간 요구 사항 사이의 균형을 맞추기 위해 Structured Streaming 트리거 간격을 설정하는 것이 좋습니다. 트리거 간격을 너무 짧게 설정하면, 시스템이 새로운 데이터의 도착을 불필요하게 확인하는 상황이 발생할 수 있습니다.

스파크 구조화 스트리밍은 세 가지 트리거 유형을 제공합니다:

  • 기본값: 기본적으로 Spark Structured Streaming은 이전 배치가 완료되는 즉시 다음 배치를 처리합니다. 이는 대부분의 사용 사례에서 사용자의 요구 사항을 충족시킵니다.
  • 고정 간격: 사용자가 지정한 간격으로 작업을 처리할 수 있는 고정 간격을 사용하면, 일정 시간 동안 대기한 후 더 큰 규모의 마이크로 배치를 실행하는 데 사용됩니다.
  • 한 번 (one-time): 데이터가 고정된 간격으로 도착하는 경우, 하루 종일 클러스터를 계속 가동하는 것은 리소스 낭비가 될 수 있습니다. 이럴 경우, 배치 모드에서 작업을 실행하는 것이 하나의 옵션이 될 수 있습니다. 그러나 one-time 트리거 또는 지금 사용 가능 모드에서 Spark 구조화된 스트리밍 작업을 실행하는 것이 일괄 처리보다 유리합니다. 이 설정을 사용하면 클러스터를 계속 실행하지 않고도 주기적으로 클러스터를 돌려가며 데이터를 처리한 후 클러스터를 종료함으로써 비용을 크게 절감할 수 있습니다. 이는 배치 작업과 유사하지만, 처리 중인 데이터의 복구 관리, 테이블 수준의 원자성 유지 등으로 인해 내결함성, 실행 전반에 걸친 상태 저장 작업 등의 추가적인 이점을 제공합니다.

2. 처리량: 스파크 구조화된 스트리밍에서 높은 처리량을 달성하기 위해 조정할 수 있는 여러 변수가 있습니다. 트리거 유형을 선택하는 것 외에도, 데이터 수집 작업의 병렬 처리는 중요한 변수 중 하나입니다. 더 높은 처리량을 달성하기 위해서는 메시지 버스의 파티션 수를 늘릴 수 있습니다. 일반적으로 Spark는 메시지 버스 파티션과 Apache Kafka용 Spark 구조화된 스트리밍 파티션 사이에 일대일 매핑이 있습니다. 하지만 AWS Kinesis의 경우, 메모리에 미리 데이터를 가져오기 때문에 Kinesis 샤드 수와 Spark 작업 수 사이에 직접적인 매핑이 없습니다.

실제 사례를 통해 배치 크기와 파티션 수를 조정하여 더 높은 처리량을 달성하는 방법을 살펴보겠습니다. 한 은행에서는 스트리밍 작업을 이용하여 하루 종일 실시간 트랜잭션을 처리했습니다. 그러나 실시간으로 수신되는 이벤트 중 일부는 부정확할 수 있습니다. 이 문제를 해결하기 위해 하루가 끝날 무렵에 조정 배치를 실행했습니다. 조정 배치는 동일한 스트리밍 코드를 사용하지만 다른 작업 인스턴스를 사용하여 처리되었습니다. 다른 토픽의 연속 흐름 데이터에 비해 높은 처리량을 달성하기 위해 파티션 수와 배치 크기를 늘렸습니다.

3. 내결함성: 스파크 구조화된 스트리밍은 작업을 마이크로 배치로 실행하여 내결함성을 달성하는 두 가지 주요 이점을 제공합니다:

  • 작업은 다른 실행자 중 하나에서 작업 일정을 재조정하여 장애로부터 효과적으로 복구할 수 있습니다.
  • 결정론적 태스크는 동일한 태스크를 여러 번 실행하더라도 동일한 출력을 제공하도록 보장함으로써, 정확히 한 번만 처리가 가능합니다.

스파크 구조화된 스트리밍에서는 실패한 작업의 복구가 각 쿼리의 체크포인트 위치를 통해 이루어집니다. 체크포인트 위치에 있는 오프셋을 사용하면 정확한 실패 지점에서 작업을 다시 시작할 수 있습니다. 쿼리에서 체크포인트 위치를 제공하는 옵션은 다음과 같습니다:

option("checkpointLocation", "dbfs://checkpointPath")

재생 가능한 소스와 이상 불변의 싱크를 사용하면, Spark 구조화된 스트리밍 작업은 프로덕션 등급 애플리케이션의 요구 사항인 정확한 일회성 시맨틱을 달성할 수 있습니다.

결론

스트리밍 데이터 수집은 레이크하우스에서 시간에 민감한 결정을 내리는 과정 중 첫 번째 단계입니다. 이 블로그에서는 스트리밍 데이터 소스를 연속적인 파일 흐름 또는 메시지 버스 서비스로 분류했습니다. 오토 로더는 스파크 구조화된 스트리밍을 사용하여 파일 소스에서 거의 실시간으로 수집을 간소화하며, 파일 도착 자동 감지, 대량 데이터 처리 가능한 확장성, 스키마 추론, 비용 효율적인 데이터 수집 등의 고급 기능을 제공합니다. 메시지 버스 서비스에서 데이터를 수집하는 경우, Spark Structured Streaming은 다양한 클라우드 제공업체의 메시지 버스 서비스와 대부분 통합되는 강력한 데이터 수집 프레임워크를 제공합니다. 대부분의 프로덕션 등급 애플리케이션은 비용을 최소화하고 정확도를 높이기 위해 지연 시간과 처리량 사이의 균형을 맞추어야 합니다.

Databricks 무료로 시작하기

관련 포스트

모든 엔지니어링 블로그 포스트 보기