data7 MIN READ

[데이터 엔지니어링 디자인 패턴] 06. 데이터 흐름

[데이터 엔지니어링 디자인 패턴] 06. 데이터 흐름

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

데이터셋 생성에 필요한 모든 파이프라인을 설계, 조정해보자
데이터 흐름을 디자인함으로써 데이터로 더 많은 혜택을 창출할 수 있다

6.1 시퀀스

  • 순서 = 파이프라인의 복잡성, 성능, 유지보수에 영향을 미치는 중요한 요소.

로컬 시퀀서

Local Sequencer pattern 로컬, 즉 동일한 pipeline / job 내에서 조정하는 방법.

  • 문제
    • 실행 실패가 잦아진 레거시 잡을 개선하려고함
    • 비즈니스로직은 그대로 유지되어야함
  • 해결책
    • 가장 쉬운방법은 비즈니스로직을 작은단위로 분해하는것.
    • 하나의 컴포넌트를 작은 여러 연결된 항목으로 분리하여 순차적으로 실행
    • 태스크간 의존성은 데이터셋 의존성에 맞게 구성
    • 데이터 오케스트레이션 기반 / 데이터 처리계층 기반 모두에 구현 가능
    • 아래 세 가지 기준에 따라 구현 레이어 선택
      • 관심사의 분리
      • 유지보수성
      • 구현을 위한 노력
  • 결과
    • 경계
      • 경계를 잘못 설정하면 latency가 길어지거나 다른 파이프라인에 영향을 줄 수 있음
      • 재시작 경계 (즉, 개별적으로 재시작 니즈가 있는 구간이 어딘지?) 를 고려해야함
      • 컴퓨팅 비용이 필요한 작업 사이에 경계를 설정하기도함
      • 트랜잭션 관점에서 로직 분리를 할 수도 있음

독립된 시퀀서

Isolated Sequencer Pattern 보통 독립된 여러 워크플로우가 서로 협력하여 최종 인사이트를 생성하는 더 복잡하고 커다란 워크플로우의 일부가됨.

  • 문제
    • 팀에서 raw dataset을 정리, 강화하여 다양한 뷰로 제공하는중
    • 데이터 시각화팀에서는 해당 데이터를 변환하는 작업을 추가로 하려고함.
  • 해결책
    • raw data의 정리/강화 파이프라인과 데이터 변환 파이프라인을 단일 프로세스로 병합 불가능 (조직이 다름)
    • 물리적으로 독립된 파이프라인을 결합할 방법이 필요
    • 컨텍스트 경계를 먼저 정의
      • ex. producer / consumer
      • 그러나 데이터 producer면서 동시에 consumer 가 되는 상황도 있음
      • 접근방식에 따라 로직을 여러 파이프라인으로 나누는 방안 고려
      • 둘을 함께 유지할 수도 있음
    • trigger machanism을 정의
      • 데이터 기반 전략 : 준비마커패턴 사용. 컨슈머는 파일을 센싱하여 작업 시작
      • 작업 기반 전략 : 프로듀서가 직접 컨슈머 잡을 트리거.
  • 결과
    • 모든 파이프라인을 동기화상태로 유지해야함
    • 독립성을 추가함으로써 별도의 운영 제약이 추가됨
    • 스케쥴링
      • 태스크기반 해결책 - 프로듀서가 컨슈머를 트리거링하기위해 같은 스케쥴러를 공유하거나 더 복잡한 구조를 도입해야함.
      • 프로듀서는 trigger skip condition정의 필요
      • 컨슈머는 프로듀서일정에 맞춰 자신의 일정을 조정해야함
    • 소통
      • 여러팀에서 파이프라인을 관리 ⇒ 조직에 효과적인 소통문화 필요

6.2 팬인

  • 시퀀스는 각 단계가 특정 순서를 따라 진행됨
  • 보통의 파이프라인은 branch가 생성되기도 하고, 다시 merge되기도 함

정렬된 팬인

Aligned Fan-in Pattern 부모태스크가 성공해야 모든 하위 태스크가 계속 진행할 수 있음 느슨한 결합으로 파이프라인을 구성.

  • 문제
    • 방문이벤트는 시간별로 분할됨
    • 컨슈머는 전체 view에만 관심이 있음
  • 해결책
    • 태스크간 의존성이 존재
    • 의존성을 데이터 오케스트레이션 계층 or 데이터 처리계층에서 해결 가능
    • 오케스트레이션계층 구현
      • 별도의 브랜치를 정의하고 공통 태스크로 병합
      • ex. 각 시간에 대한 부분집계 생성 → 모든 부분집계 완료 후 최종 view 계산
    • 데이터처리계층
      • 간단하지않음
      • 브랜치를 정의하고 브랜치들이 어떻게 상호 작용할지 정의 필요
      • UNION (수직적 정렬) or JOIN (수평적 정렬) 사용
      • feedback loop 최적화라는 장점 존재. (오류나도 빨리알수있음)
      • 특정 시간이 실패할경우, 해당 시간만 수정하고 리플레이하면됨.
  • 결과
    • 인프라 스파이크
      • 탄력적인 프로비저닝 필요
      • 프로비저닝이 어렵다면 적절한 균형점 찾는것이 중요
    • 스케줄링 스큐
      • 부모실행시간이 균형적이지 않으면 scheduling skew 발생
      • 성공한 태스크 여럿이 지연된 태스크 하나를 기다리게됨
    • 스케쥴링 오버헤드
      • 파이프라인 세분화가 과도하면 스케쥴링 오버헤드를 수반
      • 오케스트레이터는 대부분의 자원을 스케줄링 조정에 할당
      • 느슨한 결합 / 높은 가독성에서 감수해야하는 대가
    • 복잡성
      • 결합을 느슨하게 하기위해 분리할수록 파이프라인이 길어짐
      • ⇒ 가독성과 이해도가 낮아져 부정적 효과를 초래하기도함
      • 결국 적절한 경계를 찾아야.. (trade-off)

비정렬 팬인

Unaligned Fan-in Pattern 때때로 모든 부모가 성공해야한다는 조건은 latency를 늘리고, 잘못된 semantic을 초래

  • 문제
    • Aligned Fan-in Pattern으로 구현한 파이프라인에서, 실패한 태스크를 관리할 적절한 메소드가 부족
    • 회의에서 일부 데이터셋이라도 공개하고, 나중에 빈 부분을 채우자고 합의됨
  • 해결책
    • 비정렬 팬인 패턴을 사용하면 일부 부모가 성공하지 못해도 자식 태스크 실행이 가능
    • 모든 부모가 실패하면 실패 기준에 따라 fallback or 오류 관리 작업을 트리거할 수 있음
    • 오케스트레이션 도구에서 trigger condition을 설정해야함
  • 결과
    • 팬인 패턴과 동일한 단점을 가짐
    • 가독성
      • 데이터 흐름에대한 가독성과 이해도를 감소시킬 수 있음
      • 코드를 파악해야만 실행 흐름을 파악할 수 있음
      • 파이프라인이 혼란스러워짐
    • 부분 데이터
      • 컨슈머에게 부분성공에대해 알리는것이 중요함
      • 이게 실패하면, 컨슈머는 완전성 상태에 대해 잘못된 추정을 하게됨
      • 메타데이터 계층에 추가하거나
      • 다운스트림 컨슈머에 알림을 하거나 등..

6.3 팬아웃

  • 한 태스크가 다른 태스크의 입력이 되는 경우
  • 한 데이터셋이 데이터분석팀이나 데이터 사이언스팀 등 여러팀에 다양한 목적으로 사용되는 경우

병렬 분할

Parallel Split Pattern 하나의 부모태스크에 최소 두개이상의 자식이 있는 경우 ⇒ 자식태스크들은 독립적으로 분리되므로, 병렬실행이 가능

  • 문제
    • 레거시시스템을 마이그레이션하려고함
    • 기존 시스템을 유지시키면서, 새 시스템들 가동함
    • 데이터는 양쪽 시스템에 dual write해야하는 상황
  • 해결책
    • 작업을 병렬 부분으로 나누고, 동시에 실행함
    • 데이터 오케스트레이션 계층에서 쉽게 구현 가능 (API사용)
    • 데이처 처리 계층에서는 구현이 간단하진않음
      • 분할처리가 별개의 데이터 조회 작업을 하면 안됨
      • 일반적인 계산이 한번만 실행되어야함
      • 보통 중간 데이터셋을 구체화하여 사용
    • 계산 실행 시간에 민감하다면 전용자원 or 오토스케일링을 통해 병렬 분할 작업을 수행
  • 결과
    • 차단된 실행
      • 분할해 실행한 작업을 다시 조인해야하는경우
      • 각 파이프라인은 가장 느린 브랜치가 완료될때까지 기다려야함
      • ⇒ 느린 브랜치 내보내기 등으로 해결해야함
    • 하드웨어
      • 데이터 처리계층의 경우, 중간데이터셋을 사용하는 자식 태스크들은 동일한 환경에서 실행되어야하기때문에 하드웨어 요구사항이 동일해야함
      • 잡을 나누고 각각 전용 하드웨어에서 병렬잡을 실행하여 완화할수있음

배타적 선택

Exclusive Choice Pattern 공통 부모에 의존하지만 병렬 다운스트림 태스크를 실행하는 대신, 하나만 선택함 (XOR Split)

  • 문제
    • 병렬 분할 패턴으로 수행한 마이그레이션 이후, 백필링이 필요해짐
    • 파이프라인을 새로 생성하지않고 백필링을 하려면?
  • 해결책
    • 자식태스크가 여러개지만 하나만 실행해야하는경우 = 배타적 선택 패턴
    • 어떤 경로를 따를지 조건 평가 작업을 추가
    • 보통 오케스트레이션 프레임워크는 branch operator를 제공
    • 데이터 처리계층에서도 아래 구문들로 구현 가능
      • if-else
      • switch
  • 결과
    • 복잡성 양산 공장
      • if-else 지옥..
    • 숨겨진 로직
      • 잡에 조건문이 생기기때문에, 다른 데이터스토어와 상호작용하는경우 문제가 생김
      • 데이터 오케스트레이션 계층 위에 패턴을 적용하는게 좋을수도.
    • 무거운 조건
      • 데이터 처리계층에 패턴을 구현한다면, 잡의 실행시간에 영향을 미침

6.4 오케스트레이션

  • 데이터 오케스트레이션 계층에 위치한 정적자원의 흐름
  • 데이터 처리 태스크를 수행하는 동적 컴포넌트의 흐름

단일 실행기

Single Runner Pattern 선언된 파이프라인을 단일로 실행

  • 문제
    • 증분 세션화 처리기 패턴으로 세션화 파이프라인 구현
    • 오케스트레이션 작업이 필요한 상태
  • 해결책
    • 실행기가 필요
    • 증분적이므로 순차실행을 포함
    • 단일 실행기 = 동시성 수준을 1로 설정하여, 항상 단일로 실행을 보장
  • 결과
    • 백필링
      • 재처리시간이 느려짐
      • 파이프라인 전부를 백필할 필요가 있는지 살펴보고, 일부만 처리하도록해야..
    • 지연
      • 데이터가 점점 지연되면, 모든 다운스트림 컨슈머가 추가지연으로 고통받음
      • 확장성있는 인프라에서 실행해서 완화시켜야함

동시 실행기

Concurrent Runner Pattern 선언된 파이프라인을 동시에 실행

  • 문제
    • 외부의 정적인 상태의 데이터를 가능한 빨리 내부 DB로 가져오고자함
    • 순차 실행은 필요하지 않은 상태
  • 해결책
    • 서로 독립적이고 동시성 제약이 느슨하다면, 동시실행기 패턴 사용
    • 동시성을 1보다 높게 정의
    • with great power comes great responsebility
    • 현재 실행중인 인스턴스가 허용된 동시성 수준까지 동시실행
  • 결과
    • 자원부족
      • 멀티테넌트 환경이면 더욱 영향이 큼
      • 워크로드 관리 기능으로 동시성을 제어
    • 공유 상태
      • 동시실행에서의 가장 흔한 함정
      • 비결정적 실행은 예기치않은 부작용을 생성
      • 중복 트리거 or 일부만 트리거 하는 부작용이 생길수도..