데이터 중심 어플리케이션 설계 10장

devkwon·2025년 10월 7일

BackEnd

목록 보기
5/9

일괄처리

여러 현대 데이터 시스템에서 가정하고 있는 데이터 처리 방식은 먼저 시스템에 요청하거나 지시를 보낸 후 성공한다면, 잠시 뒤에 해당 시스템으로부터 결과를 반환받는 방식.

이러한 온라인 시스템은 사용자로서 요청을 보내고 응답을 기다린다고 가정. 허나 사용자는 오래 기다릴 수 없기 때문에 응답 시간 단축에 많은 노력

HTTP/REST 기반 API 때문에 요청/응답 방식의 상호작용이 매우 당연한 것 같지만, 유일한 방법은 아님.

다음과 같은 3가지의 시스템이 존재함.

  • 서비스(온라인 시스템)
    클라이언트로부터 요청이나 지시가 올 때까지 기다림. 가능한 빨리 요청을 처리해서 응답을 되돌려 보내야한다. 따라서 응답 시간이 성능을 측정하는 지표이다. 때론 가용성이 매우 중요한데 클라이언트가 접근하지 못하면 오류 메시지를 받을지 모른다.

  • 일괄 처리 시스템(오프라인 시스템)
    매우 큰 입력 데이터를 받아 이를 처리하는 작업을 수행하고 결과 데이터를 생산. 많은 시간이 걸리기에 사용자는 대기하지 않음. 하루에 한 번 등 정해진 시간에만 수행됨. 주요 성능 지표로는 처리량이 대표적.

  • 스트림 처리 시스템(준실시간 시스템)
    온라인/오프라인 중간 시스템. 준실시간 처리(near-real-time processing)으로 불림.
    일괄 처리 시스템과 마찬가지로 정해진 크기의 입력 데이터를 대상으로 동작하지만, 스트림 처리는 입력 이벤트가 발생한 직후 바로 동작함.(일괄 처리 시스템보다 지연시간이 낮음)

일괄처리는 신뢰할 수있고 확장 가능하며 유지보수하기 쉬운 애플리케이션을 구축하는 데 매우 중요한 요소. ex) 구글을 대규모로 확장시킨 맵리듀스(MapReduce), 하둡, 카우치DB, 몽고DB

유닉스 철학

  1. 각 프로그램이 한 가지 일만 하도록 작성하라. 새 작업을 하려면 기존 프로그램에 기능을 추가하지말고 새 프로그램을 작성하라.
  2. 모든 프로그램의 출력은 아직 알려지지 않은 다른 프로그램의 입력으로 쓰일 수 있다고 생각하라. 대화형 입력을 고집하지마라.
  3. 소프트웨어를 빠르게 써볼 수 있게 설계하고 구축하라. 거슬리는 부분은 과감히 버리고 새로 구축하라.
  4. 프로그래밍 작업을 줄이려면 미숙한 도움보단 도구를 사용하라.

맵리듀스와 분산 파일 시스템

맵리듀스는 유닉스 도구와 비슷한면이 있지만 수천 대의 장비로 분산해서 실행이 가능하다는 점에서 차이가 있다. 유닉스 도구와 마찬가지로 맵리듀스 작업은 입력을 수정하지 않기 때문에 출력을 생산하는 것 외에 다른 부수 효과는 없다. 맵리듀스는 작업은 분산 파일 시스템 상의 파일을 입력과 출력으로 사용한다.
하둡 맵리듀스 구현에서 HDFS(Hadoop Distributed File System)라고 하는데 GFS(Google File System)를 재구현한 오픈소스다.

HDFS는 비공유 원칙을 기반으로 하는데 NAS(Netwrok Attached Storage),SAN(Storage Area Network)와 반대이다. 따라서 파이버 채널(Fiber Channel)과 같은 특별한 하드웨어가 필요없다.

HDFS는 각 장비에서 실행되는 데몬 프로세스로 구성된다. 데몬 프로세스는 다른 노드가 해당 장비에 저장된 파일에 접근 가능하게끔 네트워크 서비스를 제공한다. 네임노드(NameNode)라고 부르는 중앙 서버는 특정 파일 블록이 어떤 장비에 저장됐는지 추적한다. 따라서 HDFS는 개념적으로는 매우 큰 하나의 파일 시스템이고 데몬이 실행 중인 모든 장비의 디스크를 사용할 수 있다.

장비가 죽거나 디스크가 실패하는 경우에 대비하기 위해 파일 블록은 여러 장비에 복제된다.
복제는 여러 장비에 동일한 데이터를 복사하는 방식이 있고 리드 솔로몬 코드 같은 삭제 코딩(erasure coding) 방식도 있다.

HDFS는 확장성이 뛰어나다. 수만 대의 장비를 묶어서 사용할 수 있으며 용량은 수백 페타바이트에 달한다. HDFS를 이용한 데이터 저장과 접근 비용은 범용 하드웨어와 오픈소스 소프트웨어를 사용하기 때문에 동급 용량의 전용 저장소 장치를 사용하는 것보다 훨씬 저렴하다.

맵리듀스 작업

  1. 입력 파일을 읽는다. 레코드로 쪼갠다.
  2. 각 입력 레코드마다 매퍼 함수를 호출해 키와 값을 추출한다.
  3. 키를 기준으로 key-value 쌍을 모두 정렬한다.
  4. 정렬된 key-value 쌍 전체를 대상으로 리듀스 함수를 호출한다. 같은 키가 여러번 등장했다면 정렬 과정에서 해당 쌍은 서로 인접한다. 그래서 같은 키를 가지는 값들을 따로 메모리 상에 상태를 따로 유지하지 않고도 쉽게 결합할 수 있다.

이렇게 맵리듀스 작업 하나는 4단계로 구성된다. 2단계(맵)와 4단계(리듀스)는 사용자가 직접 작성한 데이터 처리 코드다. 1단계는 파일을 나누어 레코드를 만드는 데 입력 형식 파서를 쓴다. 3단계는 정렬 단계로 맵리듀스에 내재하는 단계라서 직접 작성할 필요가 없다.

맵리듀스 작업을 생성하려면 다음과 같이 동작하는 두 가지 콜백 함수를 구현해야한다.

  • 매퍼(Mapper)
    매퍼는 모든 입력 레코드마다 한 번씩만 호출된다. 입력된 레코드로부터 키와 값을 추출하는 작업을 한다. 매퍼는 레코드마다 상태를 유지하지 않기 때문에 각 레코드를 독립적으로 처리한다.

  • 리듀서(Reducer)
    맵리듀스 프레임워크는 매퍼가 생성한 key-value 쌍을 받아 같은 키를 가진 레코드를 모드고 해당 값의 집합을 반복해 리듀서 함수를 호출한다. 리듀서는 출력 레코드를 생산한다.

유닉스 도구와 마찬가지로 맵리듀스의 작업은 또 다른 맵리듀스의 작업의 입력이 될 수 있다.

맵리듀스의 분산 실행

맵리듀스는 유닉스의 파이프라인과 다르게 병렬 코드를 따로 작성하지 않아도 여러 장비에서 동시에 처리가 가능하다. 분산 연산에서 매퍼와 리듀서를 유닉스 도구로 구현해도 되지만 일반적으로는 프로그래밍 언어를 사용한다.

맵리듀스 작업의 병렬 실행은 파티셔닝을 기반으로 한다. 작업의 입력으로 HDFS상의 디렉터리를 일반적으로 사용하고, 입력 디렉터리 내 파일 또는 파일 블록을 맵 태스크에서 처리할 독립 파티션으로 간주한다.

맵리듀스 스케줄러는 매퍼 입력 파일의 복제본이 있는 장비에 자원(CPU,RAM)의 여유가 충분하다면 해당 장비에서 작업을 수행하려 한다(데이터 가까이에서 연산하기). 이 원리를 적용하면 네트워크를 통해 입력 파일을 복사하는 부담과 네트워크 부하가 감소하고 지역성이 증가한다.

맵 태스크를 실행할 장비에 애플리케이션 코드가 없는 경우, 맵리듀스 프레임워크가 작업을 수행하기 위한 적절한 코드(자바 같은 경우 JAR)를 복사한다. 복사가 끝나면 매퍼 태스크가 시작된다. 매퍼의 출력은 key-value 쌍으로 구성된다.

키-값 쌍은 반드시 정렬돼야 하지만 대게 데이터셋(data set)이 매우 크기 때문에 단계를 나누어 정렬을 수행한다. 먼저 각 맵 태스크는 키의 해시값을 기반으로 출력을 리듀서로 파티셔닝한다. 그리고 각 파티션을 매퍼의 로컬 디스크에 정렬된 파일로 기록한다.

리듀서 측 연산도 파티셔닝되는데, 맵 태스크 수는 입력 파일의 블록 수로 결정되지만, 리듀스 태스크 수는 사용자가 설정한다. 즉 맵 태스크 수와 리듀스 태스크 수는 다를 수 있다.

매퍼가 입력 파일을 읽어서 정렬된 출력 파일 기록을 완료하면, 맵리듀스 스케줄러는 그 매퍼에서 출력 파일을 가져올 수 있다고 리듀서에게 알려준다. 리듀서는 각 매퍼와 연결해서 리듀서가 담당하는 파티션에 해당하는 정렬된 key-value 쌍 파일을 다운로드한다. 리듀서를 기준으로 파티셔닝하고 정렬한 뒤 매퍼로부터 데이터 파티션을 복사하는 과정을 셔플(suffle)이라고 한다.

리듀스 태스크는 매퍼로부터 파일을 가져와 정렬된 순서를 유지하면서 병합한다. 그렇기 때문에 다른 매퍼가 동일한 키로 레코드를 생성하면 병합된 이후 리듀서의 입력으로 들어갈 때는 서로 인접하게 된다.

리듀서는 키와 반복자(iterator)를 인자로 호출하는데 이 반복자로 동일한 키를 가진 레코드를 모두 흝을 수 있다. 임의의 로직을 사용해서 이 레코드들을 처리하고 여러 출력 레코드를 생성할 수 있다. 이 출력 레코드들은 분산 파일 시스템에 파일로 기록된다.

맵리듀스 워크플로

맵리듀스 작업 하나로 해결할 수 있는 문제의 범위는 제한적이다. 따라서 맵리듀스 작업 하나의 출력을 다른 맵리듀스의 입력으로 하는 방식으로 연결해 워크플로(workflow)를 구성하는 것이 일반적이다.

일괄 처리 작업의 출력은 작업이 성공적으로 끝났을 때만 유효하다. 그렇기 때문에 워크플로 상에서 해당 작업의 입력 디렉터리를 생성하는 선행 작업이 완전히 끝나야만 다음 작업을 시작할 수 있다. 이러한 작업 간 수행 의존성을 관리하기 위해 우지, 아즈카반 같은 다양한 스케줄러가 존재한다.

서로 다른 작업들이 서로의 출력을 입력으로 하는 작업이 있을 수 있는데, 이런 복잡한 데이터플로를 관리하기 위해 피그, 하이브 같은 다양한 고수준 도구들도 존재한다.

우지(Oozie)

기능

1) Scheduling

  • 특정 시간에 액션 수행
  • 주기적인 간격 이후에 액션 수행
  • 이벤트가 발생하면 액션 수행

2) Coordinating

  • 이전 액션이 성공적으로 끝나면 다음 액션 시작

3) Managing

  • 액션이 성공하거나 실패했을 때 이메일 발송
  • 액션 수행시간이나 액션의 단계를 저장

  1. 클라이언트는 우지 서버에 연결하여 job properties을 제출합니다.
  • job properties는 key-value 형태로 작업에 필요한 파라미터를 정의합니다.

  • workflow.xml(Action들과 그들을 연결하는 로직은 Workflow를 정의) 파일의 NameNode와 Yarn ResourceManager(혹은 JobTracker)에 대한 URI를 포함하고 있습니다.

  1. 우지 서버가 HDFS로 부터 workflow 파일을 읽습니다.

  2. 우지 서버에서 workflow를 파싱해서 액션을 수행합니다.

피그(Pig)

데이터 분석 프로그램을 표현하는 고급 언어와 이러한 프로그램을 평가하는 인프라로 구성된 대용량 데이터셋 분석 플랫폼. Pig의 가장 큰 특징은 상당한 병렬화가 가능한 구조로, 이를 통해 매우 큰 규모의 데이터셋을 처리할 수 있다는 것이다. Pig Latin이라는 텍스트 언어로 구성이 되어있다.

  • 프로그래밍의 용이성
    간단하게 데이터 분석 작업을 병렬로 실행할 수 있다. 여러 개의 상호 연관된 데이터 변환으로 구성된 복잡한 작업은 데이터 흐름 시퀀스로 명시적으로 인코딩되어 작성, 이해 및 유지 관리가 용이하다.

  • 최적화 기회
    작업이 인코딩되는 방식을 통해 시스템은 작업 실행을 자동으로 최적화할 수 있으며, 이를 통해 사용자는 효율성보다는 의미론에 집중할 수 있다.

  • 확장성
    사용자는 특수 목적의 처리를 수행하는 자체 함수를 만들 수 있음.

레퍼런스
https://12bme.tistory.com/154
https://kerpect.tistory.com/75

0개의 댓글