카테고리 없음

데이터 중심 애플리케이션 설계 (10장 일괄 처리)

보리시스템 2024. 7. 14.

[2부 분산 데이터]

10장: 일괄 처리
1. 유닉스 도구로 일괄 처리하기
1.1 단순 로그 분석
1.2 유닉스 철학

2. 맵리듀스와 분산 파일 시스템
2.1 맵리듀스 작업 실행하기
2.2 리듀스 사이드 조인과 그룹화
2.3 맵 사이드 조인 일괄 처리
2.4 워크플로의 출력
2.5 하둡과 분산 데이터베이스의 비교

3. 맵리듀스를 넘어
3.1 중간 상태 구체화
3.2 그래프와 반복 처리
3.3 고수준 API와 언어

 

 

[정리]

- awk, grep, sort 등 유닉스 도구의 설계 원리

=> 입력은 불변, 출력은 다른 프로그램의 입력으로 사용. 복잡한 문제도 한 가지 일을 잘하는 작은 도구를 엮어서 해결

- 유닉스 환경에서 프로그램과 다른 프로그램을 연결하는 단일 인터페이스? 파일과 파이프
=> 맵리듀스의 인터페이스는 분산 파일 시스템
=> 데이터플로 엔진은 파이프와 비슷한 자체 데이터 전송 매커니즘을 사용해 분산 파일 시스템에 중간상태를 구체화하는 것을 피함
=> 다만 작업의 초기 입력과 최종 출력은 여전히 HDFS를 사용

- 분산 일괄처리 프레임워크가 해결해야 할 중요한 문제 2가지
1) 파티시닝
=> 맵리듀스에서 매퍼는 입력 파일 블룩에 따라 파티서닝됨
=> 맵퍼의 출력은 재파티서닝해 정렬하고 리듀서 파티션으로 병합
=> 리듀서 파티션 개수는 설정할 수 있음
=> 이 과정의 목적은 관련된 모든 데이터를 같은 장소로 가져오는 것.
=> 맵리듀스 이후 데이터플로 엔진은 필요한 경우가 아니라면 정렬하지 않음
=> 그렇지 않다면 대체로 비슷한 방법으로 파티사닝함

2) 내결함성
=> 앱리듀스는 빈번히 디스크에 기록함
=> 디스크에 기록하면 개별 태스크가 실패하더라도 전체 직업을 재수행하지 않고 쉽게 복구 할 수 있음
=> 히지만 작업이 실패하지 않는 경우 수행시간이 느려지는 것은 감수해야 함
=> 데이티플로 엔진은 중간 상태를 최대한 구체화하지 않고 대신 메모리에 상태를 유지함
=> 이것은 특정 노드가 실패한디면 재계산 양이 늘어난다는 것을 의미
=> 결정적 연산자를 사용하면 재계산이 필요한 데이터의 양을 줄일 수 있음

- 맵리듀스에서 사용하는 조인 알고리즘
=> MPP 데이터베이스와 데이터 플로 엔진 내부에서도 사용
=> 파티셔닝 알고리즙의 동작 방식에 대해서도 설명해주는 에제임

1) 정렬 병합 조인
=> 조인할 각 입력은 조인 키를 추출하는 매퍼를 통과
=> 파티시닝, 정렬, 병합 과정을 마치면 같은 키를 가지는 모든 레코드는 하나의 리듀서에서 호출됨
=> 리듀서 함수에서 병합된 레코드를 출력할 수 있음

2) 브로드캐스트 해시 조인
=> 조인할 입력 두 개 중 하나가 상대적으로 작다면 피티시닝하지 않고 해시 테이블에 모두 적재할 수 있음
=> 큰 조인 입력의 각 파티션에서 매퍼를 시작할 때 각 매퍼에 작은 입력으로 만들어진 해시 테이블을 적재하고 큰 입력에서 한 번에 하나씩 레코드를 스캔하면서 각 레코드가 해시 테이블에 존재하는지 질의함

3) 피티션 해시 조인
=> 조인 입력 2개를 같은 방식으로 파티셔닝하면 해시 테이블 방식을 각 피티선별로 독립적으로 사용할 수 있음

- 분산 일괄 처리 엔진
=> 의도적으로 제한된 프로그래밍 모델을 제공
=> 매퍼와 리듀서 같은 콜백 함수는 상태정보가 없다고 가정함
=> 지정된 출력 외에 외부에서 보이는 부수효과가 없어야 함
=> 이 제한으로 프레임워크는 분산시스템에서 발생하는 어려운 문제들을 추상화 아래로 숨길 수 있음
=> 장비가 죽기나 네트위크 문제에 직면하더라도 태스크는 안전하게 재시도되고 실패한 태스크의 출력은 버림
=> 한 파티션에서 여러 태스크가 성공한다면 실제로는 그 중 하나의 출려만 보임

- 이 프레임워크 덕분에 일괄 처리 작업을 하는 코드는 내결합싱 메커니즘을 구현할 필요가 없음
=> 프레임워크는 작업의 최종 출력이 결합이 생기지 않을 때와 동일하게 보장함
=> 신뢰성의 시맨틱은 온라인 서비스에서 사용자 요청을 처리하고 그 부수 효과로 데이터베이스에 기록하는 것에 비해 훨씬 강력함

- 일괄 처리 작업의 차별화된 특징
=> 입력을 수정하지 않고 입력을 읽어 출력을 생산(출력은 입력으로부터 파생됨
=> 입력 데이터는 고정된 크기로 한정됨

 


 

10장 일관성과 합의

- 시스템의 유형 3가지
1) 서비스(온라인 시스템)

=> 클라이언트로부터 요청이 올 때까지 기다림
=> 요청이 들어오면 가능한 빨리 요청을 처리해 응답을 보냄
=> 응답시간은 서비스 성능 측정의 중요한 지표로 가용성이 매우 중요

2) 일괄 처리 시스템(오프라인 시스템)
=> 매우 큰 입력 데이터를 받이 데이터를 처리하는 작업을 수행하고 결과 데이터를 생산
=> 수 분~수 일이 걸리기 때문에 사용자가 작업이 끝날 때까지 대기하지 않음
=> 대부분 하루에 한 번 등 반복적인 일정으로 수행
=> 주요 성능 지표로는 처리량으로 입력 데이터 중 특정 크기만큼 처리할 때 걸리는 시간으로 나타냄

3) 스트림 처리 시스템(준실시간 시스템)
=> 온라인과 오프리인/일괄 처리 사이의 어딘가에 있어 준실시간 처리(near-real-time 또는 nearline processing)
=> 일괄 처리 시스템과 미찬가지로 요청에 대해 응답하지 않으며 입력 데이터를 소비하고 출력 데이터를 생산
=> 일괄 처리 시스템보다 지연시간이 낮음
* 일괄 처리 작업은 정해진 크기의 입력 데이터를 대상으로 작동하지만
* 스트림 처리는 입력 이벤트가 발생한 직후 바로 작동

- 일괄처리
=> 신뢰할 수 있고 확장 가능하며 유지보수하기 쉬운 애플리케이션 구축의 중요한 구성요소
=> 컴퓨터 연산에 있어 매우 오래된 형태임

- 맵리듀스(MapRoduce)
=> 일괄 처리 알고리즙으로 구글을 대규모로 확장 가능하게 만든 알고리즘으로 불리기도 함
=> 하둡, 카우치DB, 몽고DB 등 다양한 오픈소스 시스템에서 구현됨
=> 이전에 데이터웨어 하우스용으로 개발했던 병렬처리 시스템보다 상당히 저수준 프로그래밍 모델이지만 범용 하드웨어만을 사용해 처리한 데이터 규모면에서 상당히 진보했음
=> 현재 맵리듀스의 중요성은 떨어지고 있지만, 왜 일괄처리가 유용한지 이해할 수 있도록 하는 개념이므로 살펴볼 가치가 있음

 

1. 유닉스 도구로 일괄 처리하기

 
1.1 단순 로그 분석 / 1.2 유닉스 철학

-  1978년에 기술된 유닉스 철학
1) 각 프로그램이 한가지 일만 하도록 작성

=> 새 작업을 하려면 기존 프로그램을 고쳐 새로운 기능을 추가해 프로그램을 복잡하게 만들기 보다는 새로운 프로그램을 직성

2) 모든 프로그램의 출력은 아직 알려지지 않은 다른 프로그램의 입력으로 쓰일 수 있다고 생각
=> 불필요한 정보로 출력이 너지분해서는 안 됨
=> 입력 형식으로 엄격하게 열을 맞춘다거나 이진 형태를 사용하지 마라
=> 대화형 입력을 고집하지 마리

3) 소프트웨어를 빠르게 써볼 수 있게 설계하고 구축. 운영체제도 마찬가지임
=> 수 주 안에 끝나는 것이 이상적
=> 거슬리는 부분은 과감히 버리고 새로 구축

4) 프로그래밍 작업을 줄이려면 미숙한 도움보단 도구를 사용
=> 도구를 빌드하기 위해 한참 둘러가야 하고 게다가 사용 후 바로 버린다고 할지라도 도구를 써라

- 오늘날의 애자일 및 DevOps 운동과 매우 흡사한 유닉스 철학
=> 자동화, 빠른 프로토타이핑, 증분 반복(여러 개의 작은 단계로 나누어 점진적으로 발전시키는 방법론), 실험 친화, 큰 프로젝트를 청크로 나누어 처리하기 등

 

  • 동일 인터페이스
- 특정 프로그램이 다른 어떤 프로그램과도 연결 가능하려면 프로그램 모두가 같은 입출력 인터페이스를 사용해야 함
=> 유닉스에서의 인터페이스? 파일(좀 더 정확히는 파일 디스크립터)
=> 관례상 많은 유닉스 프로그램은 연속된 바이트를 아스키텍스트로 취급
=> 동일한 데이터 모델인 데이터베이스 간에도 한쪽에서 다른쪽으로 데이터를 옮기는 게 쉽지 않음
=> 데이터가 발칸화 되는 이유는 유닉스 도구와 같은 통합이 부족했기 때문

 

  • 로직과 연결의 분리
- 유닉스 도구의 다른 특징으로 표준입력(stdin)과 표준출력(stdout)을 사용한다는 점
=> 프로그램이 특정 파일의 경로가 어디에 있는지 신경쓰지 않고 stdin과 stdout만으로 처리하고 싶다면 유니스 접근법이 가장 좋음
=> 프로그램은 입력이 어디서부티 들어오는지 출력이 어디로 나가는지 신경쓰거나 알 필요가 없음
=> 이런 형태를 느슨한 결합, 지연 바인딩, 제어반전이라고 함

- 그러나 stdin과 stdout을 사용할 때 제약사항이 있음
=> 프로그램이 여러 개의 입력을 받거나 여러 개의 출력이 필요할 때는 불가능하지는 않지만 까다로움
=> 프로그램의 출력을 파이프를 이용해 네트워크와 연결하지는 못함
=> 프로그램이 파일을 직접 열어 읽고 쓰거나 서브프로세스로 다른 프로그램을 구동하거나 네트워크 연결을 한다면 프로그램의 I/O는 그 프로그램 자체와 서로 묶이게 됨

 

  • 투명성과 실험
- 유닉스 도구가 성공적인 이유 중 하나는 진행사항을 파악하기가 상당히 쉽기 때문임
=> 유닉스 명령에 들어가는 입력 파일은 일반적으로 불변으로 처리됨. 다양한 명령행 옵선을 사용해가며 원하는만큼 명령을 수행하더라도 입력 파일에는 손상을 주지 않음
=> 어느 시점이든 파이프라인을 중단하고 출력을 파이프를 통해 less로 보내 원하는 형태의 출력이 나오는지 확인할 수 있음. 디버깅할때 매우 유용
=> 특정 파이프라인 단계의 출력을 파일에 쓰고 그 파일을 다음 단계의 입력으로 사용할 수 있음. 전체 파이프라인을 다시 시작하지 않고 다음 단계부터 재시작할 수 있음

- 유닉스 도구를 사용하는 데 가장 큰. 제약은 단일 장비에서만 실행된다는 짐
=> 그렇기 때문에 하둡 같은 도구가 필요

 



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

- 맵리듀스
* 같은 분산 파일 시스템 위에서 대용량 데이터셋을 처리하는 코드를 작성하는 프로그래밍 프레임위크
=> 유닉스 도구와 비슷한 면이 있지만 수천대의 장비로 분산해서 실행이 가능하다는 점에서 차이가 있음 
=> 단일 맵리듀스 작업은 하나 이상의 입력을 받아 하나 이상의 출력을 만들어 낸다는 점에서 단일 유닉스 프로세스와 유사
=> 유닉스 도구와 마찬가지로 맵리듀스 작업은 입력을 수정하지 않기 때문에 출력을 생산하는 것 외에 다른 부수 효과는 없음
=> 유닉스 도구는 stdin과 stdout을 입력과 출력으로 사용하는데 맵리듀스 작업은 분산 파일 시스템 상의 파일을 입력과 출력으로 사용

- HDFS
=> 하둡 맵리듀스 구현에서 HDFS(Hadoop Distributed File System)라고 함
=> GFS(Google File Syslem)를 재구현한 오픈소스
=> HDFS 외에도 GlusterFS, QFS(Quantcast File) 등 다양한 분산 파일 시스템이 있음

- HDFS 특징
1) 비공유원칙을 기반으로 함
=> NAS(Network Attached Storage)와 SAN(Storage Area Network) 아기텍처에서 사용하는 공유 디스크 방식과는 반대

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

=> 장비가 죽거나 디스크가 실패하는 경우에 대비하기 위해 파일 블록은 여러 장비에 복제됨
=> 단순히 여러 장비에 동일한 데이터를 복사하는 방식이 있음
=> 리드 솔로몬 코드(Reed-Solomon code) 같은 삭제 코딩(erasure coding) 방식을 사용해 데이터 전체를 복제하는 것보다 적은 저장소 부담으로 손실된 데이터를 복구하는 방식도 있음

3) 확장성이 뛰어남
=> HDFS를 이용한 데이터 저장과 접근비용은 범용 하드웨이와 오픈소스 소프트웨어를 사용하기 때문에 동급 용량의 전용 저장소 장치를 사용하는 비용보다 훨씬 저렴

 
2.1 맵리듀스 작업 실행하기

- 맵리듀스의 데이터 처리 패턴
1) 입력 파일을 읽음. 레코드로 쪼갬

=> 입력 형식 파서를 씀

2) 각 입력 레코드마다 매퍼 함수를 호출해 키와 값을 추출
=> 사용자가 데이터 처리 코드를 직접 작성한

3) 카를 기준으로 키-값 쌍을 모두 정렬
=> 직접 작성할 필요가 없는데 매퍼의 출력은 리듀스로 들어가기 전에 이미 정렬됐기 때문임

4) 정렬된 키-값 씽 전체를 대상으로 리듀스 함수를 호출. 같은키가 여러번 등장했다면 정렬 과정에서 해딩 키-값 쌍은 서로 인접함
* 그래서 같은 키를 가지는 값들을 따로 메모리 상에 상태를 따로 유지하지 않고도 쉽게 결합할 수 있음
=> 사용자가 데이터 처리 코드를 직접 작성한 리듀스

- 맵리듀스 작업을 생성하려면 매퍼, 리듀서라는 2가지 콜백 함수를 구현해야 함

1) 매퍼
=> 매퍼는 모든 입력 레코드마다 한번씩만 호출됨
=> 매퍼는 입력 레코드로부터 키와 값을 추출하는 작업
=> 각 입력으로부터 생성하는 키-값 쌍은 빈 쌍을 포함해 원하는 만큼 생성 가능
=> 매퍼는 입력 레코드로부터 다음 레코드까지 상태를 유지하지 않기 때문에 각 레코드를 독립적으로 처리

2) 리듀서
=> 맵리듀스 프레임워크는 매퍼가 생산한 키-값 쌍을 받아 같은 키를 가진 레코드를 모으고 해당 값의 집합을 반복해 리듀서 함수 를 호출
=> 리듀서는 출력 레코드(예: 동일한 URL이 출현한 횟수)를 생산

 

  • 맵리듀스의 분산실행
- 맵리듀스가 병렬로 수행하는 코드를 직집 작성하지 않고도 여러 장비에서 동시에 처리 가능
=> 매퍼와 리듀서는 한번에 하나의 레코드만 처리하고 입력이 어디서 오는지 출력이 어디로 가는지 신경쓰지 않음
=> 분산 연산에서 매퍼와 리듀서로 표준 유닉스 도구를 사용하는 것도 가능

- 하둡 맵리듀스 작업에서 데이터플로
=> 맵리듀스 작업의 병렬 실행은 파티셔닝을 기반으로 함
=> 작업 입력으로 HDFS상의 디렉터리를 사용하는 것이 일반적
=> RAM과 CPU에 여유가 충분하다면 맵리듀스 스케줄러가 입력 파일이 있는 장비에서 작업을 수행하려 함
* 이 원리를 '데이터 가까이에서 연산하기'라고 함
* 이 원리를 적용하면 네트워크를 통해 입력파일을 복사하는 부담과 네트위크 부하가 감소하고 지역성이 증가함
=> 대부분의 경우 맵태스크에서 실행될 애플리케이션 코드는 작업이 할당된 장비에 아직 존재하지 않기 때문에 멥리듀스 프레임워크가 작업을 수행하기에 적절한 장비로 코드를 복사
=> 복사가 끝나면 장비에서 매퍼태스크가 시작
=> 입력파일을 읽기 시작하면 입력파일에서 한번에 레코드 하나씩 읽어 매퍼 콜백 합수로 전달
=> 매퍼의 출력은 키-값 쌍으로 구성됨
=> 리듀서 측 연산도 파티셔닝됨
* 맵 태스크 수는 입력 파일의 블록 수로 결정되지만 리듀스 태스크 수는 사용자가 설정
=> 맵리듀스 프레임워크는 같은 키를 가진 모든 키-값 쌍을 같은 리듀서(키의 해시값을 사용해 정함)에서 처리하는 것을 보장
=> 매퍼가 입력 파일을 읽어서 정렬된 출력파일을 기록 완료하면 맵리듀스 스케줄러는 그 매퍼에서 출력파일을 가져올 수 있다고 리듀서에게 알려줌
=> 리듀서는 각 매퍼와 연결해 리듀서가 담당하는 파티션에 해당하는 정렬된 키-값 쌍 파일을 다운로드
=> 리듀서를 기준으로 파티서닝하고 정렬한 뒤 매퍼로부터 데이터 파티션을 복사(셔플)

 

  • 맵리듀스 워크플로
- 맵리듀스 작업을 연결해 워크플로(workflow)로 구성하는 방식은 일반적임
=> 디렉터리 이름을 통해 압묵적으로 연결
=> 작업 실패 시 남은 부분 출력은 제거

- 하둡 도구
1) 맵리듀스 작업간 수행 의존성을 위한 스케줄러
=> Oozie, Azkaban, Luigi, Airflow, Pinball 
2) 다중 맵리듀스 연결을 위한 하둡용 고수준 도구
=> Pig, Hive, Cascading, Crunch, FlumeJava

 



2.2 리듀스 사이드 조인과 그룹화

- 맵리듀스에는 색인 개념이 없음
=> 일괄 처리에서 처리량 높이기 위해서는 가능한 한 장비 내에서 연산을 수행해야 함
=> 더 좋은 방법으로는 데이터베이스 사본을 가져와 분산 파일 시스템에 넣는 방법이 있음
=> 보조 정렬? 리듀서가 항상 사용자 데이터베이스를 먼저 보고 활동 이벤트를 시간순으로 보게 하는 식으로 맵리듀스에서 작업 레코드을 재배열
=> 정렬 병합 조인? 매퍼 출력이 키로 정렬된 후에 리듀서가 조인의 양측의 정렬된 레코드 목록을 병합

- 같은 곳으로 연관된 데이터 가져오기
=> 매퍼와 정렬 프로세스는 특정 사용자 ID로 조인 연산을 할 때 필요한 모든 데이터를 한곳으로 모음

- 그룹화
=> 조인 외에 같은 키를 가진 모든 레코드를 그룹으로 만드는 방법이 있음
=> 맵리듀스로 그룹화 연산을 구현하는 가장 간단한 방법은 매퍼가 키-값 쌍을 생성할 때 그룹화할 대상을 키로 하는 것

- 쏠림(핫스팟) 다루기
=> 키 하나에 너무 많은 데이터가 연관된다면 같은 키를 가지는 모든 레코드를 같은 장소로 모으는 패턴은 제대로 작동하지 않음
=> 불균형한 활성화 데이터베이스 레코드를 린치핀 객체 또는 핫 키라고 함
=> 핫스팟 알고리즘
1) Pig의 쏠린 조인(skewed join)
* 어떤 키가 핫 키인지 결정하기 위해 샘플링 작업 수행
2) Crunch의 공유 조인(shared join)
3) Hive의 맵 사이드 조인(map-side-join)
* 핫 키는 테이블 메타 데이터에 명시적으로 지정하고 핫 키와 관련된 레코드를 나머지 키와는 별도 파일에 저장
* 해당 테이블에서 조인할 때 핫 키를 가지는 레코드는 맵사이드조인(map -sidejoin)을 사용해 치리

 



2.3 맵 사이드 조인

- 리듀스 사이드 조인
=> 메퍼는 각 입력 레코드에서 키와 값을 추출해 추출한 키-값 쌍을 리듀서 파티션으로 할당하고 키별로 정렬하는(입력 데이터를 준비하는) 역할을 함
=> 리듀스 사이드 접근법의 장점은 입력 데이터에 대한 특정 가정이 필요없다는 점
=> 그러나 정렬 후 리듀서로 복사한 뒤 리듀서 입력을 병합하는 모든 과정에 드는 비용이 상당하다는 단점이 있음

- 맵사이드 조인
=> 입력 데이터에 대해 특정 가정이 가능하다면 이를 사용해 조인을 더 빠르게 수행할 수 있음

- 브로드캐스트 해시 조인
=> 맵사이드 조인은  작은 테이터셋과 매우 큰 데이터셋을 조인하는 경우에 가장 간단하게 적용해볼 수 있음
=> 매퍼 태스크를 여러개 사용할 수도 있음. 각 맵 태스크에 조인할 큰 입력 파일 블록 중 하나를 할당하면 됨
=> 모든 매퍼는 작은 입력 전체를 메모리에 적재

- 파티션 해시 조인
=> 맴사이드 조인의 입력을 파티셔닝한다면 해시조인접근법을 각. 파티션에 독립적으로 적용할 수 있음
=> 조인할 두 입력 모두를 같은 키와 같은 해시함수를 기반으로 같은 수로 파티셔닝해야 작동

- 맴사이드 병합조인
=> 입력 데이터셋이 같은 방식으로 파티셔닝 됐을 뿐 아니라 같은 키를 기준으로 정렬됐다면 변형된 맵사이드 조인을 적용할 수 있음
=> 선행 리듀스 작업이 미리 입력 데이터셋을 파티셔닝하고 정렬


2.4 일괄처리 워크플로의 출력

- 일괄 처리는 입력 데이터셋 대부분을 스캔하는 것이 일반적이라 분석에 더 가까움
=> 그러나 맵리듀스 작업의 워크플로는 다른 형태의 구조임

- 검색 색인 구축
* 구글이 검색 색인 구축 위해 맵리듀스를 사용했지만 현재는 더이상 사용하지는 않음
=> 일괄 처리로 색인 구축하는 것이 효율적임
=> 색인 갱신 방법으로는 전체 색인 워크플로 재수행하여 색인 대치하거나 증분 색인 구축하는 방법이 있음

- 일괄처리의 출력으로 키-값을 저장
=> 배치 프로세스의 출력을 웹 애플리케이션이 질의하는 데이터베이스로 보내는 방법?
* 일괄 처리 작업 내부에 완전히 새로운 데이터베이스를 구축해 분산 파일 시스템의 작업 출력 디렉터리에 지장

- 일괄 처리 출력에 관한 철학
=> 인적 내결함성 (human fault tolerance)
* 버그가 있다면 이전 버전으로 돌리고 작업 재수행해 간단하게 출력을 고칠 수 있음
=> 비가역성 최소화 (minimizing irreversibility)
* 쉽게 되돌릴 수 있는 속성의 결과로 실수를 하면 손상을 되돌릴 수 없는 환경에서보다 기능 개발을 빠르게 진행할 수 있음
=> 실패 출력 폐기
=> 동일 입력 파일 집합 사용
=> 연결작업과 로직 분리

 



2.5 하둡과 분산 데이터베이스의 비교

- 맵리듀스와 MPP 데이터베이스의 차이
* 맵리듀스의 개념은 이미 수십년전에 MPP 데이터베이스에서 구현된 것임
=> MPP 데이터베이스는 장비 클러스터에서 분석 SQL질의를 병렬로 수행하는 것에 초점을 둠
=> 맵리듀스와 분산 파일 시스템의 조합은 아무 프로그램이나 실행할 수 있는 운영체제와 비슷한 속성을 제공

- 저장소의 다양성
=> MPP 데이터베이스를 사용하면 대개 데이터베이스에 특화된 저장 형태로 데이터를 가져오기 전에 데이터와 질의 형태를 신중하게 선행 모델링해야 함
=> 하둡은 데이터가 어떤 형태라도 상관없이 HDFS로 덤프할 수 있는 가능성을 열어 놓음 (데이터를 어떻게 처리할지는 덤프 이후에야 생각)
* 하들은 ETL 프로세스를 구현하는 데 종종 사용되기도 함

- 처리모델의 다양성
=> MPP 데이터베이스는 일체식(monglihic) 구조로서 디스크 저장소 레이아웃과 질의 계획, 스케줄링과 실행을 다루는 소프트웨어 조각들이 긴밀하게 통합됨
=> 맵리듀스를 이용하면 엔지니어는 자신이 작싱한 코드블 대용량 데이터셋상에서 쉽게 실행할 수 있음

- 빈번하게 발생하는 결함을 줄이는 설계
=> 일괄처리는 온라인 시스템에 비해 결합에 덜 민감. 일괄처리 작입이 실패하더라도 즉시 사용자에게 영향을 주지 않으면서 언제든지 다시 실행할 수 있기 때문임
=> MPP 데이터베이스는 질의 실행 중 한 장비만 죽어도 전체 질의가 중단됨
=> 맵리듀스는 맵 또는 리듀스 태스크의 실패를 견딜 수 있음
=> 따라서 많은 데이터를 처리하고 오랜 시간 수행하는 작업이라면 태스크 실패의 가능성이 높기 때문에 맵리듀스 접근법은 대용량 작업에 더 적합함

 



3. 맵리듀스를 넘어

- 맵리듀스는 분산시스템에서 가능한 여리 프로그래밍 모델 중 단지 하나일 뿐임
=> 분산 파일 시스템 상에서 상당히 단순 명료하게 추상화된 모델이므로 유용한 도구임
* 단순함은 사용하기 쉽다는 것이 아닌 무엇을 하고 있는지 이해하기 쉽다는 의미

=> 하지만 맵리듀스 원시 API를 사용해서 복잡한 연산을 구현하는 일은 실제로 매우 어렵고 복잡함
* 이를테면 조인 알고리즘을 하나 작성한다고 해도 처음부터 모두 구현해야 함

 


 
3.1 중간 상태 구체화

- 모든 맵리듀스 작업은 다른 작업과 모두 독립적
=> 중간상태를 완전히 구체화하는 맵리듀스 접근법은 유닉스 파이프에 비해 여러 단점이 있음
1) 입력을 생성하는 모든 선행 작업이 완료됐을 때만 시작 가능
2) 매퍼 중복
3) 중간 상태인 임시 데이터도 복제되는 과잉 조치

- 데이터플로 엔진
=> 이러한 문제 해결을 위해 분산 일괄 처리 연산을 수행하는 엔진이 개발됨
* 스파크, 테즈, 플링크
=> 이 엔진들의 공통점은 전체 위크플로를 독립된 하위작업으로 나누지 않고 작업 하나로서 다룬다는 점임
=> 맵리듀스와 달리 맵과 리듀스를 번갈아 수행하는 식의 규칙을 엄격하게 지킬 필요가 없음
* 연산자라는 함수들을 조합을 통해 여러 선택지를 제공

- 내결함성
=> 대신 이 엔진들은 내길함성 확보를 위해 다른 접근법을 사용함
=> 장비가 죽어서 장비에 있던 중간상태까지 잃게 되면 아직 유효한 데이터로부터 재계산하여 복구
* 데이터을 재연산할 때 중요한 점은 해당 언산이 결정적인지 아닌지 파악하는 것
=> 더 효과적인 방법으로 중간데이터가 원천데이터보다 훨씬 작거나 연산이 CPU 중심적이라면 재연산보다 중간데이터를 파일로 구체화하는 방식이 있음
=> 맵리듀스는 데이터를 일회성으로만 처리하기 때문에 대개 반복적 스타일로 알고리즘을 구현함

 



3.2 그래프와 반복 처리

- 프리글 처리 모델
=> 일괄 처리 그래프를 최적화하는 방법으로 '벌크 동기식 병렬'이 널리 사용됨
=> 프리글에도 이같은 개념이 있는데 '한 정점은 다른 정점으로 메시지를 보낼 수 있다'는 메시지는 그래프에서 간선을 따라 보내짐
=> 메시지 통신은 고정된 횟수 안에 처리함. 각 반복에서 이 프레임워크는 이전 반복에서 보내진 모든 메시지를 전달함. 액티모델은 그런 타이밍 보장을 하지 않음

- 내결함성
=> 정점이 서로 직접 질의하는 방식이 아니라 메시지 전달로 통신한다는 점은 프리글 작업 성능 향상에 도움을 줌
=> 내결합성은 반복이 끝나는 시점에 모든 정점의 상태를 주기적으로 체크포인트로 저장함으로씨 보장됨 (전체 상태를 지속싱 있는 저장소에 기록)

- 병렬 실행
=> 병렬실행 정점은 어떤 물리장비에서 실행되는지 알 필요가 없기 때문에 메시지를 다른 정점으로 보낼 때 단순히 정점 ID를 사용해 메시지를 전달
=> 그래프 알고리즘은 장비 간 통신 오버헤드가 많이 발생함. 원본 그래프 보다 중간상태(노드 간 전송된 메시지)가 더 클 수도 있음. 네트워크 상에서 메시지를 보내는 오버헤드 때문에 분산 그래프 알고리즘이 심각하게 느려질 수도 있음

 



3.3 고수준 API와 언어

- 선언형 질의 언어로 전환
=> 코드를 임의로 실행할 수 있다는 점은 MPP 데이터베이스와 리듀스를 계승하는 일괄 처리 시스템을 오랜 세월동안 구별해준 특성임
=> 그러나 데이터플로 엔진도 조인 외에 좀 더 선언적인 기능을 통합하면 이점이 있음
=> 고수준 API에 선언적 측면을 포함하면서 실행 중에 이용할 수 있는 질의 최적화기를 가진다면 일괄처리 프레임워크는 MPP 데이터베이스와 한층 비슷해짐
=> 동시에 일괄처리 프레임워크는 임의의 코드를 실행하고 임의 형식의 데이터를 읽을 수 있는 확장성을 지녀 일괄처리 프레임워크의 장점인 유연성은 그대로 유지함

 


 

<더보기>

 

- Hadoop vs. Spark vs. Kafka - How to Structure Modern Big Data Architecture?

https://nexocode.com/blog/posts/hadoop-spark-kafka-modern-big-data-architecture/

 

Hadoop vs. Spark vs. Kafka - How to Structure Modern Big Data Architecture? - nexocode

A comparison of popular tools in the big data ecosystem and how they can be used together to build a modern architecture that is scalable, fault-tolerant, and cost-effective.

nexocode.com

 

 

- Kakao Hadoop Plaform (KHP): 카카오 자체 개발 하둡 플랫폼인 KHP(Kakao Hadoop Platform)

https://tech.kakao.com/posts/556

 

카카오 자체 개발 하둡 플랫폼, Kakao Hadoop Platform(KHP) - tech.kakao.com

Kakao Hadoop Platform (KHP) 카카오에서 자체 개발한 하둡 솔...

tech.kakao.com

 

https://www.youtube.com/watch?v=4-W-PSMshgA

 

 

- NHN 하둡 개발환경 및 배치의 MySQL->하둡 전환기

https://www.youtube.com/watch?v=-5Kul72jqLQ