10장 - 일괄 처리
- Date
- 2023년 1월 29일 PM 8:02
1. 일괄 처리#
- 시스템의 세 가지 유형
- 서비스(온라인 시스템) = 서비스는 클라이언트로부터 요청이나 지시가 올때까지 기다린다.
- 일괄 처리 시스템(오프라인 시스템) = 매우 큰 입력의 데이터를 받아 데이터를 처리하는 작업을 수행하고 결과 데이터를 생산한다.
- 스트림 처리 시스템(준실시간 시스템) = 온라인과 오프라인 사이의 어딘가에 위치하기에 준실시간 처리라고 부릅니다. 일처리 작업은 정해진 크기의 입력 데이터를 대상으로 작동하지만 스트림 처리는 입력 이벤트가 발생한 직후 바로 작동한다.
2. 유닉스 도구로 일괄 처리하기#
2.1. 단순 로그 분석#
- 다양한 도구를 사용해 트래픽 보고서를 깔끔하게 만들 수 있다.
shell
cat /var/log/nginx/access.log |
awk '{print $7} |
sort |
uniq -c |
sort -r -n |
head -n 5- 익숙하지 않다면 이해하기 쉽지 않지만 이 방식은 상당히 강력하다.
2.1.1. 연쇄 명령 대 맞춤형 프로그램#
ruby
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}"}- 표면적인 문법의 차이를 빼고 두가지 방법은 실행 흐름이 크게 다르다.
2.1.2. 정렬 대 인메모리 집계#
- 루비 스크립트는 URL 해시 테이블을 메모리에 유지한다.
- 유닉스 파이프라인 예제는 이러한 해시 테이블이 없다.
2.2. 유닉스 철학#
- 1978년 기술된 유닉스 철학은 다음과 같다.
- 각 프로그램이 한 가지 일만 하도록 작성하다.
- 모든 프로그램의 출력은 아직 알려지지 않은 다른 프로그램의 입력으로 쓰일 수 있다고 생각하라.
- 소프트웨어를 빠르게 써볼 수 있게 설계하고 구축하라.
- 프로그래밍 작업을 줄이려면 미숙한 도움보단 도구를 사용하라.
- bash나 유닉스 셸을 사용하면 작은 프로그램들을 가지고 놀랄 만큼 강력한 데이터 처리 작업을 쉽게 구성할 수 있다.
2.2.1. 동일 인터페이스#
- 어떤 프로그램의 출력을 다른 프로그램의 입력으로 쓰고자 한다면 이들 프로그램은 같은 데이터 형식을 사용해야 한다.
- 즉, 특정 프로그램이 다른 어떤 프로그램과도 연결 가능하려면 프로그램 모두가 같은 입출력 인터페이스를 사용해야 한다는 의미다.
- 동일한 데이터 모델인 데이터베이스 간에도 한쪽에서 다른 쪽으로 데이터를 옮기는 게 쉽지 않습니다. 이처럼 데이터가 발칸화되는 이유는 유닉스 도구와 같은 통합이 부족했기 때문이다.
2.2.2. 로직과 연결의 분리#
- 유닉스 도구의 다른 특징 중 하나는 표준 입력(stidn)과 표준 출력(stdout)을 사용한다는 점이다.
- 이러한 경우와 같이 입력이 어디서부터 들어오는지, 출력이 어디로 나가는지 신경을 쓰거나 알 필요가 없다.
- 이러한 형태를 느슨한 결합(loose coupling) , 지연 바인딩(late binding), 또는 제어 반전(inversion of control) 이라고도 한다.
2.2.3. 투명성과 실험#
- 유닉스 도구가 성공적인 이유 중 하나는 진행 사항을 파악하기가 상당히 쉽기 때문이다.
- 유닉스 명령에 들어가는 입력 파일은 일반적으로 불변으로 처리된다.
- 어느 시점이든 파이프라인을 중단하고 출력을 파이프를 통해 less로 보내 원하는 형태의 출력이 나오는지 확인할 수 있다.
- 특정 파이프라인 단계의 출력을 파일에 쓰고 그 파일의 다음 단계의 입력으로 사용할 수 있다.
- 유닉스 도구는 일부 불친절하지만 단순하고 유용하다.
- 이러한 가장 큰 제약은 단일 장비에서만 실행되며 이러한 이유로 하둡 같은 도구가 필요하다.
3. 맵리듀스와 분산 파일 시스템#
- 맵리듀스는 유닉스 도구와 비슷한 명이 있지만 수천 대의 장비로 분산해서 실행이 가능하다는 점에서 차이가 있다.
- 유닉스 도구와 마찬가리로 맵리듀스 작업은 입력을 수정하지 않기 때문에 출력을 생산하는 것 외에 다른 부수효과는 없다.
- 하둡 맵리듀스 구현에서 파일 시스템은 HDFS라 하는데 GFS를 재구현한 오픈소스다.
- HDFS는 비공유 원칙을 기반으로 하는데 NAS와 SAN 아키텍처에서 사용하는 공유 디스크 방식과는 반대다.
- HDFS는 각 장비에서 실행되는 데몬 프로세스로 구성되며 다른 노드가 해당 장비에 저장된 파일에 접근하게끔 네트워크 서비스를 제공한다.
- 네임노드라 부르는 중앙 서버는 특정 파일 블록이 어떤 장비에 저장됐는지 추적한다.
3.1. 맵리듀스 작업 실행 하기#
- 맵리듀스는 HDFS와 같은 분산 파일 시스템 위에서 대용량 데이터셋을 처리하는 코드를 작성하는 프로그래밍 프레임워크다.
- 맵리듀스 작업 하나는 4가지 단계로 구성된다.
- 1단계 : 파일을 나누어 레코드를 만드는 데 입력 형식 파서를 쓴다.
- 2단계 : 맵(Map)
- 3단계 : 정렬 단계
- 4단계 : 리듀스
- 맵리듀스 작업을 생성하려면 다음과 같이 동작하는 매퍼와 리듀서라는 콜백 함수를 구현해야 한다.
- 매퍼(Mapper) : 매퍼는 모든 입력 레코드마다 한 번씩만 호출된다.
- 리듀서(Reducer) : 맵리듀스 프레임워크는 매퍼가 생성한 키- 값 쌍을 받아 같은 키를 가진 레코드를 모으고 해당 값의 집합을 반복해 리듀서 함수를 호출한다.
- 매퍼는 정렬에 적합한 형태로 데이터를 준비하는 역할을 하고, 리듀서는 정렬된 데이터를 가공하는 역할을 한다.
3.1.1. 맵리듀스의 분산 실행#
- 유닉스 명령어 파이프라인과 가장 큰 차이점은 맵리듀스가 병렬로 수행하는 코드를 직접 작성하지 않고도 여러 장비에서 동시에 처리가 가능하다.
- 매퍼와 리듀서는 한 번에 하나의 레코드만 처리하고 입력이 어디서, 출력이 어디로 가는지 신경쓰지 않는다.
- 분산 연산에서 매퍼와 리듀서로 표준 유닉스 도구를 사용하는 것도 가능하다.
- 하둡 맵리듀스 작업에서 데이터플로를 보여줍니다. 맵리듀스 작업의 병렬 실행은 파티셔닝을 기반으로 한다.
- RAM과 CPU에 여유가 있다면 맵리듀스 스케줄러가 입력 파일이 있는 장비에서 작업을 수행하는 것이 좋은 데 이 원리를 데이터 가까이에서 연산하기라고 한다.
- 대표적인 예시로, 자바 프로그램을 예로 들면 JAR 파일을 복사한 후 각 장비에서 매퍼 태스크가 시작됩니다. 입력 파일을 읽기 시작하면 입력 파일에서 한 번에 레코드 하나씩 읽어 매퍼 콜백 함수로 전달한다.
- 리듀서 측 연산도 파티셔닝된다.
- 태스크 수는 사용자가 설정한다.
- 키-값 쌍은 반드시 정렬돼야 하지만 대개 데이터셋이 매우 크기 때문에 단게를 나눠서 정렬을 수행한다.
- 매퍼가 입력 파일을 읽어서 정렬된 출력 파일을 기록하기를 완료하면 맴 리듀스 스케줄러는 그 매퍼에서 출력 파일을 가져올 수 있다고 리듀서에게 알려준다.
- 리듀서를 기준으로 파티셔닝하고 정렬한 뒤 매퍼에게 데이터 파티션을 복사하는 과정을 셔플(shuffle) 라고 한다.
- 리듀서 태스크는 매퍼로부터 파일을 가져와 정렬된 순서를 유지하면서 병합한다.
- 그래서 리듀서의 입력으로 들어갈 때는 서로 인전해서 들어가게 된다.
- 리듀서는 키와 반복자(iterator)를 인자로 호출하는 데 이 반복자로 전달된 키와 동일한 키를 가진 레코드를 모두 훑을 수 있다.
3.1.2. 맵리듀스 워크플로#
- 맵리듀스 작업 하나로 해결할 수 있는 문제의 범위는 제한적이다다.
- 따라서 맵리듀스 작업을 연결해 워크폴로(workflow) 로 구성하는 방식은 꽤 일반적이다.
- 일괄 처리 작업의 출력은 작업이 성공적으로 끝났을 때만 유효합니다.
- 맵리듀스는 작업이 실패하고 남은 부분 출력은 제거합니다.
3.2. 리듀스 사이드 조인과 그룹화#
- 여러 데이터넷에서 한 레코드가 다른 레코드와 연관이 있는 것은 일반적이다.
- 관계형 모델에서는 외래키(foreign key), 문서 모델에서는 문서 참조(document reference), 그래프 모델에서는 간선(edge) 라고 한다.
- 데이터베이스에서 적은 수의 레코드만 관련된 질의를 실행한다면 데이터베이스는 일반적으로 색인(index)을 사용하지만 맵리듀스에서는 색인 개념이 없다.
- 맵리듀스는 파일을 전체 읽으며 이는 비용이 비싸보이지만 병렬처리가 가능하기 때문에 합리적이다.
- 일괄 처리 맥락에서의 조인은 데이터셋 내 모든 연관 관계를 다룬다는 뜻입니다.