[빅데이터를 지탱하는 기술] 5장_빅데이터 파이프라인

1. 워크 플로우 관리

기초 지식
  1. 워크 플로우 관리 도구

    워크 플로우 관리 도구의 주요 역할은, 정기적으로 태스크를 실행하고 비정상적인 상태를 감지하여 해결을 돕는 것이다.

    ex) Airflow, Azkaban, Digdag, Luigi, Oozie

  2. 태스크

    데이터 파이프라인의 실행 과정에서 데이터를 잇달아 이동하면서 정해진 처리를 반복하는데, 이때 실행되는 개별 처리이다.

  3. 기본 기능

    • 테스크를 정기적인 스케쥴로 실행하고 결과 통지

    • 테스크 간의 의존 관계를 정하고 순서대로 빠지없이 실행

    • 테스크의 실행 결과를 보관하고, 오류 발생하면 재실행 할 수 있도록 하기

  4. 선언 형과 스크립트 형

    • 선언형 : XML 이나 YAML 등의 서식으로 워크플로우 기술
    • 스크립트형 : 스크립트 언어로 워크플로우 정의
오류로부터 복구 방법

모든 오류를 사전에 예상하는 것은 불가능하기 때문에, 오류 발생 가능성을 고려하여 대처 방법을 결정해야한다.

  1. Retry

    재시도를 반복해도 문제가 없는 태스크라면, 1회나 2회의 재시도를 실행해도 좋다.

    그러나, 그 이상은 재시도가 아니라 올바른 문제 해결 방법을 찾아야한다.

  2. Backfill

    플로우 전체를 처음부터 다시 실행한다. 다음 상황에 사용한다.

    • 태스크의 실패가 며칠 동안이나 계속된 후에 이를 모아서 재시도 하고 싶을 때
    • 새롭게 만든 워크 플로우를 과거로 거슬라 올라가 실행하고 싶을 때
재실행의 안정성을 위한 두가지 방법
  1. 원자성 조작 (Atomic Operation)

    예를 들어, INSERT 문 2회를 호출하는 태스크가 있다고 하자.

    첫 번째의 INSERT 가 종료되고 오류가 발생하면 태스크를 재실행하면 동일한 데이터가 다시 쓰이게 될 수 있다.

    이 문제를 회피하기 위해, 각 태스크가 시스템에 변경을 가하는 것을 한 번만 할 수 있도록 하는 것이다.

    쓰기가 필요한 수 만큼 테스크를 나누는 것이다.

    하지만, 태스크 구현상의 버그 등으로 원자성 조작 직후에 문제가 발생하면 원자성 조작 자체는 성공했어도 워크 플로우 관리 도구에서는 오류로 여길 수 있다.

  2. 멱등한 조작

    더 확실한 방법은, 동일한 태스크를 여러 번 실행해도 동일한 결과가 되도록 하는 것이다.

    예를 들어 분산 스토리지에 파일을 업로드할 때,

    • 매번 새로운 파일명을 만들 경우 데이터를 추가 (append) 하는 것이고,
    • 동일 파일명으로 덮어쓰면 치환 (replace)하는 것이다. 치환은 반복해도 결과가 변하지 않으므로 멱등하다.
데이터 추가
  1. 멱등한 추가

    과거의 모든 데이터를 치환하면 멱등하지만 부하가 커진다. 그래서, Table Partitioning 이 필요하다.

    예를 들면 테이블을 1일마다 또는 1시간 마다 파티션으로 분할하고 파티션 단위로 치환하는 것이다.

    파티션의 모든 데이터를 삭제할 때, TRUNCATE 문이나 INSESRT OVERWRITER 문 등을 사용할 수 있다.

    ex) Hive 는 파티셔닝 지원, Amazon Redshift 는 파티셔닝을 지원하지 않아 UNION ALL 사용

  2. 원자성을 지닌 추가

    하나의 테이블에 여러번 데이터를 써넣는 경우, 중간 테이블을 이용해 마지막에 목적 테이블에 한 번 추가한다.

    즉, 전반 부분에서는 중간 테이블을 만들기 위해 테이블을 치환하므로 멱등하다.

    그러나 마지막에 INSESRT 는 단순히 추가이므로 전체로서는 멱등하지 않다.

    단, 마지막에 쓰기를 1회만 실시하므로 이것은 원자성을 지닌 조작이다.

    그래서 플로우가 실패해도 아무것도 쓰이지 않아 실패한 태스크를 재실행해도 복구가 완료된다.

워크 플로우 전체를 멱등하게 하기

재실행의 안정성을 위해서는, 멱등하게 구현해야한다.

Task Queue : 자원의 소비량 컨트롤

대량의 테스크를 동시 실행하면 서버에 과부하가 걸리므로 어느 정도 제한 해야한다.

워크 플로우 관리 도구는, 태스크의 크기나 동시 실행 수를 변화시켜 자원의 소비량을 조정해 모든 태스크가 원활하게 실행되도록 할 수 있다.

이 때, Job Queue 또는 Task Queue 를 사용할 수 있다.

모든 태스크는 큐에 저장되고 일정 수의 워커 프로세스가 순서대로 꺼내며 병렬화가 실현된다.

2. 배치 형 데이터 플로우

MapReduce

데이터 처리 첫 번째 단계를 Map, 그 결과를 모아서 집계하는 두 번째 단계를 Reduce 라고 한다.

이렇게 Map 과 Reduce 를 반복하면서 목적하는 결과를 얻을 때 까지 계속 데이터를 변화하는 구조가 MapReduce 이다.

MapReduce 는 Map 과 Reduce 의 하나의 사이클이 끝나지 않으면 다음 처리로 이동하지 않는다. 즉, 하나의 사이클에서 다음 사이클로 이동할 때 까지 대기 시간이 발생한다.

데이터 플로우

이전의 MapReduce 를 사용한 데이터 처리에서는, MapReduce 프로그램을 워크플로우의 태스크로 등록해 다단계의 복잡한 데이터 처리를 할 수 있었다.

현재는, 다단계의 데이터 처리를 분산 시스템 내부에서 실행할 수 있다. 이것을 데이터 플로우라고 한다.

ex) 데이터 플로우를 위한 프레임워크 : Google Cloud Dataflow, Apache Spark, Apache Flick

MapReduce 를 대신할 세로운 프레임워크

세로운 프레임워크의 공통 특징은 DAG (Direct Acyclic Graph) 이다.

다음 두 가지 성질이 있다.

  1. 방향성 : 노드와 노드가 화살표로 연결
  2. 비순환 : 화살표를 따라가도 동일 노드로 돌아오지 않음

DAG 관점에서 MapReduce 와 데이터 플로우의 차이는,

  1. MapReduce

    MapReduce 도 Map 과 Reduce 의 두 종류 노드로 이루어진 DAG 라 생각할 수 있다.

    하지만, 하나의 노드에서 처리가 끝나지 않으면 다음 처리로 진행할 수 없다.

  2. 데이터플로우

    DAG 를 구성하는 노드가 모두 동싱 병행으로 실행된다.

    처리가 끝난 데이터는 네트워크를 거쳐 차례대로 전달된다.

    먼저 데이터 파이프라인 전체를 DAG 로 조립한 뒤 실행해서, 내부 스캐쥴러가 분산 시스템에 효과적인 실행 계획을 세운다.

데이터 플로우와 워크플로우 조합하기

테스크를 정기적으로 실행하거나 실패한 테스크를 기록하여 복구하는 것은, 데이터플로우가 아니라 워크 플로우의 관리가 필요하다. 따라서, 데이터 플로우의 프로그램도 워크 플로우의 일부로 실행되는 하나의 태스크로 고려될 수 있다.

  1. 데이터를 읽어들이는 플로우

    데이터 플로우로부터 읽어 들일 데이터는 성능적으로 안정된 분산 스토리지에 배치해야한다. 외부의 데이터 소스에서 데이터를 읽어들일 때는 읽기 속도에 한계가 있으므로 데이터 플로우를 사용한다고 해도 빨라진다고 단언할 수 없다.

    분산스토리지로 데이터 복사가 완료되면 데이터 플로우로 처리한다.

  2. 데이터를 써서 내보내는 워크플로우

    데이터 플로우 안에서 대량의 데이터를 외부에 전송해서는 안된다. 왜냐하면,

    • 쓰기 작업에 오래 걸리면, 실행이 완료되지 않아 자원을 계속해서 소비 할 수 있다.

    • 최악의 경우, 쓰기 작업이 실패해 처음부터 다시 데이터 처리를 재실행 해야 할 수 있다.

    그래서, 데이터 플로우는 CSV 파일과 같이 취합하기 쉬운 형식으로 분산 스토리지에 넣는 것 까지한다.

    외부 시스템에 데이터를 전송하는 것은 워크 플로우의 역할이다.

    • 벌크 형 전송 도구를 사용해 태스크를 구현하거나

    • 외부 시스템쪽에 파일을 읽어들이도록 지시한다.

데이터 플로우와 SQL 을 나누어 사용하기

  1. SQL을 MPP 데이터베이스에서 실행

    데이터웨어하우스의 파이프라인

    로드되는 데이터를 만드는 부분까지가 데이터 플로의 역할

  2. SQL을 분산 시스템 상의 쿼리 엔진에서 실행

    데이터마트의 파이프라인

    구조화된 데이터를 만드는 부분까지가 데이터플로우의 역할

3. 스트리밍 형 데이터 플로우

배치 처리와 스트림 처리

  1. 배치 처리

    도달한 데이터를 우선 분산 스토리지에 보관한다.

    데이터가 영속적으로 보관되기 때문에 몇 번이고 재실행 가능하다.

    집계 효율이 높은 열 지향 스토리지를 구축할 수 있다.

    실행 시에 데이터 양이 정해지기 때문에 유한 데이터 (bounded data)

  2. 스트림 처리

    데이터 도달과 동시에 처리가 시작된다.

    재실행하는 것은 고려하지 않는다.

    처리한 결과는 시계열 데이터에 적합한 데이터 스토어에 보관하거나 실시간 시스템에 전송한다.

    제한 없이 데이터가 보내지기 때문에 무한 데이터 (unbounded data)

    ex) Spark Streaming

스트림 처리에 의한 1차 집계

분산 스토리지에도 성능 상이나 비용 상의 한계가 있다.

데이터 양이 많아 한계를 넘어서면, 스트림 처리를 사용해 흐름량을 줄일 수 있다.

스트림 처리의 두 가지 문제에 대한 대처

스트림 처리의 문제 두 가지가 있다.

  1. 틀린 결과를 어떻게 수정할 것인가

    새롭게 도달한 데이터만 처리한다.

  2. 늦게 전송된 데이터 취급을 어떻게 할 것인가

    집계가 종료된 후에 도착한 데이터가 있어서, 스트림 처리의 결과가 부정확해질 수 있다.

이 문제 해결을 위해, 스트림 처리와 별개로 배치 처리를 실행시켜 배치 처리의 결과가 옳다고 할 수 있다.

예를 들어, 일별 보고서를 속보 값으로 하고 월별 보고서를 확정값으로 분류하는 것이다.

이를 발전 시킨 방법이 람다 아키텍쳐, 람다 아키텍쳐를 단순화한 카파 아키텍쳐가 있다.

  1. 람다

    세 레이어로 구성된다.

    • 배치 레이어

      모든 데이터는 배치 레이어에서 처리한다. 대규모 배치 처리를 위해 실행하며 1회 처리가 오래 걸린다.

    • 서빙 레이어

      배치 처리 결과는 서빙 레이어를 통해 접근한다. 응답이 빠른 데이터베이스를 설치해서 집계 결과를 바로 추출한다.

      서빙 레이어에서 얻어진 결과를 배치 뷰 라고 한다. 정기적으로 업데이트 되지만 실시간 정보는 얻을 수 없다.

    • 스피드 레이어

      스피드 레이어에서 얻은 결과를 실시간 뷰라고 한다. 배치 뷰가 업데이트 될 동안에만 이용되고 오래된 데이터를 순서대로 삭제된다.

    배치뷰와 실시간 뷰를 조합시키는 형태로 쿼리를 실행한다. 최근 24시간 집계 결과는 실시간 뷰를 참고하고 그 이전 데이터는 배치뷰를 이용할 수 있다.

    실시간 뷰의 결과는 나중에 배치 뷰로 치환된다. 그래서 스트림 처리가 정확하지 않아도 길게 보면 문제가 없다.

  2. 카파

    람다 아키텍쳐는 스피드 레이어와 배치 레이어가 모두 같은 처리를 구현하고 있으므로 번거롭다.

    그래서, 카파 아키테쳐는 스피드 레이어만 남긴다. 대신, 메세지 브로커의 데이터 보관 기한을 길게하여 문제 발생시 메세지 배송 시간을 과거로 다시 설정한다. 그러면 과거의 데이터가 다시 스트림 처리로 흘러 들어 실질적으로 재실행이 이루어진다.

    문제점은, 부하가 높아진다는 것이다. 대량의 과거 데이터를 흘려보내면 평상시와 비교해 몇 배의 자원을 소비하기 때문이다. 클라우드 서비스 보급에 그런 자원을 확보하는 것이 어렵지 않으므로 필요에 따라 스트림 처리를 다시 하는것이 간단하는 것이 카파 아키텍쳐의 주장이다.

Out of Order 의 데이터 처리

스트림 처리를 할때 늦게 도달한 메세지, 즉 프로세스 시간과 이벤트 시간의 차이는, 이벤트 시간 윈도윙으로 해결한다.

즉, 이벤트 시간에 의해 윈도우를 나누는 것이다.

메세지가 배송된 데이터는 무작위 순이기 때문에 적절히 순서를 바꿔 집계 결과를 업데이트해야한다.

데이터가 도달할 때마다 해당하는 윈도우를 재집계한다. 데이터를 무한히 계속 보관할 수 없으므로 일정 이상 늦게 온 데이터는 무시한다.


빅데이터를 지탱하는 기술 <니시다 케이스케>

Comments