data8 MIN READ

[데이터 엔지니어링 디자인 패턴] 02. 데이터 수집

[데이터 엔지니어링 디자인 패턴] 02. 데이터 수집

데이터 엔지니어링 디자인 패턴 시리즈의 글입니다.

데이터 엔지니어링 시스템의 첫단계는 다양한 data producer에게서 데이터를 수집하는것.
수집한 데이터를 통합할때 마주할수잇는 시나리오와 챌린지를 알아보자

2.1 전체 적재

  • 매번 데이터셋 전체를 로드하는 데이터 수집 시나리오
  • db bootstrap , reference dataset 등의 상황에 유용

전체로더

가장 간단한 패턴 - 추출(extract)과 적재(load) 2단계로 구성

  • 문제
    • 마지막 데이터 수집 이후 변경된 레코드를 감지하는데 도움이 되는 속성이 없다면?
  • 해결책
    • 전체로더 패턴이 이상적인 해결
    • 동종DB간 : EL(extract-load)
    • 이종DB간 : ETL (extract-transform-load)
  • 결과
    • 데이터 크기
      • 일정한 스케쥴에 따라 실행되는 배치잡이므로, 데이터셋이 천천히 증가한다면 일정한 컴퓨팅 자원으로 오랫동안 문제없이 작동
      • 그러나 동적으로 진화하는 데이터셋의 경우, 정적 컴퓨팅 자원으로는 문제가 생길 수 있음
      • autoscaling기능을 활용해야함
    • 데이터 일관성
      • 전체로더는 일관성을 잃을 위험이 있음
      • drop-and-insert 작업으로 해도, 조회와 수집이 동시에 실행되면 데이터 일관성이 깨질 위험 존재
        • transaction으로 통해 동시성 문제 해결 가능
        • view같은 single data exposition abstraction(단일 데이터 노출 추상화)로 해결 가능
      • 예상치 못한 문제 발생시 이전 버전의 데이터셋을 사용해야할수있음
      • delta lake, big query등에서 제공하는 tiem travle 기능 사용
      • 혹은 view로 직접 해당 기능 구현

2.2 증분 적재

  • 지속적으로 증가하는 데이터셋에 적합
  • 물리적/논리적으로 나누어진 데이터셋의 더 작은부분을, 더 자주 수집

증분 로더

데이터셋의 새로운부분을 처리

  • 문제
    • 데이터 크기가 계속 증가하되,
    • 불변하는 이벤트를 수집해야함
  • 해결책
    • 지속적으로 증가하는 데이터셋 = 증분로더 패턴이 이상적인 해결
    • delta column을 사용하여 마지막 실행 이후 추가된 레코드를 식별
    • time-partitioned dataset에 의존하여, 수집할 레코드 집합을 감지
  • 결과
    • 물리삭제 (hard delete)
      • 원본에서 레코드를 물리적으로 삭제했어도, 컨슈머에서는 여전히 데이터가 남아있을수 있음
      • 삭제된 레코드에는 delta column이 존재하지않음
      • 논리삭제(soft delete)를 사용해서 해결 가능
    • back-filling
      • back-filling은 언제든지 발생 가능한데, 증분로더에서는 전체적재를 수행하기때문에 꽤 나쁜영향을 줄수있음
      • 수집 window를 제한하여 문제를 완화할수있음

변경 데이터 캡쳐

CDC (change data capture) 데이터 수집 지연시간이 더 낮아야하거나, 물리삭제를 지원할 기능이 필요하면 적합

  • 문제
    • 테이블 변화를 30초 내에 캡쳐하고
    • 중앙 토픽에서 다른 컨슈머들에게 제공해야함
  • 해결책
    • CDC 패턴이 이상적 해결
    • 수정된 모든 레코드를 직접 수집
    • 더 빠른 레코드 접근이 가능
    • 더 낮은 지연시간 보장
    • 물리삭제를 포함한 모든 유형의 데이터 작업을 commit log로 가로챔
    • 논리삭제를 사용할 필요가 없음
  • 결과
    • 복잡성
      • 서버 커밋로그 활성화 등, 운영팀의 도움이 필요
    • 데이터 범위
      • 보통 프로세스 시작 이후에만 변경사항 적용 가능
    • payload
      • 작업유형 (update, insert, delete) , 컬럼유형 등의 부가적 메타데이터 제공
      • consumer는 관련없는 속성은 무시하도록 처리 로직을 짜야함
    • data semantic
      • 저장상태의 데이터를 수집
      • 따라서 정적인 레코드들은 “이동중인 데이터”가 됨
      • ex. join작업이 타이밍에 따라 성공할수도/실패할수도 있음

2.3 복제

  • 목표 데이터를 있는 그대로 한 장소에서 다른 장소로 복사
  • 이상적인 환경에서만 가능
  • 실제로는 컴플라이언스 규정으로 인해 입력 데이터를 변경하는 경우가 많음

패스스루 복제기

passthrough replicator 보통 데이터업체가 해당 모드를 제공함

  • 문제
    • 외부 api를 통해 데이터를 적재할때, 이는 멱등성을 갖지 않을 수 있음
    • 하루 중 시점에 따라 서로 다른 결과가 반환될 수 있음
  • 해결책
    • 환경간 일관성이 필요하다면, passthrough replicator 패턴이 적합
    • EL(extract-load) job에 의존
    • 레코드를 있는 그대로 복제
      • 그렇지않으면, 데이터 품질문제를 일으킬수있음
      • ex. 날짜 유형 변환 이슈
      • ex. 부동소수점 반올림 이슈
    • replication policy 를 기반으로, 데이터 스토어 제공업체가 복제하도록 세팅해야함
  • 결과
    • 핵심은 구현을 단순하게 유지하는것
      • json i/o api에 의존하는것을 피하자
      • 원시텍스트 api 사용 권고
    • 보안과 독립성
      • 통신은 항상 까다로움
      • 버그가있으면 오류가 날수있음
      • pull보다 push접근방식으로 복제 구현
    • pii data
      • 변환 복제기 패턴 사용
      • 해당 속성을 제거하기 위한 변환단계 추가
    • latency
      • 인프라기반 구현은 추가적인 지연이 종종 발생
      • SLA를 확인해서 수용할만한지 검토 필요
    • metadata
      • 중요함
      • 파티션 내 헤더와 이벤트 순서에도 신경써야함

변환 복제기

transformation replicator

  • 문제
    • 운영 > 스테이징 데이터복제가 필요한데, pii 데이터가 포함될때
    • 단순 passthrough job은 사용 불가
  • 해결책
    • spark, flink등의 처리 프레임워크에서 사용자 정의 매핑함수 사용
    • sql select문으로 변환
  • 결과
    • 텍스트 파일 형식의 변환 위험
      • ex. 날짜시간형식이 표준과 다를수있음
      • job실패시 불필요한 작업 초래
      • 따라서, ‘단순하게 유지’해야함
      • ex. 타임스탬프 컬럼을 그대로 정의하기보다 문자열로 설정
    • 비동기화
      • pii - 새 속성이 나타날수도, 아니던게 pii로 분류될수도있음
      • 데이터 거버넌스 도구 필요
      • 변환 로직 자동화, or 직접 규칙 구현

2.4 데이터 컴팩션

  • 데이터셋은 시간이 지나며 데이터가 유입되어 규모가 커지면 병목현상이 일어날 수 있음
  • 특정 시점에 이르면 파일을 나열하는것과 같은 메타데이터 관련작업이 데이터 처리 변환보다 더 오래걸리게됨

컴팩터

기본 파일의 스토리지의 용량을 줄여야함 → 컴팩터 패턴

  • 문제
    • 10분이내에 배치가 끝나야하는 job
    • 작은 파일들이 너무 늘어나 메타데이터 오버헤드가 생김
    • 실행시간의 70%가 처리할 파일 sort에 사용됨
    • 시간지연, 서비스비용에 악영향
  • 해결책
    • 대량의 작은 파일을 저장하면 i/o 비용이 커지고 파일 여닫는 시간이 길어짐
    • ⇒ compactor (여러개의 작은 파일을 큰 파일로 결합) 하여 문제 해결
    • 조회시 전체적인 i/o 비용을 줄임
    • 구현
      • 오픈테이블파일 형식 - 트랜잭션 분산 데이터 처리 잡을 실행해 큰 파일로 병합
        • iceberg : rewrite data file 작업
        • delta lake : OPTIMIZE 명령어
        • apache hudi : MoR 테이블 설정 (데이터를 수정할때 변경분을 따로 저장한 뒤, 읽을때 merge해서 보여주는 방식)
      • 데이터 스토어 - 단순 설정으로 컴팩션 실행
        • kafka : 설정된 빈도에 따라 데이터 스토어가 컴팩션 프로세스 관리
  • 결과
    • 비용 vs 성능 trade-off
      • compaction은 연산집약적인 job
      • 파이프라인 외부에서, 드물게 실행하는것을 추천
      • compaction 되기 전에 잡이 실행되면 최적화 기술을 활용하지 못해 문제가 될 수 있음
      • 비용과 성능이 완벽할수 없음을 이해해야함
    • 일관성
      • compaction은 이미 존재하는 데이터를 rewrite하는것
      • consumer는 사용할 데이터와 컴팩션 중인 데이터를 구별하기 어려울 수 있음
      • json, csv같은 원시파일보다 delta lake나 iceberg같은 ACID 속성을 가진 개방형 테이블 파일 형식에서 훨씬 간단하고 안전함
    • 정리
      • compaction job은 원천 파일을 보존
      • 작은파일이 여전히 존재하므로, 점유한 공간을 회수하기 위한 clean job을 완성해야함
      • VACUUM 등의 명령어로 정리 가능

2.5 데이터 준비

언제 데이터 수집을 시작해야 할까?

준비 마커

readiness marker(준비 마커)는 적절한 시점에 수집을 시작하게하는 유용한 패턴 데이터셋의 완전성을 보장하도록 데이터를 수집

  • 문제
    • 데이터를 사용하는 팀들이 잡 완료시점을 몰라, 불완전한 데이터셋을 수집하게됨
    • 데이터 소비가 가능한 시점을 알려주는 메커니즘을 달라고 요청함
  • 해결책
    • readiness marker패턴을 사용해 데이터셋을 처리 준비 상태로 표시 가능
    • 구현
      • 이벤트를 사용해 데이터셋의 완전성을 알림.
        • 데이터 생성이 성공한 후 생성된 flag file로 구분
        • spark, delta lake 등 데이터 처리계층에서 사용 가능
        • 혹은 데이터 ochestration계층에서 데이터 처리 후 별개 작업으로 플래그 생성
      • 파티션된 데이터에서는 관례적으로 준비마커를 생성
        • 파티션 10을 처리하고싶다면, 파티션11작업을 시작하기까지 기다려야함.
  • 결과
    • 독자가 데이터 검색과정을 제어하는 pull 접근방식을 사용
    • 강제성 부족
    • 지연 데이터에 대한 신뢰성
      • 파티션 기반 구현 시 데이터 지연이 필연적으로 발생
      • 파티션을 한번 닫히면 절대 변하지 않을 불변의 영역으로 간주하거나
      • 변경조건을 명확히 정의하고 컨슈머와 공유해야함

2.6 이벤트 주도

  • 이상적인 수집 시나리오에서는 새로운 데이터셋을 정기적으로 이용
  • 비이상적인 시나리오에서는 데이터가 들어오는 빈도를 예측하기 어려움
  • 정적인수집 → 이벤트 기반 수집으로 사고방식 전환 필요

외부 트리거

readiness marker pattern은 새로운 데이터 확인할 책임이 컨슈머에있는 pull semantic event-driven 데이터셋은 프로듀서가 알려주는 push semantic을 선호

  • 문제
    • 새롭게 처리할 기능이 있을때만 파이프라인을 처리하고싶다
    • 중앙 메시징 버스로 알림이벤트를 보낼수 있는 상태라, 이를 활용하고자 함
  • 해결책
    • 데이터 생성이 예측 안될때가 많음
    • 보통 짧은 interval의 cronjob으로 해결 가능하나,
    • 컴퓨팅 자원 낭비 / 불필요한 운영 부담
    • ⇒ external trigger pattern (event-driven) 사용이 적합
    • 세가지 주요작업으로 구성됨
      1. 알림 채널 구독
      2. 알림에 반응
      3. 데이터 오케스트레이션 or 데이터 처리 계층에서 수집 파이프라인 trigger
  • 결과
    • push vs pull
      • pull : 처리할 이벤트가 있는지 지속적으로 확인
      • push : producer가 알리지 않는 한 아무것도 하지 않음
    • 실행 context
      • external trigger가 단순 오케스트레이터 엔드포인트를 호출하는 ping 메커니즘이 될 위험이 있음
      • 트리거된 파이프라인은 유지관리 되어야함을 명심
      • 트리거링 호출에 적절한 meta data 정보를 강화하는게 좋음
        • trigger job version
        • alert envelope
        • 처리에 걸린 시간
        • 이벤트 시간
      • ⇒ 장애 발생 원인 파악에 유용
    • 오류관리
      • 실패 트리거 설계시 이벤트 유지를 목표로 해야함