Skip to main content

10. 일괄 처리

  • 앞 장에서는 요청(request), 응답(response), 질의(query), 결과(result) 에 대해 다뤘습니다.
  • 온라인 시스템에서는 사용자의 응답 시간 단축에 많은 노력을 합니다.
  • 시스템을 세가지 유형으로 분리하면 다음과 같습니다.
    • 서비스(온라인 시스템) , 서비스는 클라이언트로부터 요청이나 지시가 올때까지 기다립니다.
    • 일괄 처리 시스템(오프라인 시스템) , 매우 큰 입력의 데이터를 받아 데이터를 처리하는 작업을 수행하고 결과 데이터를 생산합니다.
    • 스트림 처리 시스템(준실시간 시스템) , 온라인과 오프라인 사이의 어딘가에 위치하기에 준실시간 처리라고 부릅니다. 일처리 작업은 정해진 크기의 입력 데이터를 대상으로 작동하지만 스트림 처리는 입력 이벤트가 발생한 직후 바로 작동합니다.
  • 일괄 처리는 신뢰할 수 있고 확장 가능하며 유지보수하기 쉬운 애플리케이션을 구축하는 데 중요한 구성요소 입니다.

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

단순 로그 분석#

다양한 도구를 통해서 트래픽에 대한 보고서를 생성할 수 있습니다.

cat /var/log/nginx/access.log |
awk '{print $7} |
sort |
uniq -c |
sort -r -n |
head -n 5

로그를 읽고, 공백으로 분리된 줄의 7번째 필드만 출력하고, 요청 URL을 정렬하고, 중복을 제거하고,...

Tip. 개발하면서 로그 분석한거 이야기 주기.

  • 이러한 방식은 상당히 강력합니다.

연쇄 명령 대 맞춤형 프로그램#

counts = Hash.new(0)
File.open('/var/log/nginx/access.log') do |file|
file.each do |line|
url = line.split[6]
counts[url] += 1
end
end
top5 = counts.map(|url, count| [count, url] }.sort.reverse[0...5]
top.each{|count,url|puts "${count} ${url}"}
  • 표면적인 문법의 차이를 빼고 두가지 방법은 실행 흐름이 크게 다릅니다.

정렬 대 인메모리 집계#

  • 루비 스크립트는 URL 해시 테이블을 메모리에 유지합니다.
  • 유닉스 파이프라인 예제는 이러한 해시 테이블이 없습니다.

허용 메모리보다 작업 세트가 크다면 정렬 접근법을 사용하는 것이 중요합니다.

유닉스 철학#

유닉스 철학은 다음과 같습니다.

  • 각 프로그램이 한 가지 일만 하도록 작성합니다.
  • 모든 프로그램의 출력은 아직 알려지지 않은 다른 프로그램의 입력으로 쓰일 수 있다고 생각하라.
  • 소프트웨어를 빠르게 써볼 수 있게 설계하고 구축하라.
  • 프로그래밍 작업을 줄이려면 미숙한 도움보단 도구를 사용하라.

bash나 shell을 통해 데이터 처리 작업을 쉽게 구성할 수 있습니다.

동일 인터페이스#

  • 어떤 프로그램의 출력을 다른 프로그램의 입력으로 쓰고자 한다면 이들 프로그램은 같은 데이터 형식을 사용해야 합니다.
  • 즉, 특정 프로그램이 다른 어떤 프로그램과도 연결 가능하려면 프로그램 모두가 같은 입출력 인터페이스를 사용해야 한다는 의미입니다.
  • 동일한 데이터 모델인 데이터베이스 간에도 한쪽에서 다른 쪽으로 데이터를 옮기는 게 쉽지 않습니다. 이처럼 데이터가 발칸화되는 이유는 유닉스 도구와 같은 통합이 부족했기 때문입니다.

로직과 연결의 분리#

  • 유닉스 도구의 다른 특징 중 하나는 표준 입력(stidn)과 표준 출력(stdout)을 사용한다는 점입니다.
  • 이러한 경우와 같이 입력이 어디서부터 들어오는지, 출력이 어디로 나가는지 신경을 쓰거나 알 필요가 없습니다.
    • 이러한 형태를 느슨한 결합(loose coupling) , 지연 바인딩(late binding), 또는 제어 반전(inversion of control) 이라고 합니다.

투명성과 실험#

  • 유닉스 도구가 성공적인 이유 중 하나는 진행 사항을 파악하기가 상당히 쉽습니다.
    • 유닉스 명령에 들어가는 입력 파일은 일반적으로 불변으로 처리됩니다.
    • 어느 시점이든 파이프라인을 중단하고 출력을 파이프를 통해 less로 보내 원하는 형태의 출력이 나오는지 확인할 수 있습니다.
    • 특정 파이프라인 단계의 출력을 파일에 쓰고 그 파일의 다음 단계의 입력으로 사용할 수 있습니다.

유닉스 도구는 일부 불친절하지만 단순하고 유용합니다. 이러한 가장 큰 제약은 단일 장비에서만 실행되며 이러한 이유로 하둡 같은 도구가 필요합니다.


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

  • 맵리듀스는 유닉스 도구와 비슷한 면이 있지만 수천 대의 장비로 분산해서 실행이 가능하다는 점에서 차이가 있습니다.
  • 유닉스 도구와 마찬가지로 맵리듀스 작업은 입력을 수정하지 않기 때문에 출력을 생산하는 것 외에 다른 부수 효과는 없습니다.
  • 유닉스 도구는 stdin과 stdout을 사용하는데, 맵리듀스 작업은 분산 파일 시스템상의 파일을 입력과 출력으로 사용합니다. 이를 HDFS(Hadoop Distributed File System) 이라고 합니다.
  • HDFS는 비공유 원칙을 기반으로 하며, NAS(Network Attached Storage)SAN(Storage Area Network) 아키텍처에서 사용하는 공유 디스크 방식과는 반대입니다.
  • HDFS는 각 장비에서 실행되는 데몬 프로세스로 구성됩니다.
    • 데몬 프로세스는 다른 노드가 해당 장비에 저장된 파일에 접근 가능하게끔 네트워크 서비스를 제공합니다.
    • 네임노드(NameNode) 라고 부르는 중앙 서버는 특정 파일 블록이 어떤 장비에 저장됐는지 추적합니다.
    • 즉 , HDFS는 개념적으로는 매우 큰 하나의 파일 시스템이고 데몬이 실행중인 모든 장비의 디스크를 활용할 수 있습니다.
  • 장비가 죽거나 디스크가 실패하는 경우에 대비하기 위해 파일 블록은 여러 장비에 복제됩니다.
  • HDFS는 확장성이 뛰어납니다.

맵리듀스 작업 실행하기#

  • 맵리듀스는 HDFS와 같은 분산 파일 시스템 위에서 대용량 데이터셋을 처리하는 코드를 작성하는 프로그래밍 프레임워크입니다.
  • 맵리듀스 작업 하나는 4가지 단계로 구성됩니다.
    • 1단계 : 파일을 나누어 레코드를 만드는 데 입력 형식 파서를 씁니다.
    • 2단계 : 맵(Map)
    • 3단계 : 정렬 단계
    • 4단계 : 리듀스
  • 맵리듀스 작업을 생성하려면 다음과 같이 동작하는 매퍼와 리듀서라는 콜백 함수를 구현해야 합니다.
    • 매퍼(Mapper) : 매퍼는 모든 입력 레코드마다 한 번씩만 호출됩니다.
    • 리듀서(Reducer) : 맵리듀스 프레임워크는 매퍼가 생성한 키- 값 쌍을 받아 같은 키를 가진 레코드를 모으고 해당 값의 집합을 반복해 리듀서 함수를 호출합니다.
  • 매퍼는 정렬에 적합한 형태로 데이터를 준비하는 역할을 하고, 리듀서는 정렬된 데이터를 가공하는 역할을 합니다.

맵리듀스의 분산 실행#

  • 유닉스 명령어 파이프라인과 가장 큰 차이점은 맵리듀스가 병렬로 수행하는 코드를 직접 작성하지 않고도 여러 장비에서 동시에 처리가 가능합니다.
    • 매퍼와 리듀서는 한 번에 하나의 레코드만 처리하고 입력이 어디서, 출력이 어디로 가는지 신경쓰지 않습니다.
  • 분산 연산에서 매퍼와 리듀서로 표준 유닉스 도구를 사용하는 것도 가능합니다.
  • 하둡 맵리듀스 작업에서 데이터플로를 보여줍니다. 맵리듀스 작업의 병렬 실행은 파티셔닝을 기반으로 합니다.
  • RAM과 CPU에 여유가 있다면 맵리듀스 스케줄러가 입력 파일이 있는 장비에서 작업을 수행하는 것이 좋은 데 이 원리를 데이터 가까이에서 연산하기라고 합니다.
  • 대표적인 예시로, 자바 프로그램을 예로 들면 JAR 파일을 복사한 후 각 장비에서 매퍼 태스크가 시작됩니다. 입력 파일을 읽기 시작하면 입력 파일에서 한 번에 레코드 하나씩 읽어 매퍼 콜백 함수로 전달합니다.
  • 리듀서 측 연산도 파티셔닝됩니다. (태스크 수는 사용자가 설정합니다.)
  • 키-값 쌍은 반드시 정렬돼야 하지만 대개 데이터셋이 매우 크기 때문에 단게를 나눠서 정렬을 수행합니다.
  • 매퍼가 입력 파일을 읽어서 정렬된 출력 파일을 기록하기를 완료하면 맴 리듀스 스케줄러는 그 매퍼에서 출력 파일을 가져올 수 있다고 리듀서에게 알려줍니다.
    • 리듀서를 기준으로 파티셔닝하고 정렬한 뒤 매퍼에게 데이터 파티션을 복사하는 과정을 셔플(shuffle) 라고 합니다.
  • 리듀서 태스크는 매퍼로부터 파일을 가져와 정렬된 순서를 유지하면서 병합합니다. (그래서 리듀서의 입력으로 들어갈 때는 서로 인전해서 들어가게 됩니다.)
  • 리듀서는 키와 반복자(iterator)를 인자로 호출하는 데 이 반복자로 전달된 키와 동일한 키를 가진 레코드를 모두 훑을 수 있습니다.

맵리듀스 워크플로#

  • 맵리듀스 작업 하나로 해결할 수 있는 문제의 범위는 제한적입니다.
  • 즉, 맵리듀스 작업을 연결해 워크폴로(workflow) 로 구성하는 방식이 꽤 일반적입니다.
  • 일괄 처리 작업의 출력은 작업이 성공적으로 끝났을 때만 유효합니다. (맵리듀스는 작업이 실패하고 남은 부분 출력은 제거합니다.)
  • 이런 스케줄러에는 많은 일괄 처리 작업의 집합을 유지보수할 때 유용한 관리 기능이 있습니다.

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

  • 여러 데이터넷에서 한 레코드가 다른 레코드와 연관이 있는 것은 일반적입니다.
    • 관계형 모델에서는 외래키(foreign key), 문서 모델에서는 문서 참조(document reference), 그래프 모델에서는 간선(edge) 라고 합니다.
  • 연관된 레코드 양쪽 모두에 접근해야 하는 코드가 있다면 조인은 필수적입니다.
  • 데이터베이스에서 적은 수의 레코드만 관련된 질의를 실행한다면 데이터베이스는 일반적으로 색인(index)을 사용합니다.
    • 그러나, 맵리듀스에서는 색인 개념이 없습니다.
  • 맵리듀스는 파일을 전체 읽으며 (데이터베이스에는 이 연산을 전체 테이블 스캔, full table scan), 이는 비용이 비싸보이지만 병렬처리가 가능하기 대문에 합리적입니다.
  • 일괄 처리 맥락에서의 조인은 데이터셋 내 모든 연관 관계를 다룬다는 뜻입니다.

사용자 활동 이벤트 분석 예제#

  • 일괄 처리에서는 이벤트 로그(활동 이벤트(activity event) 또는 클릭스트림 데이터(clickstream data))고 오른쪽은 사용자 데이터베이스입니다.
  • 그러나 이러한 처리에서 사용자 데이터베이스가 원격에 있으면 나쁜 성능이 됩니다.
  • 일괄 처리에서는 처리량을 높이기 위해서는 가능한 한 장비에서 연산을 수행해야 하므로, 데이터베이스의 사본을 가져와 사용자 활동 이벤트 로그가 저장된 분산 파일 시스템에 넣는 것이 좋습니다.

정렬 병합 조인#

  • 매퍼는 입력 레코드로부터 키와 값을 추출하는 것이 목적입니다.

리듀스 측 정렬 병합 조인

  • 맵리듀스 프레임워크에서 키로 매퍼의 출력을 파티셔닝해 키-값 쌍으로 정렬한다면 같은 사용자의 활동 이벤트와 사용자 레코드는 리듀서의 입력으로 서로 인접해서 들어갑니다.
  • 리듀서가 항상 사용자 데이터베이스를 먼저 보고 활동 이벤트를 시간 순으로 보게 하는 식으로 맵리듀스에서 작업 레코드를 재배열하기도 합니다. 이를 보조 정렬(secondary sort) 라고 합니다.
  • 보조 정렬후, 리듀서 함수는 모든 사용자 ID당 한번만 호출되고 보조 정렬 덕분에 첫 번째 값은 사용자 데이터베이스의 생년월일 레코드로 예상할 수 있습니다.
    • 리듀서는 본 URL(viewed-url)본 사람의 연령의 쌍을 출력합니다.
    • 이를 통해 각 URL마다 본 사람의 연령 분호를 계산하고 연령대별로 클러스터링할 수 있습니다.
  • 리듀서는 특정 사용자 ID의 모든 레코드를 한 번에 처리하므로 한 번에 사용자 한 명의 레코드만 메모리에 유지하면 되고 네트워크로 아무 요청도 보낼 필요가 없습니다. 이를 정렬 병합 조인(sort-merge join) 이라고 합니다.
    • 매퍼 출력이 키로 정렬된 후에 리듀서가 조인의 양측의 정렬된 레코드 목록을 병합합니다.

같은 곳으로 연관된 데이터 가져오기#

  • 병합 정렬 조인 중 매퍼와 정렬 프로세스는 특정 사용자 ID로 조인 연산을 할 때 필요한 모든 데이터베이스를 한 곳으로 모읍니다.
    • 필요한 데이터를 사전에 줄을 세웠기 때문에 단 리듀서는 단일 스레드로 동작하는 간단한 코드 조각이 될 수 있으며 레코드를 휘젓고 다닐 때 처리량은 높게 유지하면서 메모리 부담을 줄일 수 있습니다.
  • 같은 키를 가진 키-값 쌍은 같은 리듀서를 호출합니다.
  • 맵리듀스 프로그래밍 모델은 올바른 장비로 데이터를 모으는 연산의 물리적 네트워크 통신 측면과 받은 데이터를 처리하는 애플리케이션 로직을 분리합니다.
    • 이는 데이터베이스 사용 유형과 대조적입니다.
    • 맵리듀스는 애플리케이션 로직에서 영향이 가지 않게 실패한 태스크는 확실하게 재시도합니다.

그룹화#

  • 조인 외에도 "같은 곳으로 관련 데이터를 모으는" 일반적인 사용 유형은 SQL에서 GROUP BY 절과 같이 특정 키로 레코드를 그룹화하는 것입니다.
  • 맵리듀스로 그룹화 연산을 구현하는 가장 간단한 방법은 매퍼가 키-값 쌍을 생성할 때 그룹화할 대상을 키로 하는 것입니다.
    • 맵리듀스 위에서 그룹화와 조인의 구현은 상당히 유사합니다.
  • 특정 사용자가 취한 일련의 활동을 찾기 위해 사용자 세션별 활동 이벤트를 수집 분석할 때도 일반적으로 그룹화를 사용합니다. 이 과정을 세션화(sessionization) 이라고 합니다.
  • 사용자 요청을 받는 웹 서버가 여러 개라면 특정 사용자의 활동 이벤트는 여러 서버로 분산돼 각각 다른 로그 파일에 저장됩니다.
    • 세션 쿠키, 사용자 ID나 유사한 식별자를 그룹화 키로 사용해 특정 사용자 활동 이벤트를 모두 한 곳으로 모으면 세션화를 구현할 수 있습니다.
    • 이때 서로 다른 사용자의 이벤트는 다른 파티션으로 골고루 분산됩니다.

쏠림 다루기#

  • 키 하나에 너무 많은 데이터가 연관된다면 (ex. 소셜 네트워크) 불균형한 활성 데이터베이스 레코드를 가지게 되는데 이를 린치핀 객체(linchpin object) 또는 핫 키(hot key) 라고 합니다.
  • 유명 인사 한 사람에 관련된 모든 활동을 리듀서 한 개에서 모은다면 상당한 쏠림 현상이 생깁니다. 이 현상을 핫스팟이라고 합니다.
    • 즉, 한 리듀서가 다른 리듀서보다 엄청나게 많은 레코드를 처리해야 합니다.
  • 조인 입력에 핫 키가 존재하는 경우 핫스팟을 완화시킬 몇 가지 알고리즘이 있습니다.
    • 쏠린 조인(skewed join) 메서드는 어떤 키가 핫 키인지 결정하기 위해 샘플링 작업을 수행합니다. 이 경우 핫키로 조인할 다른 입력은 핫 키가 전송된 모든 리듀서에 복제합니다.
    • 공유 조인(shared join) 메서드는 이 기법과 비슷하나 핫 키를 명시적으로 지정합니다.
  • 핫 키로 레코드를 그룹화하고 집계하는 작업은 두 단계로 수행됩니다.
    • 첫 번째 맵리듀스 단게는 레코드를 임의의 리듀서로 보냅니다. 각 리듀서는 핫 키 레코드의 일부를 그룹화하고 키별로 집계해 간소화한 값을 출력합니다.
    • 두 번째 맵리듀스 작업은 첫 단계 모든 리듀서에서 나온 값을 키별로 모두 결합해 하나의 값으로 만듭니다.

Map Reducer 구현, 파이썬

단어 빈도수 세기 예제

"""mapper.py"""
import sys
for line in sys.stdin:
line = line.strip()
words = line.split()
for word in words :
print ('%s\t%s' % (word, 1))
"""reducer.py"""
from operator import itemgetter
import sys
current_word = None
current_count = 0
word = None
for line in sys.stdin:
line = line.strip()
word, count = line.split('\t', 1)
try:
count = int(count)
except ValueError:
continue
if current_word == word:
current_count += count
else:
if current_word:
print('%s\t%s' % (current_word, current_count))
current_count = count
current_word = word
if current_word == word:
print('%s\t%s' % (current_word, current_count))
  • mapper의 아웃풋을 '키'인 단어 기준으로 정렬
cat hadoop.txt | python mapper.py | sort -k 1
  • 아웃풋을 reducer로 전달한후, 내림차순으로 정리한 경우
cat hadoop.txt | python mapper.py | sort -k 1 | python reducer.py | sort -k 2

참고 링크

맵 사이드 조인#

  • 앞의 여러 조인 알고리즘은 실제 조인 로직을 리듀서에서 수행하기 때문에 리듀스 사이드 조인(reduce-side join) 이라고 합니다.
  • 매퍼는 입력 데이터를 준비하는 역할을 합니다.
  • 리듀스 사이드 접근법의 장점은 이벽 데이터에 대한 특정 가정이 필요없다는 점입니다.
    • 그러나 정렬 후 리듀서로 복사한 뒤 리듀서 입력을 병합하는 모든 과정에 비용이 상당한 단점이 있습니다.
  • 입력 데이터에 대해 특정 가정이 가능하다면 맵사이드 조인(map-side join) 으로 불리는 기법을 사용해 조인을 더 빠르게 수행할 수 있습니다.

브로드캐스트 해시 조인#

  • 맵 사이드 조인은 작은 데이터셋과 매우 큰 데이터셋을 조인하는 경우에 간단하게 적용가능합니다
    • 작은 데이터셋은 전체를 각 매퍼 메모리에 적재 가능할 정도로 충분히 작아야 합니다.
    • 이러한 매퍼 태스크를 여러개 사용할 수도 있습니다.
  • 위처럼 간단하고 효율적인 알고리즘으을 브로드캐스트 해시 조인(broadcast hash join) 이라 합니다.
    • 브로드캐스트라는 단어는 큰 입력의 파티션 하나를 담당하는 각 매퍼는 작은 입력 전체를 읽는다는 것입니다.
    • 해시라는 이름에서 알 수 있듯이, 해시 테이블을 사용합니다.
  • 작은 조인 입력을 인메모리 해시 테이블로 적재하는 대신 로컬 디스크에 읽기 전용 색인으로 작은 조인 입력을 저장하기도 합니다.
    • 즉,이 방법을 사용하면 데이터셋 전체가 메모리 안에 들어오지 않더라도 거의 인메모리 해시 테이블만큼 빠르게 임의 접근 조회가 가능합니다.

파티션 해시 조인#

  • 같은 방식으로 맵 사이드 조인의 입력을 파티셔닝한다면 해시 조인 접근법을 각 파티션에 독립적으로 적용할 수 있습니다.
  • 제대로 파티셔닝이 작동했다면 조인할 레코드 모두가 같은 번호의 파티션에 위치합니다.
    • 각 매퍼는 각 입력 데이터셋 중 파티션 한 개만 읽어도 충분합니다. 이러한 방법은 각 매퍼의 해시 테이블에 적재해야 할 데이터의 양을 줄일 수 있다는 점이 장점입니다.
  • 파티션 해시 조인은 조인할 두 입력 모두를 같은 키와 같은 해시 함수를 기반으로 같은 수로 파티셔닝해야 작동합니다.
  • 파티션 해시 조인(partitioned hash join)을 하이브에서는 버킷 맵 조인(bucketed map join) 이라고 합니다.

맵 사이드 병합 조인#

  • 입력 데이터셋이 같은 방식으로 파티셔닝됐을 뿐 아니라 같은 키를 기준으로 정렬됐다면 변형된 맵 사이드 조인을 적용할 수 있습니다.
  • 맵 사이드 병합 정렬(map-side merge join)이 가능하다면 선행 맵리듀스 작업이 이미 입력 데이터셋을 파티셔닝하고 정렬해 놓았다는 뜻입니다.

맵 사이드 조인을 사용하는 맵리듀스 워크플로#

  • 맵리듀스 조인의 출력을 하위 작업에서 입력으로 사용하거나, 맴 사이드 조인을 사용하거나, 리듀스 사이드 조인을 사용할지에 따라 그 출력 구조가 달라집니다.
    • 리듀스 사이드 조인은 조인 키로 파티셔닝하고 정렬해서 출력합니다.
    • 반면 맵 사이드 조인은 큰 입력과 동일한 방법으로 파티셔닝하고 정렬합니다.
  • 맵 사이드 조인을 수행하기 위해서는 크기, 정렬, 입력 데이터의 파티셔닝 같은 제약 사항이 따릅니다.
    • 조인 전략을 최적화할 때는 물리적 레이아웃(파티션 수, 데이터가 어떤 키를 기준으로 파티셔닝되고 정렬됐는지) 파악이 중요합니다.
  • 하둡 생태계에서는 데이터셋 파티셔닝 관련 메타데이터를 관리하는데 H카탈로그(HCatalog)나 하이브(Hive) 메타스토어를 사용하기도 합니다.

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

맵리듀스 작업의 결과와 이 작업의 목적에 대해서 이야기합니다.

  • 데이터베이스 질의의 경우 트랜잭션 처리(OLTP)를 분석 목적과 구별했습니다.
    • OLTP 질의는 색인을 사용해 사용자에게 보여줄 소량의 레코드만 특정 키로 조회하는 것이 일반적입니다.
    • 분석 질의는 대량의 레코드를 스캔해 그룹화와 집계 연산을 수행하고 그 결과를 보고서 형태로 출력합니다.
  • 일괄 처리는 위의 트랜잭션 처리나 분석이 아니지만, 일반적으로 입력 데이터셋 대부분을 스캔하는 것이 일반적이라 분석에 더 가깝습니다.
    • 다만 일괄 처리의 워크플로는 분석 목적으로 사용하는 SQL 질의와는 다릅니다.

검색 색인 구축#

  • 구글이 색인을 구축하는 목적으로 맵리듀스를 더이상 사요하지 않지 않지만, 검색 색인을 구축하는 과정을 자세히 살펴보면 맵리듀스를 이해하하는데 도움이 많이됩니다.
  • 정해진 문서 집합을 대상으로 전문 검색이 필요하다면 일괄 처리가 색인을 구축하는데 매우 효율적입니다.
    • 매퍼는 필요에 따라 문서 집합을 파티셔닝하고 각 리듀서가 해당 파티션에 대한 색인을 구축하고 색인 파일은 분산 파일 시스템에 저장됩니다.
  • 색인된 문서 집합이 변한다면 전체 문서 집합을 대상으로 주기적으로 전체 색인 워크플로를 재수행하고 수행이 끝나면 이전 색인 파일을 서로 생성된 색인으로 바꾸는 것이 한 가지 방법입니다.
  • 다른 방법으로 증분 색인을 구축하는 것도 가능합니다.

일괄 처리의 출력으로 키-값을 저장#

  • 검색 색인은 일괄 처리 워크플로 출력의 한가지 예이니다.
  • 이러한 일괄 처리 작업의 출력은 흔히 일종의 데이터베이스가 됩니다.
  • 데이터베이스는 하둡 인프라와 별도로 사용자 요청을 받는 웹 애플리케이션에서 질의해야 합니다.
  • 가장 확실한 방법은 직접 매퍼와 리듀서 내에서 선호하는 데이터베이스 클라이언트 라이브러리를 사용해 일괄 처리 작업이 한번에 레코드 하나씩 데이터베이스 서버로 직접 요청을 보내는 것입니다. 그러나 이는 잘못된 아이디어입니다.
    • 클라이언트 라이브러리가 일괄 처리 방식을 지원해도 성능은 떨어집니다.
    • 맵리듀스 작업은 대개 많은 태스크를 동시에 실행합니다. 모든 매퍼나 리듀서가 일괄 처리에서 기대하는 속도로 동시에 같은 출력 데이터베이스에 기록한다면 데이터베이스가 과부하 상태에 빠지기 쉽고 덩달아 질의 성능도 나빠집니다.
    • 일반적으로 맵리듀스 작업은 성공한 경우에만 출력을 생성하는 것을 보장합니다. 즉, 작업이 성공하면 출력은 각 태스크가 정확하게 한번만 실행한 결과과 같습니다. 그러나 작업 내부에서 외부 시스템에 기록한다면 이런 방식에서는 감출 수 없는 외부에 드러나는 부수효과를 만들어냅니다.
  • 훨씬 좋은 해결책은 일괄 처리 작업 내부에 완전히 새로운 데이터베이스를 구축해 분산 파일 시스템의 작업 출력 디텍터리에 저장하는 방법입니다.
    • 검색 색인과 유사한 구조로 저장합니다.
    • 다양한 키-값 저장소가 맵리듀스 작업 내에서 데이터베이스 파일을 구축하는 기능을 지원합니다.
    • 데이터베이스 파일을 생성하는 작업은 굉장히 좋은 맵리듀스 활용법입니다. 매퍼로 키를 추출한 다음, 키로 정렬하는 과정은 색인을 만들 때도 꼭 필요한 작업입니다.
  • 볼드모트에 데이터를 적재할 때 분산 파일 시스템에서 서버의 로컬 디스크로 새 데이터 파일을 복사하는 동안 서버는 기존 데이터 파일로 요청을 계속 처리합니다.

일괄 처리 출력에 관한 철학#

  • 맵리듀스 작업도 마찬가지로 철학으로 출력을 취급합니다. 입력을 불변으로 처리하고 외부 데이터베이스에 기록하는 등의 부수 효과를 피하기 때문에 일괄 처리 작업은 좋은 성능을 내면서도 유지보수가 훨씬 간단합니다.
    • 코드에 버그가 있어 출력이 잘못되거나 오염됐다면 코드를 이전 버전으로 돌리고 작업을 재수행해 간단하게 출력을 고칠 수 있습니다. 혹은 다른 디렉터리에 이전 출력을 기록했다면 간단하게 출력의 위치만 바꿔 복구를 할 수 있습니다. 버그 있는 코드로부터 복원할 수 있느냐에 관한 개념을 인적 내결함성(human fault tolerance) 라고 합니다.
    • 쉽게 되돌릴 수 있는 속성의 결과로 실수를 하면 손상을 되돌릴 수 없는 환경에서보다 기능 개발을 빠르게 진행할 수 있습니다. 비가역성 최소화(minimizing irreversibility) 원리는 애자일 소프트웨어 개발에 이롭습니다.
    • 맵이나 리듀스 태스크가 실패하면 맵리듀스 프레임워크는 일시적 문제로 발생한 실패는 충분히 견딜 수 있습니다.
  • 구조화 형식은 효율적인 스키마 기반 부호화를 제공하고 시간이 지남에 따라 스키마를 발전시킬 수 있습니다.

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

  • 하둡은 유닉스의 분산 버전과 다소 비슷합니다.
  • 앞장의 처리 알고리즘과 병렬 조인 알고리즘은 대규모 병렬 처리(massively parallel processing, MVP) 데이터베이스라 불리는 것에 모두 구현되었습니다.
  • 맵리듀스와의 가장 큰 차이는 MPP 데이터베이스는 장비 클러스터에서 분석 SQL 질의를 병렬로 수행하는 것에 초점을 두지만 맵리듀스와 분산 파일 시스템의 조합은 아무 프로그램이나 실행할 수 있는 운영체제와 비슷한 속성을 제공합니다.

저장소의 다양성#

  • 데이터베이스는 특정 모델을 따라 데이터를 구조화해야합니다.
  • 극단적으로 이야기하자면 하둡은 데이터가 어떤 형태라도 상관없이 HDFS로 덤프할 수 잇는 가능성을 열어주었습니다.
  • 현실적으로 이상적인 데이터 보다는 데이터를 빨리 사용 가능하게 만드는 것이 더 가치가 있습니다.
    • 이러한 아이디어는 데이터 웨어하우스의 개념과 유사합니다.
  • 제약없는 데이터 덤핑(data dumping)은 데이터를 해석하는 부담을 이전시킵니다.
    • 이러한 접근법을 초밥 원리(sushi principle) 이라 부릅니다. 즉, "원시 데이터가 더 좋다"의 의미입니다.
  • 하둡은 ETL 프소세스를 구현하는 데 종종 사용됩니다.

처리 모델의 다양성#

  • MPP 데이터베이스는 일체식 구조로서 디스크 저장소 레이아웃과 질의 계획, 스케줄링과 실행을 다루는 소프트웨ㅓ 조각들이 긴밀하게 통합됩니다.
  • 반면 SQL 질의로 모든 종류의 처리를 표현하지는 못합니다.
  • 맵리듀스를 이용하면 엔지니어는 자신이 작성한 코드를 대용량 데이터셋 상에서 쉽게 실행할 수 있습니다.
    • HDFS와 맵리듀스가 있으면 그 위에 SQL 질의 실행 엔진을 구축할 수 있는데 하이브 프로젝트가 그러한 역할을 합니다.
  • 시간이 지나 맵리듀스가 너무 제한적이고 어떤 형태의 처리에서는 성능도 나쁘다는 점을 알게 됭ㅆ습니다.
    • 그래서 하둡 위에서 다른 다양한 처리 모델이 개발되었습니다.
  • 결정적으로 이런 다양한 처리 모델은 모두 단일 공유 클러스터 장비에서 실행되고 분산 파일 시스템상에 존재하는 동일한 파일들에 접근 가능합니다.
    • 하둡 접근법에는 다른 종류의 처리를 하기 위해 여러 다른 특정 시스템으로 데이터를 보낼 필요가 없습니다.
    • 하둡 시스템은 동일한 클러스터 내에서 다양한 작업부하를 함께 지원할 수 있을 정도로 충분히 유연합니다.
  • 하둡 생태계는 HBase 같은 임의 접근 가능한 OLTP 데이터베이스와 임팔라 같은 MPP 스타일의 분석 데이터베이스를 포함합니다.

빈번하게 발생하는 결함을 줄이는 설계#

  • 맵리듀스와 MPP 데이터베이스를 비교할 때 설계 방식에서 큰 차이점 두 가지가 두드러집니다.
    • 결합을 다루는 방식과 메모리 및 디스크를 사용하는 방식이 그 두가지 방식입니다.
    • 일괄 처리는 온라인 시스템에 비해 결함에 덜 민감합니다.
  • 질의 실행 중 한 장비만 죽어도 MPP 데이터베이스 대부분은 전체 질의가 중단됩니다.
  • 맵리듀스는 맵 또는 리듀스 태스크의 실패를 견딜 수 잇습니다.
  • 맵리듀스 접근법은 대용량 작업에 더 적합합니다.
  • 그러나 대부분의 상황은 장비 장애가 자주 발생하징는 않습니다.
  • 모든 태스크는 우선순위가 있고, 우선순위가 높은 태스크에 더 많은 자원이 필요하다면 자원 확보를 위해 같은 장비에서 수행되던 우선순위가 낮은 태스크를 종료할 수 있습니다.
  • 이 아키텍처를 사용하면 비프로덕션 연산 자원을 초과 할당할 수 있습니다.
  • 맵리듀스는 태스크 종료가 예상치 못하게 자주 발생하더라도 견딜 수 있게 설계되었습니다. 즉, 하드우에어를 신뢰할 수 없기 때문이 아닌 프로세스를 임의로 종료할 수 있으면 연산 클러스터에서 자원 활용도를 높일 수 있기 때문입니다.

맵리듀스를 넘어#

  • 맵리듀스는 2000년대 후반 인기가 있었으나 이는 그저 분산 시스템에서 가능한 여러 프로그래밍 모델 중 단지 하나일 뿐입니다.
  • 맵리듀스는 단순 명료하게 추상화된 모델이기에 의의를 가집니다. (즉, 무엇을 하고 있는지 이해하기 쉽다는 뜻입니다.)
  • 맵리듀스를 직접 사용하는 일은 어렵기 때문에 맵리듀스 상에 추상화된 다양한 고수준 프로그래밍 모델(피그, 하이브, 캐스캐이딩, 크런치 등)이 등장했습니다.
    • 이러한 고수준 프로그래밍 모델은 맵리듀스가 어떻게 동작하는지 이해하고 있으면 확실히 배우기 쉬울 뿐 아니라 일반적인 일괄 처리 태스크를 구현하기 상당히 편리합니다.
  • 그러나 맵리듀스 실행 모델 자체에도 문제가 있으며 이는 추상화 단계를 올린다고 해결되지 않고 일부 유형의 처리에 대해서는 성능 저하를 유발합니다.
    • 맵리듀스는 견고합니다.
    • 즉, 맵리듀스 작업은 느릴지언정 성공하나 특정 유형의 처리는 다른 도구들이 더 빠를 수 있습니다.

아래에서는 일괄 처리 방법의 대안을 찾아봅니다.

중간 상태 구체화#

  • 맵리듀스 작업은 다른 작업과 모두 독립적입니다.
    • 주요 접점은 분산 파일 시스템 상의 입력과 출력 디렉터리입니다.
    • 첫 번째 작업의 출력을 두 번째 작업의 입력으로 사용하려면 두 번째 작업의 입력 디렉터리를 첫 번째 작업 출력 디렉터리와 같게 설정해야 합니다.
    • 외부 워크플로 스케줄러에서 반드시 첫번째 작업을 완료한 후 두 번째 작업을 수행해야 합니다.
    • 첫 번째 작업의 출력이 조직 내에 널리 공개하는 데이터셋이라면 이러한 설정은 합리적입니다.
  • 그러나 대개 한 작업의 출력은 같은 팀 내에서 유지보수하는 다른 특정 작업의 입력으로만 사용됩니다.
    • 분산 파일 시스템 상에 있는 파일들은 단순히 한 작업에서 다른 작업으로 데이터를 옮기는 수단, 즉 중간 상태(Intermediate state) 가 됩니다.
  • 중간 상태를 파일로 기록하는 과정을 구체화(materialization) 이라 합니다.
  • 이전 장에서는 유닉스 파이프를 사용했는데, 파이프는 중간 상태를 완전히 구체화하는 대신 작은 인메모리 버퍼만을 사용해 점진적으로 출력을 입력으로 스트리밍 합니다.
  • 중간 상태를 완전히 구체화하는 맵리듀스 접근법은 유닉스 파이프에 비해 여러 단점이 있습니다.
    • 맵리듀스 작업은 입력을 생성하는 모든 선행 작업이 완료됐을 때만 시작 가능합니다. 그러나 파이프는 동시에 시작되고 출력은 생상되는 즉시 소비됩니다.
    • 매퍼는 종종 중복되기도 합니다.
    • 분산 파일 시스템에서 중간 상태를 저장하는 것은 중간 상태 파일들이 여러 장비에 걸쳐 복제됐다는 의미이며 이런 임시 데이터에게는 과잉조치입니다.

데이터플로 엔진#

  • 맵리듀스의 여러 문제를 해갈하기 위해 분산 일괄 처리 연산을 수행하는 엔진이 여러개 개발되었습니다. (스파크, 테스, 플링크 등)
    • 이러한 엔진들의 공통점은 전체 워크플로를 독립된 하위 작업으로 나누지 않고 작업 하나로서 다룬다는 점입니다.
  • 위 엔진들은 여러 처리 단계를 통해 데이터 흐름을 명시적으로 모델링하기 때문에 이 시스템을 데이터플로 엔진(dataflow engine) 이라고 부릅니다.
  • 맵리듀스와 달리 이 함수들은 맵과 리듀스를 번갈아 수행하는 식의 규칙을 엄격하게 지킬 필요가 없으며 더 유연하게 함수들을 조합할 수 있습니다.
    • 이러한 함수를 연산자(operator) 라고 부릅니다.
    • 정렬, 정렬을 건너뛰는 선택지, 브로드캐스트 해시 조인 등
  • 데이터플로 엔진은 맵리듀스 모델과 비교했을 때 몇가지 장점이 있습니다.
    • 정렬과 같은 값비싼 작업은 실제로 필요할 때만 수행합니다. 맵리듀스 모델은 기본적으로 모든 맵과 리듀스 사이에서 정렬 작업이 항상 발생합니다.
    • 필요없는 맵 태스크는 없습니다. 매퍼가 수행한 작업은 종종 선행 리듀스 연산자로 통합할 수 있기 때문입니다.
    • 워크플로에 모든 조인과 데이터 의존 관계를 명시적으로 선언하기 때문에 스케줄러가 어느 데이터가 어디에서 필요한지에 대한 개요를 가져서 지역성 최적화가 가능합니다.
    • 워크플로에 모든 조인과 데이터 의존 관계를 명시적으로 선언하기 때문에 스케줄러가 어느 데이터가 어디에 필요한지에 대한 개요를 자겨서 지역성 최적화가 가능합니다.
    • 연산자 간 중간 상태는 대개 메모리나 로컬디스크에 기록하는 것으로 충분한데 HDFS에 중간 상태를 기록할 때 보다 I/O가 훨씬 적게 듭니다.
    • 연산자들은 입력이 준비되는 즉시 실행을 시작할 수 있습니다.
    • 새로운 연산자를 실행할 때 이미 존재하는 자바 가상 머신(JVM)을 재활용할 수 있어 각 태스크마다 새로운 JVM을 구동하는 맵리듀스에 비해 시작 부담이 적습니다.
  • 맵리듀스 워크플로와 동일한 연산을 데이터플로 엔진을 사용해 구현할 수 있습니다. 또한 앞의 최적화로 인해 수행 속도가 훨씬 더 빠릅니다.
  • 테즈는 노드 간에 데이터를 실제로 복사하는 YARN 셔플 서비스에 의존하는 상당히 가벼운 라이브러리이며 스파크와 플링크는 자체 네트워크 통신 게층과 스케줄러, 사용자 측 API를 가진 대형 프레임워크입니다.

내결함성#

  • 분산 파일 시스템에 중간 상태를 모두 구체화할 때 생기는 이점은 내구성입니다.
    • 맵리듀스는 중간 상태를 모두 구체화하기 때문에 쉽게 내결함성을 확보합니다.
  • 스파크와 플링크, 테즈는 HDFS에 중간 상태를 쓰지 않기 때문에 내결함성 확보를 위해 다른 접근법을 사용합니다.
    • 장비가 죽어서 장비에 있던 상태까지 잃게 되면 아직 유효한 데이터로부터 계산을 다시해서 복구합니다.
  • 재계산이 가능하려면 프레임워크에서 주어진 데이터가 어떻게 연산되는지 추적해야합니다.
  • 데이터를 재연산할 때 중요한 점은 해당 연산이 결정적인지 아닌지 파악하는 것입니다.
    • 즉, 동일한 입력 데이터가 주어졌을 때 연산자들이 항상 같은 출력을 생산할지에 대한 내용은 중요합니다.
  • 아래로 전파되는 결함을 피하려면 연산자를 결정적으로 만드는 것이 좋습니다.
  • 결함에서 복구할 때 데이터를 재연산하는 방식이 항상 정답은 아닙니다. 중간 데이터가 원천 데이터보다 훨씬 작거나 연산이 CPU 중심적이라면 재연산보다 중간 데이터를 파일로 구체화하는 방식이 더 효과적입니다.

구체화에 대한 논의#

  • 유닉스에 비유하자면 맵리듀스는 각 명령의 출력을 임시 파일에 기록하는 것과 유사한 반면 데이터플로 엔진은 유닉스 파이프와 매우 비슷합니다.
  • 정렬 연산자는 출력을 생산하기 전에 전체 입력을 소비해야 합니다.
  • 작업을 완료하고 출력을 다른 사용자가 찾아 사용할 수 있게 지속성 있는 어떤 곳으로 보내야합니다.
    • 일반적으로 출력을 분산 파일 시스템에 다시 기록합니다. 즉, 데이터플로 엔진을 사용할 때 HDFS상에 구체화된 데이터셋은 보통 작업의 입력과 최종 출력입니다.

그래프와 반복 처리#

  • 스파크와 플링크, 테즈 같은 데이터플로 엔진은 일반적으로 작업에 있는 연산자를 비순환 방향 그래프로 배열합니다. 이는 그래프 처리와 다릅니다.
    • 데이텁플로 엔진에서는 데이터 자체는 전형적으로 관계형 튜플의 형태로 구성된 채로 한 연사자로부터 다른 연산자로 가는 데이터 흐름이 그래프로 구성됩니다.
    • 그래프 처리에서는 데이터 자체가 그래프 형식입니다.
  • 어떤 지역이 어느 다른 지역 내에 속하는지 가리키는 간선을 반복적으로 따라가는 방식을 이형적 폐쇄(transitive closure) 라고 합니다.
  • 맵리듀스는 데이터를 일회성으로만 처리하며, 이런 알고리즘은 대개 반복적 스타일로 구현됩니다.
    • 외부 스케줄러가 이 알고리즘의 한 단계를 연산하기 위해 일괄 처리를 수행합니다.
    • 해당 일괄 처리가 완료되면 스케줄러는 종료 조건을 기반으로 완료됐는지 확인합니다.
    • 아직 끝나지 않았다면 스케줄러는 1단계로 돌아가서 다음 일괄 처리를 수행합니다.
  • 위의 접근법은 맵리듀스로 구현해도 동작하나 비효율적입니다 .맵리듀스는 알고리즘의 반복적 속성을 고려하지 않기 때문입니다.

프리글 처리 모델#

  • 일괄 처리 그래프를 최적화하는 방법으로 벌크 동기식 병렬(bulk synchronous parallel, BSP) 연산 모델이 널리 사용됩니다.
  • 맵리듀스에서는 개념적으로 매퍼가 특정 리듀서를 호출해 "메시지를 전달"합니다.
    • 맵리듀스 프레임워크가 매퍼의 출력을 동일한 키를 기준으로 수집하기 때문입니다.
  • 반복할 때마다 개별 정점에서 함수를 호출해 그 정점으로 보내진 모든 메시지를 전달하는데 이는 프리글과 리듀서를 호출하는 방식이 비슷합니다.
    • 맵리듀스와 프리글 모델의 차이점은 정점에서 반복에서 사용한 메모리 상태를 기억하고 있다는 점입니다.
  • 프리글 모델은 액터 모델과 살짝 비슷하며, 각 정점은 액터로 본다면 정점 상태를 제외하고 정점 사이의 메시지는 내결함성과 지속성이 있습니다.

내결함성#

  • 정점이 서로 질의하는 방식이 아니라 메시지 전달로 통신한다는 점은 프리글 작업 성능 향상에 도움을 줍니다.
  • 네트워크 상의 문제로 메시지가 사라지거나 중복, 지연되더라도 프리글 구현상 다음 반복에서 메시지는 목적지 정점에서 정확히 한 번만 처리되빈다.
  • 이러한 내결함성은 반복이 끝나는 시점에 모든 정점의 상태를 주기적으로 체크포인트로 저장함으로써 보장됩니다.

병렬 실행#

  • 정점은 어떤 물리 장비에서 실행되는지 알 필요가 없기 때문에 메시지를 다른 정점으로 보낼 때 단순히 정점 ID를 사용해 메시지를 전달합니다.
  • 프로그래밍 모델은 한 번에 정점 한 개를 다루기 때문에 프리글 프레임워크가 임의의 방법으로 그래프를 파티셔닝할 수 있습니다.
  • 결과적으로 그래프 알고리즘은 장비간 통신 오버헤드가 많이 발생합니다.
  • 이러한 이유로 그래프가 단일 컴퓨터 메모리에 넣즐 수 있는 크기라면 단일 장비 알고리즘이 분산 일괄 처리보다 훨씬 성능이 좋을 가능성이 있습니다.

고수준 API와 언어#

  • 10000대가 넘는 장비로 구성된 클러스터 상에서 페타바이트급의 데이터를 충분히 저장하고 처리할 정도로, 일괄 처리를 운영하는 문제가 거의 해결했으며 다른 분야에 더 집중할 수 있게 되었습니다.
  • 직접 맵리듀스 작업을 작성하는 일은 상당히 어렵기 때문에 하이브, 피그, 캐스캐이딩, 크런치와 같은 고수준 언어나 API가 인기를 끌었습니다.
  • 이렇게 데이터플로 API는 일반적으로 관계형 스타일의 빌딩 블록을 사용해 연산을 표현합니다.
  • 고수준 인터페이스는 코드를 적게 작성해도 되는 명백한 이점뿐만 아니라 대화식 사용도 지원합니다.
  • 고수준 인터페이스를 사용하면 사용자가 시스템의 생산성 높게 사용할 수 있을 뿐 아니라 장비 수준에서도 작업을 더욱 효율적으로 수행할 수 있습니다.

선언형 질의 언어로 전환#

  • 조인을 수행하는 코드를 작성하는 방식에 비해 관계형 연산자로 조인을 나타내면 프레임워크가 조인 입력의 속성을 분석해 자동으로 앞서 기술한 조인 알고리즘 중에 어떤 방법이 적절한지 자동으로 결정할 수 있다는 장점이 있습니다.
  • 어떤 조인 알고리즘을 선택하느냐에 따라 일괄 처리 작업의 성능이 크게 달라집니다.
    • 선언적인 방법으로 조인을 지정하면 가능합니다.
  • 맵리듀스와 맵리듀스의 데이터플로 계승자들은 SQL의 완전한 선언형 질의 모델과는 다릅니다.
    • 맵리듀스는 함수 콜백 개념으로 각 레코드 또는 레코드 그룹을 입력으로 사용자 정의 함수를 호출합니다.
  • 코드를 임의로 실행할 수 있다는 점은 MPP 데이터베이스와 맵리듀스를 계승하는 일괄 처리 시스템을 오랜 세월 동안 구별해준 특성입니다.
  • 데이터플로 엔진도 조인 외에 좀 더 선언적인 기능을 통합하면 이점이 있습니다.
    • 디스크에서 필요한 칼럼만 읽을 수 있습니다.
  • 고수준 API에 선언적 측면을 포함하면서 실행 중에 이용할 수 있는 질의 최적화기를 가진다면 일괄 처리 프레임워크는 MPP 데이터베이스와 한승 비슷해집니다. (성능적으로도)
    • 동시에 일괄처리 프레임워크는 임의의 코드를 실행하고 임의 형식의 데이터를 읽을 수 있는 확장성을 지녀 일괄처리 프레임워크의 장점인 유연성은 그대로 유지합니다.

다양한 분야를 지원하기 위한 전문화#

  • 재사용 가능한 공통 빌딩 블록을 구현하는 일은 가치가 있습니다.
    • 이러한 분야로 비즈니스 정보 분석, 통계학, 수치 알고리즘, 염기 서열 분석 등이 있습니다.
  • 일괄 처리 엔진은 광범위한 영역에서 필요한 알고리즘을 분산 수행하는데 사용됩니다.
    • 일괄 처리 시스템은 내장 기능과 고수준 선언적 연산자를 모두가 가지고 있고 MPP 데이터베이스는 유연해져서 비슷해 보입니다.
    • 일괄 처리 시스템과 MPP 데이터베이스 모두 결국에는 데이터를 저장하고 처리하는 시스템이기 때문입니다.

정리#

  • 맵리듀스의 설계 원리는 입력은 불변이고 출력은 다른 프로그램의 입력으로 사용됩니다.
  • 유닉스 환경에서 프로그램과 다른 프로그램을 연결하는 단일 인터페이스는 파일과 파이프입니다. 맵리듀스의 인터페이스는 분산 파일 시스템입니다.
  • 분산 일괄 처리 프레임워크는 두가지 중요한 문제를 고려해야합니다.
    • 파티셔닝
    • 내결함성
  • 맵리듀스에서 사용하는 몇 가지 조인 알고리즘은 다음과 같습니다.
    • 정렬 병합 조인
    • 브로드캐스트 해시 조인
    • 파티션 해시 조인
  • 분산 일괄 처리 엔진은 의도적으로 제한된 프로그래밍 모델을 제공합니다.
  • 프레임워크는 작업의 최종 출력이 결함이 생기지 않을 때와 동일하게 보장됩니다.
    • 이러한 신뢰성의 시맨틱은 온라인 서비스에서 사용자 요청을 처리하고 그 부수 효과로 데이터베이스에 기록하는 것에 비해 훨씬 강력합니다.
  • 일괄 처리 작업의 차별화된 특징은 입력을 수정하지 않고 입력을 읽어 출력을 생산한다는 점입니다. (즉, 출력은 입력으로부터 파생됩니다.)
    • 결정적으로 입력 데이터는 고정된 크기로 한정됩니다.

다음의 장에서는 스트림 처리를 다루며 스트림 처리는 입력이 한정되지 않습니다.

Last updated on