ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [빅데이터의 파이프라인] 1. 워크플로 관리
    책/빅데이터를 지탱하는 기술 2022. 4. 4. 00:24
    반응형

    이 글은 빅데이터를 지탱하는 기술을 읽고 정리한 글입니다.


     

     

     

    1. [기초 지식] 워크플로 관리


    워크플로 관리

    - 정해진 업무를 원할하게 진행하기 위한 구조

    - 다수의 업무 시스템에 내장되어 있어 매일 매일의 태스크를 관리하는데 이용

    - 이 구조가 정기적인 배치 처리의 실행에도 유용하여 데이터 처리 현장에서 자주 이용됨

     

    워크플로 관리 도구와 태스크

    - 태스크: 데이터 파이프라인에서 데이터가 이동하면서 정해진 처리를 반복함. 이때 개별 처리를 하나의 태스크라함

    - 워크플로 관리 도구: 정기적으로 태스크를 실행하고, 비정상적인 상태를 감지하여 그것에 대한 해결을 돕는 도구

    - ex) Airflow가 제일 유명하고, 이외에 Azkaban, Digdag, Luigi, Oozie등이 있다.

     

    워크플로 관리 도구의 기능

    - 태스크를 정기적인 스케줄로 실행하고, 그 결과를 통지한다.

    - 태스크 간의 의존 관계를 정하고, 정해진 순서대로 실행한다.

    - 태스크의 실행 결과를 보관하고, 오류 발생하면 재실행을 할 수 있도록 한다.

    → 데이터 파이프라인의 모든 태스크를 관리하기 쉽게 한 것

     

    워크플로 관리 도구의 종류

    1. 선언 형

    - XML, YAML 등의 서식으로 워크플로를 기술하는 타입

    - 미리 제공된 기능만 사용할 수 있어서 이 범위 안이면 최소한의 기술로 태스크를 정의할 수 있다.

    - 다 똑같은 코드를 사용하기 때문에 유지 보수성이 높다.

    - 동일 쿼리를 파라미터만 바꾸어 여러번 실행하거나, 워크플로를 단순 반복적으로 자동 생성하는 경우 사용한다.

    - ex) Azkaban, Digdag, Oozie

     

    2. 스크립트 형

    - 스크립트 언어로 워크플로를 정의하는 타입

    - 태스크의 정의를 프로그래밍으로 할 수 있어서 유연하게 워크플로를 조립 가능하다.

    - 데이터 처리를 태스크 안에서 실행하는 것이 가능하다.

    - ex) Airflow, Luigi

     

    → ETL 프로세스에는 스크립트 형, SQL의 실행에는 선언 형으로 나누어 사용하면 좋다.


     

     

     

    2. 오류로부터의 복구 방법


    배치 처리 동작에 수시간이 걸리면 실패할 경우 재실행할 때 매우 치명적이다.

     

    복구와 플로우 재실행

    기본적으로 워크플로 관리에서는 자동 복구가 아닌 수작업에 의한 복구를 전제한 태스크를 설계한다.

    플로우는 워크플로 관리 도구에 의해 실행되는 일련의 태스크라고 하는데, 각 플로우에는 실행 시에 고정 파라미터가 부여되고, 일별 배치처리라면 특정 날짜가 파라미터가 된다. 그래서 동일한 플로우에 동일한 파라미터를 건네면 완전히 동일한 태스크가 실행되도록 하는 것이 복구의 기초다.

    대부분의 워크플로는 과거에 실행한 플로우와 파라미터를 자동으로 DB에 기록하여 실패한 플로우를 확인한 후 재실행하는 것만으로 복구가 완료될 수 있다.

     

    재시도

    여러 번 발생하는 오류는 수작업 대신 태스크 단위의 자동적인 재시도를 하게 만드는 것이 좋다. 재시도를 할 때 주의할 점은 결과 자체는 실패지만 데이터 전송에 성공했을 수도 있으므로 데이터가 중복되는 문제가 존재한다.

     

    백필

    플로우 전체를 처음부터 다시 실행하는 방법도 존재하는데, 여기서 일정 기간의 플로우를 연속적으로 실행하는 백필이라는 기능을 사용한다. 참고로 백필을 사용하여 대량의 태스크를 재실행하면 커다란 부하가 걸려 대량의 오류가 발생할 수 있기 때문에 자동적인 재시도는 무효로 하고, 오류는 모두 통지하는 것이 좋다. 이후 오류를 다시 재실행하면 안정적으로 백필이 완료 된다.


     

     

     

    3. 멱등한 조작으로 태스크를 기술하기


     

    각 태스크는 마지막까지 성공하거나 실패하면 아무것도 남지 않음중에 하나만이 존재해야 한다.(= 원자성)

     

    원자성 조작

    트랜잭션 처리에 대응한 데이터베이스라면 여러 번의 작업을 한 번의 트랜잭션으로 실행할 수 있지만, 그렇지 않으면 여러 번을 작업을 전부 태스크로 나누어 원자성을 만족할 수 있도록 해준다. 하지만 원자성 조작이 끝나자마자 에러가 일어나면 원자성 조작이 실패했다고 워크플로는 판단할 수 있어서 데이터 중복이 발생할 수 있다. 그래서 원자성 조작에 의존한 플로우를 만들기 보다는 멱등한 조작을 할 수 있도록 한다.

     

    멱등한 조작

    멱등이란 같은 연산을 여러 번 적용해도 동일한 결과가 주어지는 것이다. 그래서 SQL이면 테이블을 삭제한 후에 다시 만드는 것이 멱등한 조작이 될 수 있다. 파일을 분산 스토리지에 업로드한다면 매번 새로운 파일명을 만드는 경우 데이터를 추가하는 것이고, 동일 파일명으로 덮어쓰는 것은 치환이다. 그래서 각 태스크는 추가 또는 치환중에 하나를 선택해야한다. 원칙적으로 각 태스크는 치환을 사용한다.

     

    멱등한 추가

    현실에서는 항상 멱등한 태스크를 구현하기가 힘들다. 그래서 데이터를 치환하게 된다면 테이블 파티셔닝 사고방식을 사용하여 시간 단위로 파티션 단위를 만들어 데이터를 덮어쓰도록 한다. 이때 파티션의 모든 데이터를 삭제하는데 TRUNCATE 문이나 INSERT OVERWRITE 문의 효율 좋은 명령을 사용하면 하나의 시계열 테이블에 데이터가 추가되는 듯하면서 태스크 단위의 멱등성을 유지할 수 있게 된다.

    테이블 파티셔닝의 구현은 시스템에 따라 전혀 다르기 때문에 실제로는 이용하는 시스템에 맞추어 플로우를 조립할 필요가 있다. 그리고 태스크를 멱등으로 구성하기 어렵다면 멱등을 포기하고 원자성을 지닌 추가만으로 운용한다. 이때 데이터 중복 때문에 자동 재시도는 무효로 하고, 오류는 수작업으로 복구해야 한다.

     

     

    원자성을 지닌 추가

    복잡한 플로우는 하나의 테이블에 여러번 데이터를 쓸 수도 있기 때문에 테이블에 넣기 전에 중간 테이블을 만들고 마지막에 테이블에 한 번에 추가하는 것이 안전하다. 그래서 중간 테이블은 데이터를 치환하는 것으로 멱등한 조작을 할 수 있도록 하고, 마지막엔 테이블에 추가하여 원자성을 가질 수 있도록 한다.


     

     

     

    4. 워크플로 전체를 멱등으로 하기


    1. 데이터 수집의 파이프라인에서는 테이블 파티셔닝을 도입함으로써 파티션 단위의 치환이 가능하다. 이때 스트리밍형 뿐만 아니라 벌크 형의 데이터 전송에서도 워크플로 관리 도구에서 날짜와 시간을 파라미터로 전달함으로써 치환 형의 태스크를 구현할 수 있다.

    2. 데이터 마트를 구축하는 플로우에서는 테이블마다 치환을 할 수 있도록 한다. 하지만 성능상의 이유로 추가를 하는 경우도 생긴다.

    3. 각 태스크를 멱등으로 하는 것이 제일 이상적이지만, 최종적으로 워크플로가 안정적으로 실행되고 있으면 데이터 중복만 주의하면 문제될 것이 없다. 하지만 데이터 자체가 문제에 생기는 경우에는 안전하지 않다. 그래서 재실행의 안정성을 높이려면 적어도 각 플로우가 전체로서 멱등하게 되도록 구현을 해야한다. 이때 중간 테이블을 초기화해야 재실행해도 안전하다.


     

     

     

    5. 태스크 큐


    이때 컨트롤하는 방법은 병렬화를 하는 것인데 잡 큐, 태스트 큐로 불리는 구조를 사용하여 모든 태스크를 큐에 저장하여 일정 수의 워커 프로세스가 태스크를 순서대로 꺼내서 병렬화가 실현될 수 있게 한다.

     

    병목 현상의 해소

    각 태스크는 CPU 사용뿐만 아니라 디스크 I/O, 네트워크 I/O도 소비하기 때문에 서버의 코어 수보다 많은 워커를 투입하면 실행속도를 더 높일 수 있다. 하지만 워커를 너무 증가시키면 어디서 병목 현상이 생겨나 성능 향상이 되지 않거나, 오류가 발생하게 된다. 이때 오류는 서버의 내부적인 요인과 외부적인 요인으로 나뉜다. 이때 외부적인 요인은 문제를 제거할 수 없다.

     

    오류가 발생하는 서버의 내부적인 요인

    - CPU 사용률 100%: CPU 코어 수를 늘리거나 서버를 증설한다.

    - 메모리 부족: 메모리를 증설하거나, 스왑 디스크를 추가하거나, 태스크를 작게 분할한다.

    - 디스크 넘침: 각 태스크가 임시 파일을 삭제하는지 확인하거나, 디스크를 증설한다.

    - 디스크 I/O의 한계: SSD 등의 고속 디스크를 사용하거나, 여러 디스크로 분산한다.

    - 네트워크 대역의 한계: 고속 네트워크를 사용하거나, 데이터의 압축률을 높인다.

    - 통신 오류나 타임 아웃: 시스템 상의 한계일 가능성이 있다. 서버를 분리해본다.

     

    태스크 수의 적정화

    하나의 파일 전송을 하나의 태스크로 고려하지 말고, 큰 파일이라면 태스크에는 날짜와 시간이 파라미터로 건네지므로 지정된 시간의 데이터를 모아서 처리할 수 있도록 구현한다. 파일이 1년이 걸려서 만들어진다면 태스크를 1일씩으로 나누어서 태스크의 수를 365개로 만들게 한다.

    이렇게 태스크를 적절하게 크게 만들어주면, 효율적으로 실행할 수 있게 된다. 작은 파일을 모아 하나의 파일로 만들거나, 여러 파일을 한 번에 업로드하는 명령을 사용할 수 있기 때문에 좀 더 많은 워커로 태스크를 동시에 실행할 수 있으므로 처리 효율을 좋게하는 조합을 발견할 수 있게 된다. 이런 최적화 방법은 Haddop과 같은 분산 시스템에서 이용해도 변하지 않는다.

    결과적으로 워크플로 관리 도구에 등록된 태스크는 적당한 크기로 분할된 다수의 태스크가 여러 워커로부터 호출되고 있는 상태가 된다. 만약 지연 및 오류가 발생하면 태스크의 크기를 바꾸거나 자원을 증설해서 문제를 해결할 수 있기 때문에 워크플로 관리 도구를 사용하는 것이 좋다.


    반응형

    댓글

Designed by Tistory.