- 스파크를 공부하면서 하둡에 관심이 가기 시작했고 실무로 배우는 빅데이터 기술의 책을 읽고 간단한 사이드 프로젝트를 진행하면서 하둡 에코시스템에 대해 디테일하게 알고 싶어 책을 선택하게 되었습니다.
- 2005년 더크 커팅이 오픈 소스로 공개한 하둡은 분산 저장 파일시스템인 HDFS와 분산 병렬 처리를 담당하는 맵리듀스로 구성되어 있음, 하둡이 나온 후 이를 기반으로 피그, 하이브, HBase, 스쿱, 플룸 등의 오픈 소스 기술이 등장했고, 이들을 모두 결합한 빅데이터 기술은 통칭하여 하둡 에코시스템이라고 부르게 되었음, 스파크의 등장으로 대용량 데이터를 저장하고 일괄 처리하는 수준에서 벗어나 머신러닝과 실시간 분석까지 아우르게 되었으며 하둡 기초부터 시작하여 맵리듀스, 운영, 사례와 하둡 관련 오픈 소스 기술에 대해 자세히 설명하고 있습니다.
- 이 책은 하둡의 핵심, 하둡 에코시스템 관련 프로젝트, 하둡 사례 연구를 다루고 있으며 이 책을 통해 각 기술의 핵심을 설명했고, 다른 기술과의 관계도 친절하게 설명하고 있다.
- 하둡 관련 프로젝트인 에이브로, 파케이, 플룸, 스쿱, 피그, 하이브, 크런치, 스파크, HBase, 주키퍼의 특징들에 대해 디테일하게 설명하고 있으며 관련 코드까지 예시로 보여주고 있어서 이해하는데 편했습니다. 책이 전반적인 난이도를 요하고 있으나 읽으면서 분산시스템에 대한 전반적인 이해를 할 수 있어서 좋았습니다.
- 전체 데이터에 질의하기
- 맵리듀스의 접근법은 무차별대입(brute-force) 방식 처럼 보임 , 맵리듀스 전체가 한 번의 쿼리로 전체나 상당한 규모의 데이터셋을 처리하는 것이기 때문
- 맵리듀스는 일괄 질의 처리기고, 전체 데이터셋을 대상으로 비정형(ad hoc) 쿼리를 수행하고 합리적인 시간 내에 그 결과를 보여주는 능력을 지니고 있음
- 일괄 처리를 넘어서
- 맵리듀스의 강점은 기본적으로 일괄 처리 시스템, 대화형 분석에는 적합하지 않음, 질의를 실행한 후 수 초 이내에 결과를 받는 것을 불가능함
- 온라인 접근을 지원하는 첫 번째 구성요소인 HBase는 HDFS를 기본 저장소로 하는 키-값 저장소, HBase는 개별 행에 대한 온라인 읽기/쓰기와 산적한 데이터를 읽고 쓰는 일괄 처리를 둘다 지원하기 때문에 애플리케이션을 구축하는 데 좋은 솔루션이 될 수 있음
- YARN은 클러스터 자원 관리 시스템으로, 맵리듀스뿐만 아니라 어떤 분산 프로그램도 하둡 클러스터에 저장된 데이터를 처리할 수 있게 해줌
- 다양한 처리 패턴
- 대화형 SQL
- 대화형 sQL은 맵리듀스 대신 장기 실행 전용 데몬(임팔라)이나 컨테이너를 재사용하는(테즈 기반의 하이브) 분산 쿼리 엔진을 사용함
- 반복 처리
- 머신러닝과 같은 다수의 알고리즘은 근본적으로 반복 연산을 함
- 스트림 처리
- 스톰, 스파크 스트리밍, 삼자와 같은 스트리밍 시스템은 실시간으로 실행되고 경계가 없는 스트림 데이터를 분산 계산하여 그 결과를 하둡 저장소나 외부 시스템에 보낼 수 있음
- 검색
- 솔라(Solr) 검색 플랫폼은 하둡 클러스터에서 실행될 수 있음, 솔라는 문서를 색인하여 HDFS에 저장하고 HDFS에 저장된 색인을 기반으로 검색 쿼리를 제공함
- 대화형 SQL
- 분산형으로 확장하기
- 데이터 흐름
- 맵리듀스 잡은 클라이언트가 수행하는 작업의 기본 단위, 잡은 입력 데이터, 맵리듀스 프로그램, 설정 정보로 구성됨
- 하둡은 잡을 맵 태스크와 리듀스 태스크로 나누어 실행함, 각 태스크는 YARN을 이용하여 스케줄링되고 클러스터의 여러 노드에서 실행됨, 특정 노드의 태스크 하나가 실패하면 자동으로 다른 노드를 재할당하여 다시 실행됨
- 하둡은 맵리듀스 잡의 입력을 입력 스플릿(input split) 또는 단순히 스플릿이라고 부르는 고정 크기 조각으로 분리함, 하둡은 각 스플릿마다 하나의 맵 태스크를 생성하고 스플릿의 각 레코드를 사용자 정의 맵 함수로 처리함
- 데이터 지역성 최적화(data locality optimiztation) : 하둡은 HDFS 내의 입력 데이터가 있는 노드에서 맵 태스크를 실행할 때 가장 빠르게 작동함, 클ㄹ러스터의 중요한 공유 자원인 네트워크 대역폭을 사용하지 않는 방법
- 컴바이너 함수
- 하둡은 맵의 결과를 처리하는 컴바이너 함수(컴바이너 함수의 출력이 결국 리듀스 함수의 입력이 됨)를 허용, 컴바이너 함수는 최적화와 관련이 있음
- 하둡은 컴바이너 함수의 호출 빈도와 상관없이 리듀스의 결과가 언제나 같도록 보장함
- 컴바이너를 사용하면 매퍼와 리듀서 사이의 셔플 단계에서 전송되는 데이터양을 줄이는 데 큰 도움이됨
- 컴바이너 함수는 Reducer 클래스를 사용해서 정의함, MaxTemperatureReducer에 있는 리듀서 함수와 동일한 구현체를 사용함
- 분산 맵리듀스 잡 실행하기
- 맵리듀스는 데이터 크기와 하드웨어 성능에 따라 확장할 수 있는데 이것이 바로 맵리듀스의 핵심임
- 데이터 흐름
- 하둡 스트리밍
- 자바 외에 다른 언어로 맵과 리듀스 함수를 작성할 수 있는 맵리듀스 API를 제공함
- 하둡과 사용자 프로그램 사이의 인터페이스로 유닉스 표준 스트림을 사용함, 사용자는 표준 입력을 읽고 표준 출력으로 쓸 수 있는 다양한 언어를 이용하여 맵리듀스 프로그램을 작성할 수 있음
- 스트리밍은 그 특성상 텍스트 처리에 매우 적합함, 맵의 입력 데이터는 표준 입력으로 맵 함수에 전달되고, 행 단위로 처리되어 표준 출력으로 쓰여짐, 맵의 출력 키-값 쌍은 탭으로 구분된 하나의 행으로 출력됨
- 네트워크로 연결된 여러 머신의 스토리지를 관리하는 파일시스템
- HDFS(Hadoop Distributed FileSystem)라는 분산 파일시스템을 제공함
- HDFS 설계
- 범용 하드웨어로 구성된 클러스터에서 실행되고 스트리밍 방식의 데이터 접근 패턴으로 대용량 파일을 다룰 수 있도록 설계된 파일시스템
- 설계 특성
- 매우 큰 파일
- 스트리밍 방식의 데이터 접근
- 범용 하드웨어
- 하둡은 노드 장애가 발생할 확률이 높은 범용 하드웨어(여러 업체에서 제공하는 쉽게 구할 수 있는 하드웨어)로 구성된 대형 클러스터에서 문제없이 실행되도록 설계됨
- HDFS가 잘 맞지 않는 응용 분야
- 빠른 데이터 응답시간
- HDFS는 높은 데이터 처리량을 제공하기 위해 최적화되어 있고 이를 위해 응답 시간을 희생함, HBase가 하나의 대안이 될 수 있음
- 수많은 작은 파일
- 다중 라이터와 파일의 임의 수정
- HDFS는 단일 라이터로 파일을 씀, 한 번 쓰고 끝나거나 파일의 끝에 덧붙이는 것은 가능하지만 파일에서 임의 위치에 있는 내용을 수정하는 것은 허용하지 않으며 다중 라이터도 지원하지 않음
- 빠른 데이터 응답시간
- HDFS 개념
- 블록
- 블록 크기는 한 번에 읽고 쓸 수 있는 데이터의 최대량
- HDFS 블록이 큰 이유
- HDFS 블록은 디스크 블록에 비해 상당히 큼, 탐색 비용을 최소화하기 위해서, 블록이 매우 크면 블록의 시작점을 탐색하는데 걸리는 시간을 줄일 수 있고 데이터를 전송하는 데 더 많은 시간을 할애할 수 있음, 여러 개의 블록으로 구성된 대용량 파일을 전송하는 시간은 디스크 전송 속도에 크게 영향을 받음
- 블록 추상화 개념을 도입하면서 얻은 이점
- 파일 하나의 크기가 단일 디스크의 용량보다 더 커질 수 있다는 것
- 파일 단위보다는 블록 단위로 추상화를 하면 스토리지의 서브시스템을 단순하게 만들 수 있다는 것
- 블록은 내고장성(fault tolerance)과 가용성(availability)을 제공하는 데 필요한 복제(replication)를 구현할 때 매우 적합함,블록의 손상과 디스크 및 머신의 장애에 대처하기 위해 각 블록은 물리적으로 분리된 다수의 머신(보통 3개)에 복제됨
- 만일 하나의 블록을 이용할 수 없는 상황이 되면 다른 머신에 있는 복사본을 읽도록 클라이언트에 알려주면 됨
- 네임노드와 데이터노드
- HDFS 클러스터는 마스터-워커 패턴으로 동작하는 두 종류의 노드, 마스터인 하나의 네임노드와 워커인 여러 개의 데이터노드로 구성되어 있음, 네임노드는 파일시스템의 네임스페이스를 관리함
- 네임노드는 파일시스템 트리와 그 트리에 포함된 모든 파일과 디렉터리에 대한 메타데이터를 유지함 , 네임스페이스 이미지와 에디트 로그라는 두 종류의 파일로 로컬 디스크에 영속적으로 저장됨, 파일에 속한 모든 블록이 어느 데이터노드에 있는지 파악하고 있음
- HDFS 클라이언트는 사용자를 대신해서 네임노드와 데이터노드 사이에서 통신하고 파일시스템에 접근함
- 네임노드의 장애복구 기능
- 파일시스템의 메타데이터를 지속적인 상태로 보존하기 위해 파일로 백업하는 것, 네임노드가 다수의 파일시스템에 영구적인 상태를 저장하도록 하둡을 구성할 수 있음, 백업 작업은 동기화되고 원자적으로 실행됨, 주로 권장하는 방법은 로컬 디스크와 원격의 NFS 마운트를 두 곳에 동시에 백업하는 것
- 보조 네임노드(secondary namenode)를 운영하는 것, 에디트 로그가 너무 커지지 않도록 주기적으로 네임스페이스 이미지를 에디트 로그와 병합하여 새로운 네임스페이스 이미지를 만드는 것, 주 네임노드에 장애가 발생할 것을 대비해서 네임스페이스 이미지의 복제본을 보관하는 역할을 함
- 블록 캐싱
- 오프힙(off-heap, 자바 힙 외부에서 관리되는) 블록 캐시라는 데이터노드의 메모리에 명시적으로 캐싱할 수 있음
- 조인을 할 때 작은 룩업 테이블을 캐싱하는 것은 좋은 활용사례임
- 사용자나 애플리케이션은 캐시 풀(cache pool)에 캐시 지시자(cache directive)를 추가하여 특정 파일을 캐싱하도록 명령할 수 있음, 캐시 풀은 캐시 권한이나 자원의 용도를 관리하는 관리 그룹의 역할을 맡음
- 블록
- HDFS 패더레이션
- HDFS 페더레이션을 적용하면 각 네임노드는 네임스페이스의 메타데이터를 구성하는 네임스페이스 볼륨과 네임스페이스에 포함된 파일의 전체 블록을 보관하는 블록 풀을 관리함
- HDFS 고가용성
- 네임노드는 여전히 단일 고장점(single point of failure - SPOF), 네임노드에 장애가 발생하면 맵리듀스 잡을 포함하여 모든 클라이언트가 파일을 읽거나 쓰거나 조회할 수 없게 됨, 네임노드는 메타데이터와 파일 블록의 매핑 정보를 보관하는 유일한 저장소이기 때문
- 새로운 네임노드는 네임스페이스 이미지를 메모리에 로드하고 -> 에디트 로그를 갱신하고 -> 전체 데이터노드에서 충분한 블록 리포트를 받아 안전 모드를 벗어날 때까지 그 어떤 요청도 처리하지 못함
- HDFS 고가용성(high availability -HA)을 지원함, 고가용성은 활성대기상태로 설정된 한 쌍의 네임노드로 구현됨, 활성네임노드에 장애가 발생하면 대기 네임노드가 그 역할을 이어받아 큰 중단없이 클라이언트의 요청을 처리함
- 장애복구와 펜싱
- 대기 네임노드를 활성화시키는 전환 작업은 장애복구 컨트롤러라는 새로운 객체로 관리됨
- 장애복구는 정기적인 유지관리를 위해 관리자가 수동으로 초기화할 수 있음
- 우아한 장애복구(graceful failover) - 자애복구 컨트롤러는 두 개의 네임노드가 서로 역할을 바꾸게 하는 방법으로 전환 순서를 제어할 수 있음
- 인터페이스
- HTTP
- HTTP로 HDFS에 접근하는 두 가지 방식
- 클라이언트의 HTTP 요청을 HDFS 데몬이 직접 처리하는 방식 - 네임노드와 데이터노드에 내장된 웹 서버가 WebHDFS의 말단으로 적용함
- 클라이언트 대신 DistributedFileSystem API로 HDFS에 접근하는 프록시를 경유하는 방식 - 하나 또는 그 이상의 독립(standalone) 프록시 서버를 통하는 것, 프록시 서버는 상태를 저장할 필요가 없으므로 표준 로드 밸런서를 사용해도 괜찮음, 클러스터의 모든 트래픽은 프록시를 경유하므로 클라이언트는 네임노드와 데이터노드에 직접 접근할 필요가 없음, 프록시를 통하면 엄격한 방화벽이나 대역폭 제한 정책을 적용하기 쉬움, 프록시를 통한 방식은 서로 다른 데이터 센터에 있는 하둡 클러스터 사이의 데이터 전송이나 외부 네트워크에 있는 클라우드에서 운영되는 하둡 클러스터에 접근할 때 일반적으로 이용되는 방법
- HTTP로 HDFS에 접근하는 두 가지 방식
- C
- 자바 FileSystem 인터페이스를 모방한 libhdfs라는 C 라이브러리를 제공함
- libhdfs는 자바 파일시스템 클라이언트를 호출하기 위해 자바 네이티브 인터페이스(JNI)를 사용함
- NFS
- NFSv3 게이트웨이를 이용하면 로컬 클라이언트 파일시스템에 HDFS를 마운트할 수 있음
- 파일시스템을 다루는 ls나 cat 같은 Unix 유틸리티를 이용할 수 있으며, 파일 업로드 및 일반적인 프로그래밍 언어에서 파일시스템을 다루는 POSIX 라이브러리도 사용할 수 있음
- FUSE
- Filesystem in Userspace (사용자 공간에서의 파일시스템)로, 사용자 공간과 유닉스 파일시스템을 통합한 파일시스템을 지원함
- HTTP
- 하둡의 클러스터 자원 관리 시스템, 클러스터의 자원을 요청하고 사용하기 위해 API를 제공함
- 맵리듀스, 스파크 등과 같은 분산 컴퓨팅 프레임워크는 클러스터 계산 계층(YARN)과 클러스터 저장 계층(HDFS와 HBase) 위에서 YARN 애플리케이션을 실행함
- 리소스 매니저와 노드매니저 등 두가지 유형의 장기 실행 데몬을 통해 핵심 서비스를 제공함
- 클러스터에서 유일한 리소스 매니저는 클러스터 전체 자원의 사용량을 관리함
- 모든 머신에서 실행되는 노드 매니저는 컨테이너를 구동하고 모니터링하는 역할을 맡음
- 자원 요청
- 분산 데이터 처리 알고리즘에서 클러스터의 네트워크 대역폭을 효율적으로 활용하기 위해서는 지역성을 보장하는 것이 가장 중요함
- YARN은 특정 애플리케이션이 호출한 컨테이너에 대해 지역성 제약을 규정하는 것을 허용함, 지역성 제약은 특정 노드나 랙 또는 클러스터의 다른 곳(외부 랙)에서 컨테이너를 요청할 때 사용됨
- 애플리케이션 수명
- 실행 시간 보다는 사용자가 실행하는 잡의 방식에 따라 애플리케이션을 분리하는 것이 좋음
- 사용자의 잡 당 하나의 애플리케이션이 실행되는 방식으로, 맵리듀스 잡이 여기에 속함
- 워크플로나 사용자의 잡 세션(잡은 서로 관련이 없을 수도 있음)당 하나의 애플리케이션이 실행되는 방식, 첫 번째 유형보다 훨씬 더 효율적, 순차적으로 실행되는 잡이 동일한 컨테이너를 재사용할 수 있기 때문, 잡 사이에 공유 데이터를 캐싱할 수 있는 큰 장점도 있음, 사례로는 스파크
- 서로 다른 사용자들이 공유할 수 있는 장기 실행 애플리케이션, 일종의 코디네이션 역할을 수행함, 아파치 슬라이더는 클러스터에서 다양한 애플리케이션을 구동시키는 장기 실행 애플리케이션 마스터를 가지고 있응, 임팔라는 여러 임팔라 데몬이 클러스터 자원을 요청할 수 있도록 프록시 애플리케이션을 제공함
- 실행 시간 보다는 사용자가 실행하는 잡의 방식에 따라 애플리케이션을 분리하는 것이 좋음
- YARN 애플리케이션 만들기
- 잡의 방향성 비순환 그래프(DAG)를 실행하고 싶으면 스파크나 테즈가 더 작합함, 스트리밍 처리는 스파크, 쌈자 또는 스톰을 사용하는 것이 좋음
- 아파치 슬라이더는 기존의 분산 애플리케이션을 YARN 위에서 실행하도록 해줌
- 아파치 트윌(Apache Twill)
- 슬라이더와 비슷하지만 YARN에서 실행되는 분산 애플리케이션을 개발할 수 있는 간단한 프로그래밍 모델을추가로 제공함
- 자바 Runnable 객체를 확장한 클러스터 프로세스를 정의한 후 클러스터의 YARN 컨테이너에서 이를 실행하는 기능을 제공함
- 실시간 로깅(runnalbes의 로그 이벤트를 클라이언트에 스트리밍으로 돌려줌)과 명령 메시지(클라이언트에서 runnables 전송) 기능 등을 제공함
- 분산 쉘(distributed shell) - 복잡한 스케줄링 요구사항이 있는 애플리케이션
- 클라이언트 또는 애플리케이션 마스터가 YARN 데몬과 통신하기 위해 YARN의 클라이언트 API를 어떻게 사용하는지 잘 보여주고 있음
- YARN과 맵리듀스1의 차이점
- 맵리듀스 1에는 잡의 실행과정을 제어하는 하나의 잡트래커와 하나 이상의 태스크트래커등 두 종류의 데몬이 있음
- 잡트래커
- 여러 태스크트래커에서 실행되는 태스크를 스케줄링함으로써 시스템에서 실행되는 모든 잡을 조율함
- 맵리듀스 1에서 잡 스케줄링(태스크와 태스크트래커를 연결)과 태스크 진행 모니터링(태스크를 추적하고, 실패하거나 느린 태스크를 다시 시작하고, 전체 카운터를 유지하는 방법으로 태스크 장부(bookeeping)을 맡고 있음, 반면 YARN은 이러한 역할을 분리된 객체인 리소스 매니저와 애플리케이션 마스터(맵리듀스 잡당 하나)를 통해 처리함
- 완료된 잡에 대한 잡 이력을 저장하는 역할을 맡음, 잡트래커의 부하를 줄이기 위해 별도의 데몬인 히스토리 서버를 통해 수행될 수도 있음, YARN에서 이와 동일한 역할은 애플리케이션의 이력을 저장하는 타임라인 서버가 맡고 있음
- 태스크트래커
- 태스크를 실행하고 진행 상황을 잡트래커에 전송하기 때문에 잡트래커는 각 잡의 전체적인 진행 상황을 파악할 수 있음
- 맵리듀스1과 YARN 컴포넌트의 비교
- 잡트래커 - 리소스 매니저, 애플리케이션 마스터, 타임라인 서버
- 태스크트래커 - 노드 매니저
- 슬롯 - 컨테이너
- YARN을 사용하여 얻을 수 있는 이익
- 확장성
- 맵 리듀스 1보다 큰 클러스터에서 실행될 수 있음
- 가용성
- 고가용성(high availability - HA)은 서비스 데몬에 문제가 발생했을 때 서비스에 필요한 작업을 다른 데몬이 이어받을 수 있도록 상태 정보를 항상 복사해두는 방법으로 구현함
- 효율성
- 멀티테넌시(다중 사용자)
- 하둡이 맵리듀스를 뛰어넘어 다양한 분산 애플리케이션을 수용할 수 있다는 것
- 확장성
- YARN 스케줄링
- 스케줄러 옵션
- FIFO, 캐퍼시티(가용량), 페어(균등) 스케줄러를 제공함
- FIFO
- 애플리케이션을 큐에 하나씩 넣고 제출된 순서에 따라 순차적으로 실행함(선입선출 방식), 큐에 처음으로 들어온 애플리케이션 요청을 먼저 할당하고, 이 요청을 처리한 후 큐에 있는 다음 애플리케이션 요청을 처리하는 방식으로 순차적으로 실행함
- 공유 클러스터 환경에서는 적합하지 않음, 대형 애플리케이션이 수행될 때는클러스터의 모든 자원을 점유해버릴 수 있기 때문에 다른 애플리케이션은 자기 차례가 올때 까지 계속 대기해야함, 다른 두 스케줄러는 장시간 수행되는 잡을 계속 처리하는 동시에 작은 비정형 질의도 중간에 실행하여 적당한 시간 내에 사용자가 결과를 얻을 수 있도록 허용함
- 캐퍼시티(Capacity)
- 작은 잡을 제출되는 즉시 분리된 전용 큐에서 처리함
- 물론 해당 큐는 잡을 위한 자원을 미리 예약해두기 때문에 전체 클러스터의 효율성은 떨어짐, 또한 대형 잡은 FIFO 스케줄러보다 늦게 끝나게 됨
- 회사의 조직 체계에 맞게 하둡 클러스터를 공유할 수 있음, 각 조직은 전체 클러스터의 지정된 가용량을 미리 할당받음, 각 조직은 분리된 전용 큐를 가지며 클러스터 가용량의 지정된 부분을 사용하도록 설정할 수 있음
- 페어(Fair)
- 실행 중인 모든 잡의 자원을 동적으로 분배하기 때문에 미리 자원의 가용량을 예약할 필요가 없음, 대형 잡이 먼저 시작되면 이때는 실행 중인 잡이 하나밖에 없기 때문에 클러스터의 모든 자원을 얻을 수 있음
- 대형 잡이 실행되는 도중에 작은 잡이 추가로 시작되면 페어 스케줄러는 클러스터 자원의 절반을 이 잡에 할당함, 각 잡은 클러스터의 자원을 공평하게 사용할 수 있게 됨
- 실행 중인 모든 애플리케이션에 동일하게 자원을 할당함
- 스케줄러 옵션
- 압축
- 파일 압축은 파일 저장 공간을 줄이고, 네트워크 또는 디스크로부터 데이터 전송을 고속화할 수 있는 두 가지 커다란 이점이 있음
- 압축 포맷의 요약
- 압축 포맷 - 도구 - 알고리즘 - 파일 확장명 - 분할 가능
- DEFLATE - N/A - DEFLATE - .deflate - No
- gzip - gzip - DEFLATE - .gz - No
- bzip2 - bzip2 - bzip2 - .bz2 - Yes
- LZO - lzop - LZO - .lzo - No
- LZ4 - N/A - LZ4 - .lz4 - No
- Snappy - N/A - Snappy - .snappy - No
- gzip은 일반적인 목적의 압축 도구고, 공간/시간 트레이드오프의 중앙에 위치함
- bzip2는 gzip보다 더 효율적으로 압축하지만 대신 더 느림, 압축 해제 속도는 압축 속도보다 더 빠르지만 여전히 다른 포맷에 비해 더 느림
- LZO, LZ4, Snappy 모두 속도에 최적화되었고 gzip보다 어느 정도 빠르지만 압축 효율 은 떨어짐
- 압축 포맷 사용
- 압축과 분할 모두를 지원하는 시퀀스 파일, 에이브로, ORCFile, 파케이 같은 컨테이너 파일 포맷을 사용하라, 보통 LZO, LZ4, Snappy와 같은 빠른 압축 형식이 적당함
- 상당히 느리긴 하지만 bzip2 같은 분할을 지원하는 압축 포맷을 사용하라, 또는 분할을 지원하기 위해 색인 될 수 있는 LZO 같은 포맷을 사용하라
- 애플리케이션에 파일을 청크로 분할하고, 지원되는 모든 압축 포맷(분할에 관계없이)을 사용하여 각 청크를 개별적으로 압축하라. 이 경우 압축된 청크가 거의 HDFS 블록 하나의 크기가 되도록 처크 크기를 선택해야 함
- 파일을 압축하지 말고 그냥 저장하라
- 직렬화(serialization)
- 네트워크 전송을 위해 구조화된 객체를 바이트 스트림으로 전환하는 과정
- 역직렬화(deserializaition) - 바이트 스트림을 일련의 구조화된 객체로 역전환하는 과정
- 직렬화는 프로세스 간 통신과 영속적인 저장소와 같은 분산 데이터 처리의 독특한 두 영역에서 나타남
- 하둡 시스템에서 노드 사이의 프로세스 간 통신은 원격 프로시저 호출(Remote Procedure Call(RPC))을 사용하여 구현됨
- RPC 직렬화 포맷이 유익한 이유
- 간결성
- 고속화
- 확장성
- 상호운용성
- 저장소 포맷은 간결하고(저장 공간의 효율적 사용을 위해), 빠르고(테라바이트 데이터를 읽고 쓰는 오버헤드를 최소화하기 위해), 확장 가능하고(예전 포맷으로 쓰인 데이터도 문제없이 읽기 위해), 상호운용(다양한 언어를 사용하여 영속적인 데이터를 읽고 쓰기 위해)할 수 있어야 함
- 맵리듀스 웹 UI
- 클러스터 메트릭스(Cluster Metrics) 부분에서 클러스터의 요약 정보를 볼 수 있음, 클러스터(그리고 다양한 상태)에서 현재 실행 중인 애플리케이션의 개수, 클러스터 가용 자원의 수량(전체 메모리 - Memory Total), 노드 매니저 정보가 포함되어 있음
- 메인 테이블은 클러스터에서 완료되었거나 현재 실행 중인 모든 애플리케이션을 보여줌, 특정 애플리케이션을 찾을 수 있도록 검색 창을 제공함
- 잡 히스토리
- 완료된 맵리듀스 잡에 대한 이벤트와 설정을 갖고 있음, 잡 히스토리는 잡을 실행한 사용자에게 유용한 정보를 제공하기 위해 잡의 성공 여부와 상관없이 보관함
- 잡 히스토리 파일은 1주일 동안 보관된 후 시스템에서 삭제됨
- 히스토리 로그는 잡, 태스크, 태스크 시도 이벤트를 JSON 형태의 파일로 저장함
- 맵리듀스 잡 페이지
- Tracking UI를 클릭하면 애플리케이션 마스터 웹 UI(완료된 애플리케이션은 히스토리 페이지)로 이동함
- Total 컬럼은 각 잡에 대해 맵과 리듀스 태스크의 전체 개수를 한 줄씩 보여줌, 태스크 상태를 Pending(대기 중), Running(실행 중), Complete(실행 성공)로 구분하여 보여줌
- 맵 또는 리듀스 태스크에 대해 실패했거나 죽은 태스크 시도의 전체 개수를 보여줌, 투기적 실행 중복(speculative execution duplicate), 태스크를 실행하던 노드의 죽음, 사용자의 강제 종료로 태스크 시도가 실패했을 때는 killed로 표시됨
- 하둡 로그
- 로그 - 주 사용자 - 설명
- 시스템 데몬 로그 - 관리자 - 각 하둡 데몬은 로그파일과 표준 출력과 에러를 결합한 파일을 생성함
- HDFS 감사 로그 - 관리자 - HDFS와 관련된 모든 요청에 대한 로그로, 기본적으로 사용하지 않음
- 맵리듀스 잡 히스토리 로그 - 사용자 - 잡을 실행하는 과정에 발생하는 이벤트(태스크 완료와 같은)로그
- 맵리듀스 태스크 로그 - 사용자 - 각 태스크 자식 프로세스는 log4j를 사용하는 로그 파일(syslog로 불리는), 표준 출력(stdout)으로 보낸 데이터 파일, 표준 에러(stderr)를 위한 파일을 생성함
- YARN은 완료된 애플리케이션의 모든 태스크 로그를 가져온 후 병합하여 HDFS에 있는 기록 보관용 컨테이너 파일에 저장하는 로그 통합(log aggregation) 서비스를 제공함
- 로그 - 주 사용자 - 설명
- 원격디버깅
- 로컬에서 실패를 재현하기
- 태스크 실패를 일으키는 파일을 로컬에 내려받은 후 로컬에서 잡을 실행하면 로컬에서 문제를 재현할 수 있음, 가능하면 자바의 VisualVM과 같은 디버거를 사용하라
- JVM 디버깅 옵션 사용하기
- 실패의 주된 이유는 태스크 JVM의 자바 메모리 부족 때문, jhat이나 이클립스 메모리 분석기(Eclipse Memory Analyzer)와 같은 도구로 사후 분석이 가능한 힙 덤프를 생성
- 태스크 프로파일링 사용하기
- 자바 프로파일러는 JVM에 대한 상당한 통찰력을 제공하며, 하둡은 잡의 일부 태스크에 대한 프로파일링 기법을 제공함
- 사후 분석을 위해서는 실패한 태스크 시도의 중간 파일을 보관하는 것이 유용함
- 로컬에서 실패를 재현하기
- 잡 튜닝하기
- 성능 문제와 관련이 있는 하둡 특유의 유력 용의자(usal suspect)가 있음, 태스크 수준에서 프로파일링이나 최적화를 시도하기 전에 점검 목록을 순서대로 실행해 보는것이 좋음
- 매퍼 수 - 매퍼가 얼마나 오랫동안 수행되고 있는가?
- 리듀서 수 - 두 개 이상의 리듀서를 사용 중인지 확인해보라
- 컴바이너 - 셔플을 통해 보내지는 데이터양을 줄이기 위해 컴바이너를 활용할 수 있는지 확인해보라
- 중간 데이터 압축 - 맵 출력을 압축하면 잡 실행 시간을 거의 대부분 줄일 수 있음
- 커스텀 직렬화 - 커스텀 Writable 객체나 비교기(comparator)를 사용하고 있다면 RawComparator를 구현했는지 반드시 확인해라
- 셔플 튜닝 - 맵리듀스 셔플은 메모리 관리를 위해 대략 12개정도의 튜닝 인자를 제공하는데, 이는 성능을 조금이라도 더 향상시키는 데 도움을 줄 수 있음
- 성능 문제와 관련이 있는 하둡 특유의 유력 용의자(usal suspect)가 있음, 태스크 수준에서 프로파일링이나 최적화를 시도하기 전에 점검 목록을 순서대로 실행해 보는것이 좋음
- 맵리듀스 작업 흐름
- 데이터 처리가 더 복잡해지면 복잡한 맵과 리듀스 함수를 만드는 것보다는 맵리듀스 잡을 더 많이 만드는 것이 더 좋은 방법, 잡을 복잡하게 만들기보다는 잡을 더 많이 만드는 것이 좋음
- 매우 복잡한 문제는 맵리듀스 대신 피그,하이브,캐스케이딩,크런치,스파크와 같은 고수준 언어를 사용하는 것이 좋음
- 맵리듀스잡으로 변환하는 작업을 하지 않아도 되므로 분석 작업에만 집중할 수 있다는 것
- 아파치 오지(Apache OOzie)
- 종속관계가 있는 여러 잡을 흐름에 따라 실행해주는 시스템
- 워크플로 엔진은 다른 형태의 하둡잡(맵리듀스, 피그, 하이브 등)을 구성하는 작업 흐름을 저장하고 실행하며, 코디네이터 엔진(coordinator engine)은 미리 정의된 일정과 데이터 가용성을 기반으로 워크플로 잡을 실행함.
- 오지는 확장 가능하도록 설계되었고 하둡 클러스터 내에 수천 개의 워크플로(수십 개의 연속적인 잡으로 구성된)를 시의 적절하게 실행하도록 관리함
- 오지는 실패한워크플로를 다시 실행할 때 성공한 부분에 대해서는 다시 실행하지 않기 때문에 효율적이며 따라서 시간 낭비도 없음
- 오지의 워크플로는 액션 노드(action node)와 제어흐름노드(control-flow node)로 이루어진 DAG
- 액션 노드는 HDFS에 저장된 파일을 옮기거나 맵리듀스, 스트리밍, 피그, 하이브 잡을 실행하거나 스쿱 임포트를 수행하거나 쉘 스크립트나 자바 프로그램을 실행하는 등 워크플로의 태스크를 수행함
- 제어흐름 노드는 조건부 로직(분기문)과 같은 구문을 통해 액션 사이의 워크플로 실행을 관장함
- 맵리듀스 잡 실행 상세분석
- 클라이언트 : 맵리듀스 잡을 제출함
- YARN 리소스 매니저 : 클러스터 상에 계산 리소스 할당을 제어함
- YARN 노드 매니저 : 클러스터의 각 머신에서 계산 컨테이너를 시작하고 모니터링함
- 맵리듀스 애플리케이션 마스터 : 맵리듀스 잡을 수행하는 각 태스크를 제어함, 애플리케이션 마스터와 맵리듀스 태스크는 컨테이너 내에서 실행되며, 리소스 매니저는 잡을 할당하고 노드 매니저는 태스크를 관리하는 역할을 맡음
- 분산 파일시스템 : 다른 단계 간에 잡 리소스 파일들을 공유하는 데 사용됨
- 실패
- 사용자 코드의 버그 때문에 프로세스가 강제로 죽거나 서버에 장애가 발생하는 일이 빈번함
- 태스크 실패
- 가장 흔한 실패의 유형은 맵 또는 리듀스 태스크 내 사용자 코드에서 런타임 예외를 던질 때
- 예외가 발생하면 태스크 JVM은 종료하기 전에 부모인 애플리케이션 마스터에 에러를 보고함, 이 에러는 최종적으로 사용자 로그에 기록됨
- 애플리케이션 마스터는 이 태스크 시도를 실패로 표시하고 해당 리소스를 다른 태스크에서 사용 가능하도록 컨테이너를 풀어줌
- 태스크 JVM이 갑작스럽게 종료하는 것인데, 아마도 맵리듀스 사용자 코드에의해 드러난 특정 상황으로 인해 JVM이 종료되는 JVM 버그, 이때 노드 매니저는 프로세스가 종료되었음을 알게 되고,이를 애플리케이션 마스터에 알려주어 해당 시도가 실패했다고 표시
- 행이 걸린(멈춘) 태스크는 다르게 처리됨
- 애프리케이션 마스터는 잠시 동안 진행 상황을 갱신받지 못함을 알게 되며 해당 태스크를 실패로 표시함
- 태스크 JVM 프로세스는 이 기간 후에 자동으로 강제 종료됨
- 태스크를 실패로 간주하는 타임아웃 기간은 보통 10분이고 잡 단위(또는 클러스터 단위)로 mapreduce.task.timeout 속성에 밀리초 단위의 값을 설정할 수 있음
- 타임아웃을 0으로 설정하면 타임아웃을 비활성화하며 따라서 실행 시간이 긴 태스크는 절대로 실패로 표시되지 않음, 행이 걸려 멈춘 태스크는 자신의 컨테이너를 결코 해제하지 않을 것이며 시간이 지남에 따라 클러스터를 느리게 만드는 결과를 초래함
- 태스크가 주기적으로 진행 상황을 확실히 보고하도록 하는것이 좋음
- 노드 매니저 실패
- 노드 매니저가 크래시에 의해 실패하거나 굉장히 느리게 수행 중이라면 리소스 매니저에 하트비트 전송을 중단할 것(혹은 굉장히 드물게 전송함)
- 셔플과 정렬
- 맵리듀스는 모든 리듀서의 입력이 키를 기준으로 정렬되는 것을 확실히 보장함
- 정렬히 수행하고 맵의 출력을 리듀서의 입력으로 전송하는 과정을 셔플이라고 함
- 스필(spill) : 각 파티션별 메모리 버퍼를 디스크에 한번에 쓰는 것을 말함
- 투기적 실행
- 태스크의 투기적 실행(speculative execution) : 하둡은 느린 태스크를 진단하거나 고치려 하지 않는 대신 태스크 수행이 예상했떤 것보다 더 느린 상황을 감지하여 또 다른 동일한 예비 태스크를 실행함
- 카운터
- 내장 카운터
- 하둡은 모든 잡에 대해 내장 카운터를 제공하며 이들은 다양한 메트릭(지표)을 알려줌
- 맵리듀스 태스크 카운터
- 파일시스템 카운터
- FileInputFormat 카운터
- FileOutputFormat 카운터
- 잡 카운터
- 내장 카운터 그룹
- 태스크 카운터
- 태스크가 진행되면서 갱신됨
- 각 태스크가 실행될 때 해당 태스크에 대한 정보를 수집한 후 잡의 모든 태스크에 대한 값을 취합하여 최종 결과를 알려줌
- 각 태스크 시행마다 관리되고 주기적으로 애플리케이션 마스터에 전송되므로 결국 전역적으로 수집됨
- 잡 카운터
- 잡이 진행되면서 갱신됨
- 태스크 카운터
- 내장 카운터
- 조인
- 매퍼에 의해 조인이 수행되면 맵-사이즈 조인(map_side join), 리듀서에 의해 수행되면 리듀스-사이드 조인(reduce-side join)
- 맵-사이드 조인
- 대용량 입력에 대한 맵-사이드 조인은 데이터가 맵 함수에 도달하기 전에 조인이 수행됨, 각 맵의 입력이 특별한 방식으로 분할되고 정렬되어야 함
- 각 입력 데이터 셋은 반드시 동일한 개수의 파티션으로 분할되어야 하며, 각 원본은 동일한 조인키로 정렬되어 있어야함, 특정 키에 대한 모든 레코드는 동일한 파티션에 존재해야 함
- 동일한 개수의 리듀서, 동일한 키, 분리되지 않는 추력 파일(예를 들면 HDFS 블록보다 작거나 gzip으로 압축된 파일)을 가진 여러 잡의 출력을 조이하는 데 사용할 수 있음
- 리듀스-사이드 조인
- 입력 데이터셋을 일부러 특별한 방식으로 구조화할 피룡가 없기 때문, 두 데이터셋 모두 맵리듀스의 셔플 단계를 거쳐야 한다는 비효율적인 면이 존재함
- 매퍼가 소스에 따라 각 레코드에 태그를 붙이고 조인키를 맵 출력키로 사용함으로써 동일한 키를 가진 레코드는 같은 리듀서와 함께 모이게 된다는 것
- 다중 입력
- MultipleInputs 클래스를 사용하여 각 입력 원본을 분석하고 태깅하는 코드를 별도로 작성하는 것이 더 편함
- 2차 정렬
- 다중 입력
- 사이드 데이터 분배
- 사이드 데이터는 잡이 주요 데이터셋을 처리하는 데 필요한 별도의 읽기 전용 데이터
- 잡 환경 설정 사용
- Configuration(이전 맵리듀스 API에서는 JobConf)의 다양한 setter 메서드를 사용하여 잡 환경 설정에 임의의 키-값 쌍을 설정할 수 있음, 작은 크기의 메타데이터를 각 태스크에 전달할 때 매우 유용함
- 수 킬로바이트가 넘는 데이터를 전송할 때는 적합하지 않음, 맵리듀스 컴포넌트의 메모리 사용량에 부하를 주기 때문
- 클라이언트, 애플리케이션 마스터, 태스크 JVM은 매번 잡 환경 설정을 읽으며 전혀 사용되지 않는 요소를 포함한 모든 요소를 메모리에 로드함
- 분산 캐시
- 실행 시점에 파일과 아카이브의 사본을 태스크 노드에 복사하여 이를 이용하도록 해주는 서비스, 네트워크 대역폭을 줄이기 위해 파일은 잡 단위로 특정 노드에 복사됨
- 하둡 클러스터를 구축하는 방법은 매우 다양함, 자체적으로 구축하는 방법과 하드웨어를 임대하거나 클라우드 호스팅 하는 방식으로 제공되는 하둡 서비스를 이용하는 방법
- 자체적으로 구축하는 방법의 몇 가지 설치 옵션
- 아파치 타르볼
- 아파치 하둡 프로젝트 및 관련 프로젝트는 각 릴리즈별로 바이너리 타르볼과 소스를 제공함, 사용자에게 높은 유연성을 제공하지만 사용자가 설치 파일, 설정 파일, 로그 파일의 위치를 직업 결정해야 하고 정확한 권한 설정을 해야 하는 등 상당한 노력이 필요함
- 패키지
- 아파치 빅톱 프로젝트와 하둡 벤더(클라우데라,호튼웍스 등)는 RPM과 데비안 패키지를 제공함, 일관된 파일시스템 레이아웃을 제공하며 스택 방식(함께 잘 작동하는 하둡과 라이브 버전을 알 수 있음)의 호환성 테스트를 거쳤음, 퍼펫(Puppet)과 같은 설정 관리 도구를 함께 사용할 수 있음
- 하둡 클러스터 관리 도구
- 클라우데라 매니저와 아파치 암바리는 전체 수명 주기에 걸쳐 하둡 클러스터의 설치 및 관리 기능을 제공하는 전용 도구
- 간단한 웹 사용자 인터페이스를 제공하며, 하둡 클러스터를 구축하려는 사용자와 운영자에게 권장되는 방식
- 아파치 타르볼
- 클러스터 명세
- 클러스터 규모 결정
- 마스터 노드 시나리오
- HDFS와 YARN은 마스터 데몬을 활성-대기 쌍으로 실행할 수 있는 설정(고가용성)을 지원함
- 활성 마스터에 장애가 발생하면 별도의 하드웨어에서 구동되는 대기 마스터가 활성 마스터의 역할을 대신 수행하므로 무중단 서비스가 가능함, HDFS에 고가용성 설정을 하면 대기 네임노드가 기존에 보조 네임노드가 맡았던 체크포인트 작업을 대신 수행함
- 마스터 노드 시나리오
- 클러스터 규모 결정
- 시스템 로그파일
- 컴퓨터에서 실행 중인 각 하둡 데몬은 두 개의 로그 파일을 생성함
- log4j를 통해 출력되는 로그파일
- 파일의 확장자는 .log, 애플리케이션의 로그 메시지는 대부분 이곳에 기록되므로 문제가 발생하면 제일 먼저 살펴볼 필요가 있음
- 표준 하둡 log4j 설정은 로그파일의 순환을 위해 일일 순환 파일 추가자(appender)를 사용함
- 하둡은 오래된 로그파일을 자동으로 삭제하지 않기 때문에 로컬 노드에 저장 공간이 모자라지 않도록 로그파일을 주기적으로 삭제하거나 보관하는 계획을 세워야 함
- 표준 출력과 표준 에러 로그가 함께 기록되는 로그 파일
- .out이며, 하둡은 log4j를 이용하여 로그를 저장하기 때문에 보통 비어 있거나 적은 양의 로그만 기록됨, 데몬이 재시작될 때만 순환되고 최근 다섯 개의 로그만 보관함
- 두 종류의 로그파일의 이름은 데몬을 수행하는 사용자 이름, 데몬 이름, 머신의 호스트명의 조합
- log4j를 통해 출력되는 로그파일
- 컴퓨터에서 실행 중인 각 하둡 데몬은 두 개의 로그 파일을 생성함
- 중요한 하둡 데몬 속성
- core-site.xml
- hdfs-site.yml
- yarn-site.xml
- 보안
- 커버로스와 하둡
- 커버로스를 사용할 때 클라이언트가 이 서비스를 이용하려면 각 단계에서 서버와의 메시지 교환을 수반하는 다음 세 단계를 거쳐야 함
- 인증 - 클라이언트는 인증 서버에 자신을 인증함, 시간 정보가 포함된 티켓-승인 티켓(Ticket-Granting Ticket -TGT)을 수신함
- 권한 부여 - 클라이언트는 TGT를 이용하여 티켓 승인 서버에 서비스 티켓을 요청함
- 서비스 요청 - 클라이언트는 서비스 티켓을 이용하여 클라이언트가 사용할 서비스를 제공하는 서버에 자신을 인증함, 하둡의 경우 이 서버는 네임노드나 리소스 매니저가 될 것
- 인증 서버와 함께 티켓 승인 서버는 키 분배 센터(Key Distriubution Center -KDC)를 구성함
- 커버로스를 사용할 때 클라이언트가 이 서비스를 이용하려면 각 단계에서 서버와의 메시지 교환을 수반하는 다음 세 단계를 거쳐야 함
- 커버로스와 하둡
- 데이터노드 블록 스캐너
- 모든 데이터노드는 블록 스캐너(block scanner)를 실행하여 데이터노드에 저장된 모든 블록을 주기적으로 점검함, 클라이언트가 블록을 읽기 전에 문제가 있는 블록을 탐지하고 수리할 수 있음
- 블록 스캐너는 점검할 블록의 목록을 관리하며 체크섬 오류를 찾기 위해 모든 블록을 확인함, 스캐너는 데이터노드의 디스크 대역폭을 유지하기 위해 조절 메커니즘(throttling mechansim)을 사용함
- 밸런서
- 시간이 지남에 따라 데이터노드 사이의 블록의 분포는 불균형 상태가 될 수 있음. 불균형 상태의 클러스터는 맵리듀의 지역성(locality)에 영향을 받게 되므로 자주 사용되는 데이터노드에 큰 부하를 주게 됨, 불균형 상태가 되지 않도록 해야 함
- 밸런서 프로그램은 블록을 재분배하기 위해 사용률이 높은 데이터노드의 블록을 사용률이 낮은 데이터노드로 옮기는 하둡 데몬
- 모니터링
- 모니터링의 목적은 클러스터가 기대하는 수준의 서비스를 제공하지 못하는 시점을 감지하는 것
- 주 네임노드, 보조 네임노드, 리소스 매니저와 같은 마스터 데몬이 가장 중요한 모니터링 대상임, 대형 클러스터에서는 특히 데이터노드와 노드 매니저에 장애가 발생할 수 있기 때문에 일부 노드의 장애에 항상 대처할 수 있도록 추가 가용량을 제공해야 함
- 로깅
- 모든 하둡 데몬은 로그파일을 생성하기 때문에 시스템에 어떤 일이 일어났는지 파악하는 데 매우 유용함
- 로그 수준 설정
- 문제를 파악할 때 시스템의 특정 컴포넌트의 로그 수준을 임시로 변경할 수 있으며 매우 편리함
- 하둡 데몬은 log4j 로그파일(각 데몬의 웹 UI의 /logLevel에서 찾을 수 있음)의 로그 수준을 변경할 수 있는 웹 페이지를 제공함
- 메트릭과 JMX
- 하둡 데몬은 메트릭으로 알려진 이벤트와 측정치에 대한 정보를 수집함, 데이터노드는 기록된 바이트 수, 복제된 블록 수, 클라이언트의 읽기 요청 수(로컬과 원격 포함) 등의 메트릭을 수집함
- 메트릭과 카운터의 차이점
- 수집하는 정보의 범위, 메트릭은 하둡 데몬이 수집하지만 카운터는 맵리듀스 태스크가 수집하고 전체 잡을 위해 집계됨, 서비스의 대상도 다른데, 메트릭은 관리자, 카운터는 맵리듀스 사용자를 위해 정보를 수집함
- 카운터는 맵리듀스의 기능, 맵리듀스 시스템은 태스크 JVM에서 생성된 카운터의 값을 애플리케이션 마스터로 전달하고 최종적으로 맵리듀스잡을 실행한 클라이언트로 전달되는 것을 보장함
- 유지 보수
- 메타데이터 백업
- 네임노드의 영속적인 메타데이터가 손실되거나 훼손되면 전체 파일시스템을 사용할 수 없게 됨
- 데이터 백업
- HDFS는 관리자와 사용자가 파일시스템의 스냅숏을 생성하는 것을 지원함, 스냅숏은 특정 시점의 파일시스템 서브트리의 읽기 전용 사본, 스냅숀은 데이터를 복사하지 않기 때문에 매우 효율적으로 동작함
- 스냅숏은 파일의 메타데이터와 블록의 목록만 저장함, 스냅숏을 이용하면 스냅숏을 생성한 특정 시점의 파일시스템을 완전히 되돌리 수 있음
- 스냅숏은 데이터 백업을 대체하는 것이 아니라 사용자의 실수로 삭제된 파일을 특정 시점으로 복구하는 데 유용한 도구, 주기적으로 스냅숏을 찍고 시기에 따라 일정 기간 동안 보관하도록 정책을 수립할 수 있음
- 메타데이터 백업
- 노드의 추가와 퇴역
- 새로운 노드 추가하기
- hdfs-site.xml 파일에 네임노드를, yarn-site.xml 파일에 리소스 매니저를 지정하여 환경을 구성하고 데이터노드와 리소스 매니저 데몬을 시작하여 새로운 노드를 간단히 추가할 수 있음, 하지만 추가를 허용하는 노드 목록을 따로 만들어두는 것이 제일 좋은 방식
- 새로운 노드 추가하기
- 아파치 에이브로는 특정 언어에 종속되지 않는 언어 중립적 데이터 직렬화 시스템, 하둡 Writable (직렬화 방식)의 주요 단점인 언어 이식성(language portability)을 해결하기 위해 만든 프로젝트
- 아파치 쓰리프트나 구글의 프로토콜 버퍼와 같은 다른 직렬화 시스템과 차별화된 특성을 가지고 있음, 에이브로의 데이터는 다른 시스템과 비슷하게 언어 독립 스키마로 기술됨, 에이브로에서 코드를 생성하는 것은 선택사항
- 에이브로의 스키마는 보통 JSON으로 작성하며, 데이터는 바이너리 포맷으로 인코딩함
- 스키마 해석(schema resolution)기능이 있음, 스키마 변형(schema evolution) 메커니즘 - 신중하게 정의된 어떠한 제약조건에서도 데이터를 읽는 데 사용되는 스키마와 데이터를 쓰는 데 사용되는 스키마가 같지 않아도 됨
- 하둡의 시퀀스 파일과 유사한 연속적 객체를 위한 객체 컨테이너 포맷(object container foramt)을 제공함
- 에이브로 데이터 파일은 스키마가 저장된 메타데이터 섹션을 포함하고 있어 자신을 설명하는 파일이 됨, 파일은 압축과 분할 기능을 제공함
- 에이브로 자료형과 스키마
- 모든 프로그래밍 언어는 런타임 직전에 스키마를 결정할 수 없을 때 동적 매핑을 사용함, 자바에서는 이것을 제너릭 매핑(Generic mapping)이라고 함
- 자바에서는 코드 생성을 구체적 매핑(Specific mapping)이라고 하며, 데이터를 읽거나 쓰기 전에 스키마 사본이 있을 때 유용한 최적화 방식
- 자바는 리플렉션을 이용하여 에이브로 자료형을 기존의 자바 자료형으로 매핑하는 리플렉트 매핑(Reflect mapping)을 지원함, 제너릭이나 구체적 매핑에 비해 느리지만 에이브로가 자동으로 스키마를 유추하기 때문에 자료형을 쉽게 정의할 수 있는 장점이 있음
- 에이브로 맵리듀스
- 에이브로 맵리듀스 API는 일반 하둡 맵리듀스 API와 두가지 차이점이 있음
- 에이브로 자바 자료형에 맞는 래퍼를 사용한다는 것
- 잡을 설정하는 데 AvroJob 클래스를 사용한다는 것, AvroJob 클래스는 입력, 맵 출력, 최종 출력 데이터에 대한 에이브로 스키마를 정의하는 데 편리함
- 에이브로 맵리듀스 API는 일반 하둡 맵리듀스 API와 두가지 차이점이 있음
- 중첩된 데이터를 효율적으로 저장할 수 있는 컬럼 기준 저장 포맷
- 컬럼 기준 포맷은 파일 크기와 쿼리 성능 측면 모두에서 효율성이 높은 장점이 있음, 동일한 컬럼의 값을 나란히 모아서 저장하기 때문에 인코딩 효율이 높음, 컬럼 기준 포맷의 파일 크기는 행 기반 포맷에 비해 일반적으로 작음
- 진정한 컬럼 기반 방식으로 중첩 구조의 데이터를 저장할 수 있다는 것 , 파케이 포맷을 지원하는 수많은 도구가 있다는 것
- 데이터 처리 컴포넌트(맵리듀스, 피그, 하이브, 캐스케이딩, 크런치, 스파크)는 대부분 파케이 포맷을 지원함 , 유연성은 인메모리 표현까지 확장됨
- 파케이 파일 포맷
- 파케이 파일은 헤더, 하나 이상의 블록, 꼬리말 순으로 구성됨
- 파케이 파일의 각 블록은 행 그룹을 저장함, 행 그룹은 행에 대한 컬럼 데이터를 포함한 컬럼 청크로 되어 있음, 각 컬럼 청크의 데이터는 페이지에 기록됨
- 델타 인코딩(값의 차이를 저장), 연속길이 인코딩(run-length - 동일한 값이 연속으로 나오면 그 값과 빈도를 저장), 사전 인코딩(dictionary - 값의 사전을 만들어 인코딩한 후 사전의 인덱스를 나타내는 정수로 그 값을 저장)을 비롯하여 압축률이 높은 다양한 인코딩을 지원함, 작은 몇개의 값을 한 바이트에 저장하여 공간을 절약하는 비트 패킹(bit packing)과 같은 기술도 적용할 수 있음
- 파케이 설정
- 블록 크기를 설정할 때 스캔 효율성과 메모리 사용률 사이의 트레이드오프 관계를 고려해야 함, 블록의 크기를 크게 하면 더 많은 행을 가지므로 순차 I/O의 성능을 높일 수 있어 효율적으로 스캔할 수 있음(각 컬럼 청크를 설정하는 부담을 줄임), 하지만 개별 블록의 읽고 쓸 때 모든 데이터가 메모리에 저장되어야 하기 때문에 너무 큰 블록을 사용하는 것은 한계가 있음
- 파케이 파일 쓰기와 읽기
- 다양한 도구와 컴포넌트로 파케이 파일 포맷을 쉽게 통합할 수 있는 장착형(pluggable) 인메모리 데이터 모델이 있음, 자바는 ReadSupport와 WriteSupport로 파케이 파일 포맷을 통합함
- 플룸은 이벤트 기반의 대용량 데이터를 하둡으로 수집하기 위해 개발됨, 다수의 웹 서버에서 로그파일을 수집하고 해당 파일의 로그 이벤트를 처리하기 위해 HDFS에 위치한 새로운 통합 파일로 옮기는 것은 플룸을 사용하는 전형적인 예
- 플룸을 사용하려면 플룸 에이전트를 실행해야 함, 플룸 에이전트는 채널로 연결된 소스와 싱크를 실행하는 장기 실행 자바 프로세스, 플룸에서는 소스는 이벤트를 만들고 이를 채널로 전달함, 채널은 싱크로 전송할 때까지 이벤트를 저장함, 소스-채널-싱크의 조합이 플룸의 기본 구성요소(building block)
- 분산형 토폴로지에서 실행되는 연결된 에이전트의 집합으로 구성됨, 시스템의 가장자리에 있는 에이전트(웹 서버에서 실행되는)는 데이터를 수집한 다음 이를 집계하는 에이전트로 전송하고 마지막으로 최종 목적지에 데이터를 저장함
- 트랜잭션과 신뢰성
- 플룸은 소스에서 채널까지와 채널에서 싱크까지의 전송을 보장하기 위해 분리된 트랜잭션을 사용함
- HDFS 싱크
- 플룸의 핵심은 대량의 데이터를 하둡 데이터 저장소에 전달하는 것
- 파티셔닝과 인터셉터
- 파티션을 사용하면 데이터의 일부만 질의할 때 특정 파티션에 국한된 데이터 처리가 가능함
- 플룸 이벤트 데이터는 주로 시간을 기준으로 파티셔닝됨, 프로세스를 주기적으로 실행하여 완료된 파티션으로 변환할 수 있음(예를 들면 중복 이벤트 제거하기 위해)
- 인터셉터(interceptor)는 전송 중인 이벤트의 내용을 수정하거나 삭제할 수 있는 컴포넌트, 인터셉터는 소스에 달려 있으며, 이벤트가 채널에 도착하기 전에 실행됨
- 파일 포맷
- 데이터를 저장할 때는 바이너리 포맷을 사용하는 것이 좋음, 텍스트 파일을 사용할 때보다 최종 파일의 크기가 더 작아지기 때문
- 분기(fan out)
- 하나의 소스에서 발생하는 이벤트를 여러 개의 채널로 전송하는 것을 뜻하는 용어
- 싱크 그룹
- 여러 개의 싱크를 마치 하나의 싱크처럼 처리하므로 장애 복구나 부하 분산에 활용할 수 있음, 두 번째 계층의 에이전트 중 하나가 작동하지 않아도 중단 없이 이벤트를 다른 두 번째 계층의 에이전트에 전송할 수 있고 이어서 HDFS에 저장할 수 있음
- HDFS는 수많은 소스의 로그와 데이터를 안정적으로 저장할 수 있음, 맵리듀스 프로그램은 다양한 비정형 데이터의 포맷을 파싱하여 적절한 정보를 추출하고 여러 데이터셋을 결합하여 우리가 원하는 결과를 얻을 수 있음
- 회사의 주요 데이터는 관계형 데이터베이스 관리 시스템(relational database management system - RDBMS)과 같은 구조적인 데이터 저장소에 주로 저장됨
- 아파치 스쿱은 구조화된 데이터 저장소에서 데이터를 추출해서 하둡으로 보내 처리할 수 있도록 해주는 오픈 소스 도구
- 스쿱2
- 스쿱 1은 명령행 도구고 자바 API를 제공하지 않았기 때문에 다른 프로그램에 내장하기 어려웠음, 스쿱 1의 모든 커넥터는 모든 출력 포맷에 대한 정의를 포함해야 하므로 새로운 커넥터를 작성하는 것은 매우 어려웠음
- 스쿱 2는 잡을 실행하는 서버 컴포넌트뿐만 아니라 명령행 인터페이스(command-line-interface - CLI), 웹 UI, REST API, 자바 API 등 다양한 클랑이언트를 제공함
- 스쿱 커넥터
- 스쿱은 대용량 데이터 전송 기능이 있는 외부 저장 시스템에 데이터를 임포트하고 익스포트하는 확장 프레임워크
- 스쿱 커넥터는 이 프레임워크를 사용하여 스쿱이 임포트와 익스포트 하게 해주는 모듈식 컴포넌트
- 아파치 피그를 이용하면 대용량 데이터셋을 더 높은 추상 수준으로 처리할 수 있음, 피그를 사용하면 다중값이나 중첩된 형태의 데이터 구조를 처리할 수 있고 데이터 변환도 쉽게 할 수 있음
- 데이터 흐름을 표현하기 위해 사용하는 피그 라틴 언어
- 피그 라틴 프로그램을 수행하는 실행 환경. 단일 JVM에서의 로컬 실행 환경과 하둡 클러스터 상의 분산 실행 환경을 지원함
- 피그 라틴 프로그램은 입력 데이터를 처리하여 출력 결과를 생성하는 일련의 연산(operation) 및 변환(transformation)으로 구성, 전체적으로 보면 각각의 연산은 데이터의 연속적인 흐름을 표현하며, 피그의 실행 환경은 이를 실행 가능한 표현으로 변환한 후 실제 수행함, 피그는 내부적으로 이러한 과정을 일련의 맵리듀스 잡으로 변환함
- 매퍼와 리듀서를 작성해서 코드를 컴파일하고 패키징한 후 잡을 실행하고 그 결과를 확인하려면 오랜 시간이 걸림, 컴파일과 패키징이 필요 없는 하둡 스트리밍 방식을 사용하더라도 마찬가지, 피그를 사용하면 콘솔 화면에서 대여섯 줄 정도의 피그 라틴 코드만 작성하면 수 테라바이트의 데이터를 곧바로 처리할 수 있음
- 처리 과정의 모든 부분(로딩, 저장, 필터링, 그룹핑, 조인)은 사용자 정의 함수(user-defined function - UDF)로 변경할 수 있음, 피그의 중첩 데이터 모델 위에서 동작하므로 피그의 연산자와 매우 긴밀히 통합
- 피그의 프로그램 실행
- 스크립트
- 피그 명령어가 포함된 스크립트 파일을 실행함
- 그런트
- 피그 명령어를 실행하는 대화형 쉘, 피그가 실행할 스크립트 파일을 지정하지 않았거나 -e 옵션을 사용하지 않았을 때 시작됨
- 내장형
- 자바에서 JDBC로 SQL 프로그램을 실행하는 것처럼 PigServer 클래스를 사용하면 자바에서 피그 프로그램을 실행할 수 있음
- 스크립트
- 그런트
- bash 쉘이나 다른 명령행 애플리케이션에서 주로 쓰는 GNU의 Readline과 같은 행 편집 기능이 있음
- 함수
- 평가 함수
- 하나 이상의 표현식을 받아 다른 표현식을 반환하는 함수
- 필터 함수
- 평가 함수의 특별한 종류로 논리적인 불린값을 반환함
- 로드 함수
- 외부 저장소의 데이터를 관계자에 로드하는 방법을 지정하는 함수
- 저장 함수
- 관계자의 내용을 외부 저장소에 저장하는 방법을 지정하는 함수
- 평가 함수
- 데이터 그룹과 조인
- 단편 복제(fragment replicate join) - 작은 입력 데이터를 모든 매퍼에 분산한 후 단편화된 대규모 관계자에 대해 인메모리 룩업 테이블을 이용하여 맵-사이드 조인을 수행함
- 하둡 기반의 데이터 웨어하우징 프레임워크로, 빠른 속도로 성장하는 페이스북의 소셜 네트워크에서 매일같이 생산되는 대량의 데이터를 관리하고 학습하기 위해 개발됨
- 하이브는 자바 프로그래밍 기술은 부족하지만 강력한 SQL 기술을 가진 분석가가 페이스북의 HDFS에 저장된 대량의 데이터를 분석할 수 있도록 개발됨
- SQL은 비즈니스 인텔리전스 분야의 도구에서 사용되는 공통 언어(lingua franca)이기 때문에(예를 들어 ODBC는 공통 인터페이스) 해당 분야의 상용 제품과 쉽게 통합할 수 있음
- 하이브 설치하기
- 하이브는 HDFS에 저장된 데이터(디렉터리/파일)에 구조(스키마)를 입히는 방식으로 데이터를 테이블로 구조화시킴, 테이블 스키마와 같은 메타데이터는 메타스토어라 불리는 데이터베이스에 저장됨
- 하이브 쉘
- HiveQL 명령어로 하이브와 상호작용하는 하이브의 기본 도구
- 하이브 설정하기
- 하이브는 하둡과 같이 xml 설정 파일을 사용하여 환경 설정을 함, 관련 파일은 hive-site.xml이고 하이브의 conf 디렉터리에 위치함
- 같은 디렉터리에 하이브가 보유하고 있는 속성과 기본값을 기록한 hive-default.xml 파일도 있음
- 실행 엔진
- 테즈와 스파크는 맵리듀스보다 더 높은 성능과 유연성을 제공하는 범용 방향성비순환 그래프(DAG-directed acyclic graph) 엔진, 잡의 임시 출력을 HDFS에 저장하는 맵리듀스와 달리 테즈와 스파크는 임시 출력을 로컬 디스크에 기록하거나 하이브 플래너의 요청으로 메모리에 저장하는 방식으로 복제 오버헤드를 피할수 있음
- 로깅
- 하이브의 에러 로그는 로컬 파일시스템의 ${java.io.tmpdir}/${user.name}/hive.log에서 찾을 수 있음, 환경 설정 문제나 다른 유형의 에러를 진단할 때 매우 유용함
- 로깅 설정 파일은 conf/hive-log4j.properties고, 로그 수준과 다른 로깅 관련 설정을 변경하고 싶으면 이 파일을 변경하면 됨
- 메타스토어
- 하이브 메타데이터의 핵심 저장소, 메타스토어는 서비스와 데이터 보관 저장소로 나뉨
- 내장형 메타 스토어(embedded metastore) 설정 - 메타데이터 서비스는 하이브 서비스와 동일한 JVM에서 실행되고 로컬 디스크에 저장되는 내장형 더비(Derby)데이터베이스 인스턴스를 포함함 , 내장형 더비 데이터베이스 인스턴스는 한번에 디스크에 위치한 데이터베이스 파일 하나에만 접근할 수 있음
- 로컬 메타스토어(local metastore) - 다중 세션, 즉 다중 사용자를 지원하는 방법은 독립형 데이터베이스를 사용하는 것
- 원격 메타스토어(remote metastore) - 하나 이상의 메타스토어 서버가 하이브 서비스와 별도의 프로세스로 실행됨, 데이터베이스 계층이 방화벽의 역할을 대신하고, 따라서 클라이언트는 데이터베이스 자격 증명을 더 이상 얻을 필요가 없기 때문에 관리성과 보안성이 더 높아짐
- 하이브 메타데이터의 핵심 저장소, 메타스토어는 서비스와 데이터 보관 저장소로 나뉨
- 읽기 스키마와 쓰기 스키마의 비교
- 쓰기 스키마(schema on write) - 전통적인 데이터베이스에서 테이블의 스키마는 데이터를 로드하는 시점에 검증됨, 로드 중인 데이터가 스키마에 부합되지 않으면 해당 데이터를 거부함, 데이버테이스 쓰는 시점에 떼이터의 스키마를 검증하기 때문
- 읽기 스키마(schema on read) - 하이브는 로드 시점이 아니라 쿼리를 실행할 때 그 데이터를 검증함
- 두 방식은 서로 상충 관계(trade-off) ,읽기 스키마는 데이터베이스 내부 형식으로 데이터를 읽거나 파싱하거나 디스크에 직렬화할 필요가 없기 때문에 초기에 매우 빠른 속도로 데이터를 로드할 수 있음, 로드 조작을 위해서는 단순히 파일을 복사하거나 이동하기만 하면 됨
- 쓰기 스키마는 데이터베이스가 컬럼 단위의 데이터 색인과 압축을 제공하기 때문에 더 빠르게 쿼리를 수행할 수 있음, 상대적으로 데이터베이스에 데이터를 로드하는 시간은 더 오래 걸림, 더욱이 쿼리가 정해지지 않아서 로드 시점에 스키마를 지정할 수 없고 색인도 적용할 수 없는 경우도 빈번함
- 갱신, 트랜잭션, 색인
- 실제 테이블의 갱신은 아예 새로운 테이블을 만들어 데이터를 변환하는 방식으로 구현된다는 점에 주목, 대량의 데이터셋을 대상으로 실행되는 데이터웨어하우징 애플리케이션에서 작동하는 방식
- HDFS 기존 파일의 갱신을 지원하지 않기 때문에 삽입, 변경, 삭제로 인한 갱신 내역은 별도의 작은 델타 파일에 저장됨, 델타 파일은 메타스토어에서 백그라운드로 실행되는 맵리듀스 잡에 의해 기존 테이블과 주기적으로 병합됨
- 테이블과 파티션 수준의 잠금을 지원함, 잠금은 특정 프로세스가 테이블을 읽는 도중에 다른 프로세스가 테이블을 삭제하는 것을 방지할 수 있음, 잠금은 주키퍼에 의해 투명하게 관리되므로 사용자가 직접 주키퍼를 조작하여 잠금을 적용하거나 해제할 수는 없음
- 하이브는 특정한 경우에 쿼리의 속도를 높일 수 있는 색인을 지원함, 콤패트(compact) 색인과 비트맵(bitmap) 색인을 지원함, 색인은 플러그인 방식으로 구현되었기 때문에 다른 방식의 색인도 추가할 수 있음
- 콤팩트 색인은 각 값을 파일 오프셋이 아닌 HDFS 블록 넘버로 저장함, 디스크 공간을 많이 차지 않으면서도 인접한 행 사이에 분포된 특정 컬럼에 대한 값을 색인하는 데 매우 효율적, 비트맵 색인은 특정 값이 출현하는 행을 효율적으로 저장하기 위해 압축된 비트셋(bitset)을 사용함
- SQL-on-Hadoop 대안
- 하이브의 대안으로 개발된 유명한 오픈 소스로는 페이스북의 프레스토, 아파치 드릴, 스파크 SQL이 있음, 프레스토와 드릴은 임팔라와 비슷한 아키텍처를 가지고 있지만, 드릴은 HiveQL 대신 SQL:2011을 지원함, 스파크 SQL은 스파크를 기반 엔진으로 이용하고 ,스파크 프로그램에 내장 SQL 쿼리를 허용함
- 스파크 기반의 하이브는 하이브 프로젝트의 일부이므로 모든 하이브의 기능을 제공함, 스파크SQL은 일정 수준에서 하이브와의 호환성을 제공하는 새로운 SQL 엔진
- 아파치 피닉스는 HBase 기반의 SQL을 제공함, JDBC 드라이버를 통해 SQL을 요청하면 HBase의 scan() 메서드로 변환되어 해당 쿼리가 처리되므로 서버 측 집계를 수행하는 HBase의 보조프로세서의 장점을 취할 수 있음, 메타데이터 역시 HBase에 저장되는 것을 활용함
- 하이브의 대안으로 개발된 유명한 오픈 소스로는 페이스북의 프레스토, 아파치 드릴, 스파크 SQL이 있음, 프레스토와 드릴은 임팔라와 비슷한 아키텍처를 가지고 있지만, 드릴은 HiveQL 대신 SQL:2011을 지원함, 스파크 SQL은 스파크를 기반 엔진으로 이용하고 ,스파크 프로그램에 내장 SQL 쿼리를 허용함
- HiveQL
- 하이브의 SQL언어인 HiveQL은 SQL-92, MySQL, 오라클 SQL을 혼합한 것
- 파티션과 버킷
- 테이블을 파티션으로 구조화할 수 있음, 파티션이란 테이블의 데이터를 날짜와 같은 파티션 컬럼의 값을 기반으로 큰 단위(coarse-grained)로 분할하는 방식, 파티션을 사용하면 데이터의 일부를 매우 빠르게 질의할 수 있음
- 테이블과 파티션은 효율적인 쿼리를 위해 데이터에 추가된 구조인 버킷으로 더욱 세분화 될 수 있음, 사용자 ID를 기준으로 버킷을 생성하면 전체 사용자 중에서 무작위 데이터 샘플을 뽑아 사용자가 작성한 쿼리가 제대로 실행되는지 빠르게 평가할 수 있음
- 파티션
- 테이블은 다중 차원으로 파티션될수 있음, 예를 들어 먼저 날짜를 기준으로 로그를 파티션하고 그다음에 지역별로 효율적인 쿼리를 수행하기 위해 각 날짜별 파티션에 국가별 서브파티션을 추가할 수 있음
- 버킷
- 테이블을 버킷으로 구조화하는 이유는 두 가지
- 매우 효율적인 쿼리가 가능하기 때문, 버킷팅은 테이블에 대한 추가 구조를 부여하고, 하이브는 어떤 쿼리를 수행할 때 이 추가 구조를 이용할 수 있음, 특히 동일한 컬럼(조인할 컬럼) 에 대한 버킷을 가진 두 테이블을 조인할 때 맵 조인을 구현하면 매우 효율적임
- 효율적인 샘플링에 유리, 매우 큰 데이터셋을 대상으로 개발하거나 개선하는 과정에서 데이터셋의 일부만을 쿼리를 수행할 수 있으면 매우 편리함
- 테이블을 버킷으로 구조화하는 이유는 두 가지
- 저장 포맷
- 하이브는 두 개의 차원, 즉 로우 포맷과 파일 포맷으로 테이블 저장소를 관리함
- 로우 포맷은 행과 특정 행의 필드가 저장된 방식을 지시함, 직렬자-역직렬자(Serializer-Deserializer)를 혼합한 하이브 전문 용어인 SerDe로 정의됨
- 테이블을 질의하는 경우와 같이 역질렬화를 수행할 때 SerDe는 파일에 저장된 바이트의 데이터행을 하이브에서 내부적으로 사용되는 객체로 역지렬화하여 그 데이터에 대한 연산을 수행함
- 뷰
- SELECT 문으로 정의된 일종의 가상 테이블(virtual table), 뷰는 사용자에게 디스크에 실제 저장된 것과 다른 방시긍로 데이터를 보여주는 데 사용됨
- 사용자 정의 함수
- 정의 UDF, 사용자 정의 집계 함수(user-defined aggregate function - UDAF), 사용자 정의 테이블 생성 함수(user-defined table-generating function - UDTF) 등 세 종류의 UDF를 지원함, 세 종류의 차이점은 입력으로 받는 행과 출력되는 행의 개수가 다르다는 것
- 정규 UDF는 단일 행을 처리한 후 단일 행을 출력함, 수학 함수나 문자열 함수와 같은 대부분의 함수가 여기에 해당함
- UDAF는 다수의 입력 행을 처리한 후 단일 행을 출력함, COUNT나 MAX같은 집계 함수가 여기에 해당함
- UDTF는 단일 로우를 처리한 후 다수의 행(테이블)을 출력함
- 정의 UDF, 사용자 정의 집계 함수(user-defined aggregate function - UDAF), 사용자 정의 테이블 생성 함수(user-defined table-generating function - UDTF) 등 세 종류의 UDF를 지원함, 세 종류의 차이점은 입력으로 받는 행과 출력되는 행의 개수가 다르다는 것
- 아파치 크런치는 맵리듀스 파이프라인을 작성하는 고수준 API, 맵리듀스 대신 크런치를 사용하면 String이나 POJO(Plain old Java object)와 같은 프로그래머에 익숙한 자바 자료형, 풍부한 데이터 변환 기능, 여러 단계의 파이프라인에 집중할 수 있는 장점이 있음(워크플로에 있는 개별 맵리듀스 잡을 직접 관리할 필요가 없음)
- 피그와 달리 크런치 프로그램과 UDF는 모두 단일 언어(자바 또는 스칼라)로 작성되고 프로그램 속에 UDF를 바로 넣을 수 있음
- 고수준의 크런치 파이프라인은 복잡한 구성이 가능하고 공통 함수는 라이브러리로 추출하여 다른 프로그램에서 다시 사용할 수 있음, 이 점이 코드의 재사용이 어려운 맵리듀스와의 차이점
- 파이프라인 실행
- 파이프라인을 구축할 때 크런치는 내부 실행 계획을 만드는데,이 계획은 사용자에 의해 명시적으로 또는 크런치에 의해 암시적으로 실행됨
- 파이프라인 수행하기
- 파이프라인 동작은 Pipeline의 run() 메서드를 호출하여 명시적으로 실행됨
- 여러 단계로 실행 계획을 최적화함, 최적화에 대한 자세한 내용은 실행 엔진에 따라 다름
- 최적화된 계획에서 각 단계를 실행하여(가능하면 병렬로) 결과 PCollection을 실체화함
- run() 메서드는 실행되는 각 단계에 대한 정보(실행 시간과 맵리듀스 카운터)파이프라인의 성공 여부(succeeded() 메서드를 통해)와 함께 PipelineResult 객체를 호출자에 반환함
- clean() 메서드는 PCollection을 실체화하기 위해 생성된 모든 임시 중간 파일을 삭제함, 파이프라인이 종료된 이후에 HDFS의 디스크 공간을 풀어주기 위해 반드시 호출
- done()을 호출하는 것이 더 편리함, 파이프라인이 실행된 다음에 더 이상 필요 없으며 정리하라는 신호를 보냄
- 비동기 실행
- run() 메서드는 파이프라인이 종료될 때까지 반환하지 않고 기다리는 대기호출
- 대용량 데이터 처리를 위한 클러스터 컴퓨팅 프레임워크
- 스파크는 클러스터 기반으로 작업을 실행하는 자체 분산 런타임 엔진이 있음, 하둡과 밀접하게 통합되어 있어서 YARN 기반으로 실행할 수 있고, 하둡 파일 포맷과 HDFS 같은 기반 저장소를 지원함
- 잡 사이의 대용량 작업 데이터셋을 메모리상에 유지할 수 있는 것으로 잘 알려져 있음, 이런 특성이 있어서 동일한 기능을 수행하지만 매번디스크에서 데이터셋을 읽는 맵리듀스 워크플로에 비해 10배 혹은 어떤 경우에는 더 빠른 성능을 보임
- 스파크 처리 모델로 큰 효과를 얻을 수 있는 두 가지 애플리케이션
- 반복적 알고리즘(종료 조건을 만족할 때까지 데이터셋에 함수를 반복해서 적용)
- 대화형 분석(사용자가 데이터셋에일련의 대화식 쿼리를 생성)
- 인메모리 캐싱을 사용하지 않더라도 스파크는 DAG 엔진과 사용자 경험 등을 제공하기 때문에 큰 매력이 있음
- 조인과 같은 다양한 일반적인 데이터 처리 작업을 수행하는 풍부한 API를 제공함, 파이썬과 스칼라를 위한 REPL(read-eval-print loop)환경을 제공하므로 빠르고 편리하게 데이터셋을 탐색할 수 있음
- val lines = sc.textFile("~.txt")
- lines 변수는 탄력적인 분산 데이터셋(Resilient Distributed Dataset - RDD)을 참조함, 클러스터에 있는 다수의 머신에 분할되어 저장된 읽기 전용 컬렉션, 전형적인 스파크 프로그램은 하나 또는 그 이상의 RDD를 입력받고, 일련의 변환 작업을 거쳐 목표 RDD 집합으로 변형됨
- RDD로 데이터를 로드하거나 트랜스포메이션(변형 연산)을 수행해도 실제로 데이터는 처리 되지 않음, 단지 계산을 위한 수행 계획이 만들어질뿐, 실제 계산은 RDD를 처리하는 foreach()와 같은 액션을 호출할 때 수행됨
- 스파크 애플리케이션, 잡, 스테이지, 태스크
- 하나의 맵과 하나의 리듀스로 구성된 단일 맵리듀스의 잡과 달리 스파크의 잡은 임의의 방향성 비순환 그래프(directed acyclic graph - DAG)인 스테이지로 구성됨
- 스파크가 실행될 때 스테이지는 다수의 태스크로 분할되고, 각 태스크는 맵리듀스의 태스크와 같이 클러스터에 분산된 RDD파티션에서 병렬로 실행됨
- 잡은 항상RDD 및 공유변수를 제공하는 애플리케이션(SparkContext 인스턴스로 표현되는)의 콘텍스트 내에서 실행됨, 하나의 애플리케이션은 하나 이상의 잡을 수행할 수 있으며, 직렬 또는 병렬로 실행되면, 동일한 애플리케이션에서 수행된 이전 잡에서 캐싱된 RDD에 접근할 수 있는 메커니즘을 제공함
- 스파크는 사용자의 파이썬 코드를 수행하기 위해 파이썬의 서브프로세스를 포크(fork - 자식 프로세스 하나 생성)함 (구동 프로그램과 클러스터에서 사용자 태스크를 실행하는 익스큐터 모두 해당됨), 두 프로세스를 소켓으로 연결하면 부모 프로세스는 파이썬 코드로 처리될 RDD 파티션 데이터를 전달할 수 있음
- 탄력적인 분산 데이터셋 RDD
- 생성
- 객체의 인메모리 컬렉션(병렬parallelizing 컬렉션으로 알려진)으로 생성하는 것
- 적은 양의 입력 데이터를 병렬로 처리하는 CPU 부하 중심의 계산에 유용함
- HDFS와 같은 기존 외부 저장소의 데이터셋을 사용하는 것
- 기존의 RDD를 변환하는 것
- 객체의 인메모리 컬렉션(병렬parallelizing 컬렉션으로 알려진)으로 생성하는 것
- 트랜스포메이션과 액션
- 스파크는 RDD에 트랜스포메이션과 액션이라는 두 종류의 연산자를 제공함, 트랜스포메이션은 기존 RDD에서 새로운 RDD를 생성함
- 액션은 특정 RDD를 계싼하여 어떤 결과를 만들어냄, 그 결과는 사용자에게 보여지거나 외부 저장소에 저장될 수 있음
- 액션은 즉시 실행되지만 트랜스포메이션은 그렇지 않음, 스파크는 지연 실행이라는 특별한 개념이 있어서 트랜스 포메이션이 적용된 RDD에 액션이 수행될 때까지 아무런 동작도 하지 않음
- 반환 타입이 RDD면 그 메서드는 트랜스포메이션이고 그렇지 않으면 액션, 트랜스포메이션에는 매핑,그룹화,집계,재분할,샘플링,RDD 조인 및 RDD 집합 처리 등의 메서드가 있으며 액션에는 RDD를 컬렉션으로 실체화, RDD 통계 계산, RDD에서 특정 개수의 항목을 샘플링, RDD를 외부 저장소에 저장하는 메서드가 있음
- 생성
- 집계 트랜스포메이션
- 키-값 쌍이 있는 RDD를 키를 기준으로 집계하는 트랜스포메이션에는 reduceByKey(), foldByKey(), aggregateByKey()가 있음, 모두 주어진 키의 값을 집계해서 키마다 하나의 값을 만든다는 공통점이 있음(대응하는 액션인 reduce(), fold(), aggregate()는 유사한 방식으로 전체 RDD에서 하나의 값을 만듬)
- reduceByKey()는 하나의 값이 나올 때까지 반복적으로 키-값 쌍의 값에 이진 함수를 적용함
- 지속성
- cache() 메서드를 호출해도 RDD를 메모리에 즉시 캐싱하지 않음, 대신 스파크 잡이 실행될 때 해당 RDD를 캐싱해야 한다고 플래그로 표시해둠
- 맵리듀스는 다른 계산을 수행하기 위해서는 입력 데이터셋을 디스크에서 다시 불러와야 함, 심지어 원본 데이터셋에서 비정상 레코드를 제거하고 불필요한 필드를 정리한 중간 데이터셋이 있더라도 반드시 디스크에서 다시 불러와야 하고 속도는 상대적으로 느릴 것, 스파크는 클러스터의 여러 머신에 있는 메모리에 데이터셋을 분산하여 캐싱할 수 있고 해당 데이터셋에 대해 수행되는 계산은 매우 빠른 속도로 처리됨
- 대화형 데이터 탐색 작업에 매우 유용함, 반복 알고리즘과 같이 첫 번째 반복 연산의 결과를 메모리에 캐싱했다가 그다음 반복 연산에서 입력으로 사용하는 특정 알고리즘에 적합함
- 지속성 수준
- cache()를 호출하면 익스큐터의 메모리에 각 RDD 파티션을 보존함, 익스큐터에 RDD 파티션을 저장할 수 있는 충분한 메모리가 없다면 계산은 실패하지 않으나 필요에 따라 다시 계산을 수행해야 함, 트랜스포메이션 연산이 매우 많은 복잡한 프로그램에서 다시 계산을 수행하려면 상당한 시스템 자원이 필요함, StorageLevel을 인자로 지정할 수 있는 persist() 메서드로 다양한 유형의 지속성을 선택할 수 있는 기능을 제공함
- StorageLevel의 기본값은 MEMORY_ONLY로, 일반적인 인메모리 객체 표현을 사용함, MEMORY_ONLY_SER로 설정하면 파티션의 요소를 바이트 배열로 직렬화하여 객체를 압축된 형태로 저장할 수 있음, MEMORY_ONLY_SER 수준은 MEMORY_ONLY에 비해 더 많은 CPU를 사용함, 하지만 일반적인 인메모리 객체 표현을 위한 충분한 메모리는 없지만 최종 직렬화 RDD 파티션을 저장하기에 적합하다면 시도해볼 만한 가치는 있음, MEMORY_ONLY_SER 레벨은 각 RDD를 큰 객체가 아닌 하나의 바이트 배열로 저장하기 때문에 가비지 컬렉션 부담을 줄일 수 있음
- RDD 파티션 직렬화는 기본적으로 일반적인 자바 직렬화를 사용함, 크라이오(kyro) 직렬화는 크기와 속도측면에서 모두 장점이 있음, CPU를 더 사용하지만 직렬화된 파티션을 압축하기 때문에 필요한 공간도 줄일 수 있음
- 메모리를 사용하는 비용이 너무 크면 MEMORY_AND_DISK(메모리에 먼저 저장하고 충분하지 않으면 디스크에 저장)나 MEMORY_AND_DISK_SER(메모리가 충분하지 않으면 디스크에 직렬화하여 저장)옵션을 사용하는 편이 더 좋음
- 파티션을 클러스터에 있는 단일 노드가 아닌 여러 노드에 복제해서 저장하거나 힙 메모리를 사용하는 진보적이고 실험적인 지속성 수준도 있음
- 직렬화
- 데이터 직렬화
- 크라이오 직렬화는 효율성이 더 높고 범용적인 자바의 직렬화 라이브러리
- 직렬화될 객체의 클래스를 단일 참조자에 기록함(기록된 모든 객체에 대해 단일 참조자가 작성됨), 클래스가 등록되어 있으면 정수 식별자로, 그렇지 않으면 전체 클래스 이름으로 관리됨
- 함수 직렬화
- 함수 직렬화는 작업 자체를 의미함, 스칼라에서 함수는 표준 자바 직렬화 메커니즘으로 직렬화되며, 스파크는 원격 익스큐터 노드에 함수를 전송할 때 이를 사용함, 스파크는 로컬 모드에서 실행할 때도 함수를 직렬화함, 누군가 실수로 직렬화되지 않는 함수(nonserializable 클래스의 메서드로 변환)를 사용했다면 개발 단계에서 이를 쉽게 발견할 수 있음
- 데이터 직렬화
- 공유 변수
- map() 연산에서 룩업(lookup) 테이블을 이용함
- lookup 변수는 클러저의 일부로 직렬화되어 map()에 전달되며 제대로 작동하지만 브로드캐스트 변수를 사용하면 더 효율적으로 동일한 기능을 수행할 수 있음
- 브로드캐스트 변수
- 브로드캐스트 변수는 직렬화된 후 각 익스큐터에 전송되며, 나중에 태스크가 필요할 때 언제든지 접근할 수 있도록 캐싱됨
- 브로드캐스트 변수는 맵리듀스의 분산 캐시와 유사한 역할을 하지만 스파크 메모리가 충분하면 메모리에 모두 저장하고 부족하면 나머지를 디스크에 저장한다는 차이점이 있음
- 브로드캐스트 변수는 드라이버에서 태스크로 단방향 전송됨, 브로드캐스트 변수의 값을 변경하거나 드라이버로 역전파하는 방법은 없음, 필요하면 다음에 나오는 어큐뮬레이터(accumulator)를 사용하면 됨
- 어큐뮬레이터
- 맵리듀스의 카운터와 유사하게 태스크에서 그 값을 증가만 시킬 수 있는 공유변수, 잡이 완료된 후 드라이버 프로그램에서 어큐뮬레이터의 최종값을 조회할 수 있음
- 스파크 잡 수행 분석
- 드라이버는 SparkContext를 포함한 애플리케이션을 관리하고 잡의 태스크를 스케줄링함
- 익스큐터는 애플리케이션과는 분리되어 있으며, 애플리케이션의 실행을 관장하고 애플리케이션의 태스크를 실행함
- 일반적으로 드라이버는 클러스터 매니저가 관리하지 않는 클라이언트에서 실행되지만, 익스큐터는 클러스터에 있는 머신에서 실행됨
- DAG 구성
- 셔플 맵 태스크(shuffle map task)
- 맵리듀스 셔플의 맵 부분과 비슷함, 각 셔플 맵 태스크는 파티셔닝 함수에 기반하여 RDD 파티션당 하나의 계산을 실행하고, 그 결과를 새로운 파티션 집합에 저장함
- 새로운 파티션의 데이터는 셔플 맵 태스크나 결과 태스크로 구성된 다음에 스테이지에서 사용됨
- 결과 태스크
- count() 액션의 결과처럼 그 결과를 사용자 프로그램에 돌려주는 마지막 스테이지에서 실행됨
- 각 결과 태스크는 RDD 파티션에서 계산을 수행하고 그 결과를 드라이버에 돌려줌
- 가장 단순한 스파크 잡은 셔플 단계가 없고 오직 결과 태스크로만 구성된 단일 스테이지로 되어있음, 이 잡은 맵리듀스의 맵 단독 작업과 유사함
- countByKey() : 두 번째 셔플을 실행하지 않고 드라이버 프로그램이 실행되는 로컬에서 최종 집계 작업을 수행한다는 점을 유의하자
- DAG 스케줄러는 태스크 스케줄러가 데이터 지역성(data locality)을 활용할 수 있도록 개별 태스크의 배치 우선권을 지정함
- 셔플 맵 태스크(shuffle map task)
- 태스크 스케줄링
- 태스크 스케줄러에 태스크의 집합을 전송할 때 태스크 스케줄러는 해당 애플리케이션이 실행되는 익스큐터의 목록을 찾고 배치 우선권이 있는 익스큐터에 각 태스크를 매핑함, 빈 코어가 있는 익스큐터에 태스크를 할당함
- 스케줄러가 먼저 프로세스-로컬 태스크를 할당하고, 노드-로컬 태스크, 랙-로컬 태스크 순으로 할당함
- 익스큐터와 클러스터 매니저
- 익스큐터의 생명주기를 관리하는 것은 클러스터 매니저의 책임
- 로컬
- 로컬 모드에는 드라이버와 동일한 JVM에서 실행되는 단일 익스큐터가 있음, 로컬 모드는 테스트를 하거나 작은 잡을 실행하는 데 유용함
- 독립
- 독립 클러스터 매니저는 단일 스파크 마스터와 하나 이상의 워커로 실행되는 간단한 분산 방식, 스파크 애플리케이션이 시작되면 마스터는 애플리케이션을 대신해서 모든 워커에 익스큐터 프로세스를 생성하도록 요청함
- 메소스
- 아파치 메소스는 범용 클러스터 자원 관리자로 조직의 정책에 따라 다수의 애플리케이션이 세밀하게 자원을 공유할 수 있음
- 기본 정책인 미세 단위(fine-grained) 모드에서 각 스파크 태스크는 메소스 태스크로 실행됨, 미세 단위 모드는 클러스터의 자원을 매우 효율적으로 관리하지만 프로세스 구동 시 오버헤드가 있음
- 큰 단위(coarse-grained)모드에서 익스큐터는 프로세스의 내부에서 해당 태스크를 실행함, 스파크 애플리케이션이 실행되는 동안 익스큐터 프로세스가 클러스터의 자원을 계속 유지하고 있음
- YARN
- 하둡에서 사용하는 리소스 매니저
- 실행되는 각 스파크 애플리케이션은 YARN 애플리케이션의 인스턴스며, 각 익스큐터 자체의 YARN 컨테이너에서 실행됨
- 로컬
- YARN에서 스파크 실행
- 하둡 컴포넌트와 밀접한 통합을 제공하는 YARN에서 스파크를 실행하는 것은 기존에 하둡 클러스터가 있고 스파크를 추가로 사용할 때 가장 편리한 방법
- 배포 모드
- 클라이언트에서 드라이버가 실행되는 YARN 클라이언트 모드
- spark-shell이나 pyspark와 같은 대화형 컴포넌트가 필요함, 클라이언트 모드는 디버깅을 위한 출력을 바로 볼 수 있기 때문에 스파크 프로그램을 처음 만들때 유용함
- 드라이버가 클러스터의 YARN 애플리케이션 마스터에서 실행되는 YARN 클러스터 모드
- 전체 애플리케이션이 클러스터에서 실행되기 때문에 운영 잡에 적합함, 나중에 감사를 위해 드라이버 프로그램을 포함한 로그를 파일로 보관함
- 클라이언트에서 드라이버가 실행되는 YARN 클라이언트 모드
- 익스큐터의 생명주기를 관리하는 것은 클러스터 매니저의 책임
- HBase는 HDFS 기반으로 구현한 컬럼 기반 분산 데이터베이스(distributed column-oriented database)
- 대규모 데이터셋에서 실시간으로 읽고 쓰는 랜덤 액세스가 필요할 때 사용할 수 있는 하둡 애플리케이션
- 단지 노드만 추가하면 선형으로 확장할 수 있는 기반으로 구축했음, HBase는 관계형 구조가 아니며 SQL을 지원하지 않지만 특정 영역에서는 RDBMS가 할 수 없는 문제를 해결해줌, 상용 하드웨어로 구성된 클러스터에서 대용량의 산재된 테이블을 관리함
- 수집된 웹페이지와 그 속성(언어,MIME 형식 등)을 가진 웹 테이블(webtable), 웹테이블의 키는 웹페이지의 URL
- 리전
- 테이블을 자동으로 리전 단위로 수평 분할함, 각 리전은 테이블의 로우의 부분집합으로 구성됨
- 리전은 자신이 속한 테이블, 첫 번째 로우(포함), 마지막 로우(제외)로 정의됨
- 구현
- HDFS와 YARN이 클라이언트, 워커, 관리 마스터(coordinating master - HDFS의 네임노드와 데이터노드, YARN의 리소스 매니저와 노드 매니저)로 이루어진 것처럼, HBase도 하나 이상의 리전서버 워커로 구성된 클러스터를 조율하는 HBase 마스터 노드로 이루어짐
- HBase 마스터는 최초 설치를 부트스트랩핑(운영체제 또는 시스템을 초기화하거나 준비 상태로 만드는 일련의 작업)하는 역할을 수행하고, 등록된 리전서버에 리전을 할당하며, 실패한 리전서버를 복구할 책임을 가짐
- 마스터 노드는 가볍게 시작됨, 리전서버는 0개 이상의 리전을 다루며 클라이언트의 읽기/쓰기 요청을 처리함
- 리전 스플릿을 관리하고, 새로운 리전을 HBase 마스터에 알려줌으로써 마스터가 부모 리전과의 연결을 끊고 대신 자식을 할당하게 됨
- 주키퍼 앙상블은 hbase:meta 카탈로그 테이블의 윛, 현재 클러스터 마스터의 주소와 같은 아주 중요한 값을 가짐, 주키퍼는 중간에 리전을 할당할 때 참여하는 서버들 간의 충돌을 중재함
- 주키퍼는 할당 트랜잭션 상태를 관리하므로 고장나서 제외된 서버가 내버린 리전을 알아서 복구할 수 있음
- 대량 로드
- HBase 대량 로드를 위해 맵리듀스에서 파일시스템으로 내부 데이터 포맷을 직접 기록할 수 있는 효율적인 기능을 가지고 잇음, HBase 클라이언트 API를 통해 기록할 때보다 훨씬 빠른 속도로 HBase 인스턴스에 로드할 수 있음
- 맵리듀스 잡을 이용해서 HFile을 HDFS 디렉터리에 기록하기 위해 HFileOutputFormat2를 사용함
- HDFS의 HFile을 기존의 HBase 테이블로 옮기는 것
- HBase와 RDBMS의 비교
- HBase
- 분산 및 컬럼 기반 데이터 저장 시스템, 하둡이 HDFS의 무작위 읽기와 쓰기를 제공하지 않는다는 점을 발견했으며 모든 방향의 확장성에 중점을 두어 밑바닥부터 설계됨, 로우 개수가 길고(수억), 컬럼 개수가 넓으며(수백만), 수평적으로 분할 가능해서 수천 대의 상용 노드에 자동으로 복제할 수 있음, 테이블 스키마는 물리적 저장소를 반영해서 효율적인 데이터 구조 직렬화, 저장, 검색을 위한 시스템을 생성함
- RDBMS
- 전형적인 RDBMS는 고정된 스키마, ACID 특성의 로우 기반 데이터베이스, 복잡한 SQL 쿼리 엔진, 강한 일관성, 참조 무결성, 물리층의 추상화, SQL 언어로 복잡한 쿼리를 하는 것에 주안점을 두었음, 쉽게 2차 인덱스를 생성할 수 있고, 복잡한 내부,외부 조인을 수행하고, 여러 테이블, 로우 컬럼을 카운트, 합계, 정렬, 그룹, 페이징 할 수 있음
- 데이터셋 크기나 읽기/쓰기 병행성을 고려해서 규모를 늘려야 할 때 RDBMS의 편리함은 막대한 성능 저하로 이어지며 태생적으로 분산은 어렵다는 것을 알게 될것, RDBMS를 확장하면 대개 코드의 규칙을 어기고, ACID 제약을 느슨하게 하고, 전통적인 DBA의 지혜를 무용지물로 만들어 처음에 너무나 편리했던 관계형 데이터베이스의 이상적인 속성 대부분을 잃음
- HBase
- 성공적인 서비스
- 전형적인 RDBMS를 확장하는 방법
- 초기 대중에 출시 : 로컬 워크스테이션에서 잘 정의한 스키마를 가진 공유 및 원격으로 관리되는 MySQL 인스턴스로 이동함
- 서비스가 점점 더 유명해지면서 데이터베이스에 아주 많은 읽기 요청 : 멤캐시드를 추가하여 잦은 쿼리를 캐시함, 캐시된 데이터는 만료되므로 읽기는 더 이상 엄격한 ACID를 따르지 않음
- 서비스가 계속해서 인기를 더해가며 데이터베이스에 아주 많은 쓰기 요청 발생 : 16코어,128GB 메모리, 15k RPM의 하드 드라이브를 가진 고성능 서버를 구매해서 MySQL 수직 확장함, 고비용이 발생함
- 새로운 기능은 쿼리의 복잡도를 증가시키며 이제 아주 많은 조인이 존재 : 조인을 줄이기 위해 데이터를 비정규화함
- 유명세는 서버에 엄청난 부하를 주어 굉장히 느려짐 : 서버 측 연산을 멈춤
- 일부 쿼리는 여전히 너무 느림 : 주기적으로 대부분의 복잡한 쿼리를 미리 실체화하고, 대부분의 조인을 중단하려 시도함
- 읽기는 문제없지만 쓰기는 점점 더 느려짐 : 2차 인덱스와 트리거를 내림
- HBASE 특성
- 실제 인덱스가 없음 : 로우는 순차적으로 저장되며 각 로우별 컬럼도 순차적으로 저장됨, 인덱스 확장과 같은 문제가 발생하지 않으며 입력 성능은 테이블의 크기와 무관함
- 자동 분할 : 테이블이 증가하면 자동으로 여러 리전으로 분할되고 가용한 모든 노드로 분산됨
- 새로운 노드를 추가하여 자동으로 선형 확장 : 노드를 추가하고 이를 기존 클러스터에 붙이고 리전서버를 실행함, 리전은 자동으로 균형을 맞추고 부하는 균등하게 분산될것
- 범용 하드웨어 : 클러스터는 50,000달러짜리가 아닌 1,000 ~ 5,000달러 정도의 범용 머신으로 구성됨, RDBMS는 I/O성능이 중요하며 이러한 요구사항을 충족하는 하드웨어는 매우 비쌈
- 내고장성 : 수많은 노드로 구성되었기 때문에 개별 노드는 상대적으로 큰 문제가 되지 않음, 개별 노드의 장애에 대해 전혀 걱정할 필요가 없음
- 배치 처리 : 맵리듀스와의 통합으로 데이터의 지역성을 준수하고 완전한 병렬성과 분산 작업을 지원함
- HBASE 클러스터 운영하면서 겪는 몇 가지 흔한 현상
- 파일 기술자의 고갈 : 클러스터 시작 후 파일을 열린 상태로 두기 때문에 시스템과 하둡에 부여된 한계에 도달하는 데 그다지 오래 걸리지 않음
- 데이터노드 스레드의 고갈 : 하둡 데이터노드는 동시에 실행할 수 있는 스레드 수의 제한이 있음
- 메트릭
- 하둡은 주기적으로 중요한 정보를 콘텍스트로 보내주는 메트릭 시스템을 지원함
- 하둡 메트릭을 활성화하고, 갱글리아와 연동하거나 JMX를 이용해서 내보내면 클러스터의 현재 상황을 확인할 수 있음, HBase 자체도 메트릭(요청률, 중요한 수치, 사용된 자원)을 제공함
- 하둡의 분산 코디네이션(Coordination) 서비스인 주키퍼(ZooKeeper)를 이용해서 분산 애플리케이션을 구추하는 방법
- 분산 애플리케이션을 작성하는 것은 매우 어려운 일, 부분 실패(partial failure)때문, 네트워크로 연결된 두 노드 사이에 메시지가 전송한 후 네트워크가 끊겼을 때 송신자는 수신자가 메시지를 수신했는지 여부를 모르게 됨
- 분산 시스템에 있어서 부분 실패는 절대 피할 수 없기 때문에 주키퍼를 사용한다고 해도 부분 실패가 완전히 사라지는 것은 아니며 완벽히 감출 수도 없음, 주키퍼는 부분 실패를 안전하게 처리할 수 있는 분산 애플리케이션을 구축하기 위한 도구를 제공함
- 특징
- 단순하다 : 주키퍼는 몇 개의 기본 기능을 핵심으로 제공하고 명령 및 통지와 같은 추상화 기능을 추가로 제공하는 간소화된 파일 시스템
- 제공하는 기능이 풍부함 : 주키퍼 프리미티브(primitive)는 대규모 데이터 구조와 프로토콜 코디네이션에 사용되는 풍부한 구성요소를 제공하고 있음
- 고가용성을 제공함 : 주키퍼는 다수의 머신에서 실행되며 고가용성을 보장하도록 설계되었기 때문에 애플리케이션은 주키퍼의 이러한 특성을 전적으로 신뢰하고 사용할 수 있음, 주키퍼는 시스템에서 발생할 수 있는 단일 장애점(single points of failure - SPOF)문제를 해결하는 데 도움을 주므로 신뢰성 높은 애플리케이션을 개발할 수 있음
- 느슨하게 연결된 상호작용에 도움을 줌 : 주키퍼가 동작할 때 참여자들은 서로에 대해 몰라도 상관없음
- 라이브러리다 : 주키퍼는 일반적인 코디네이션 패턴에 대한 구현체와 구현 방법을 공유 저장소에 오픈 소스로 제공함
- 주키퍼 서비스
- 순차 번호(sequential) - 주키퍼가 znode 이름 뒤에 순차 번호를 부여한 것
- 감시 - znode에 어떤 변화가 있을 때 클라이언트에 관련 이벤트를 통지하는 기능
- 주키퍼 설계에서 보장하는 데이터 일관성 흐름
- 순차적 일관성 : 특정 클라이언트의 업데이트는 보낸 순서대로 적용함
- 원자성 : 업데이트는 성공 또는 실패 둘 중 하나
- 단일 시스템 이미지 : 클라이언트는 연결된 서버에 관계없이 같은 시스템을 바라봄
- 지속성 : 업데이트 연산이 성공하면 업데이트 내역은 저장되고 취소되지 않음
- 적시성 : 클라이언트가 시스템을 볼 때 지연이 발생하더라도 수십 초 이상 오래된 정보를 보여주지 않을 것임
- 탄력적인 주키퍼 애플리케이션
- 멱등(idempotent) 연산은 한 번 이상 적용되더라도 같은 결과를 내는 것을 말함, read 요청이나 무조건적인 setData 등을 말함, 멱등 연산은 쉽게 재시도 할 수 있음
- 비멱등 연산(nonidempotent)은 무차별로 재시도할 수 없는 것을 말하는데, 여러 번 적용된 결과가 한 번 적용된 것과 다르기 때문, 이때 프로그램은 znode 경로명이나 데이터 내의 정보를 인코딩해서 업데이트 여부를 판단하는 방법이 필요함
- 회복 불가능한 예외, 몇 가지 사례에서 주키퍼 세션이 더 이상 유효하지 않을 수 있는데, 이를 회복불가능한 예외라고 함, 이는 타임아웃되었거나 세션이 닫혔거나(둘 다 KeeperException SessionExpiredException 발생) 아니면 인증이 실패했기 때문일 수 있음(KeeperException.AuthFailedException 발생)
- 더 많은 분산 데이터 구조와 프로토콜
- 북키퍼
- 북키퍼(BookKeeper)는 고가용성의 신뢰성 높은 로깅 서비스, WAL(write-ahead logging)을 제공하는 데 사용될 수 있는데, WAL은 저장소 시스템 안에 있는 데이터의 무결성을 보장하는 데 사용되는 일반적인 기술, WAL을 사용한 시스템에서 모든 쓰기 동작은 적용되기 전에 먼저 트랜잭션 로그에 기록됨
- 북키퍼 클라이언트는 레저(leger)ㅏ고 하는 로그를 생성하고, 레저에 추가된 각 레코드를 레저 엔트리(ledger entry)라고 함, 레저엔트리는 간단하게 바이트 배열로 되어 있음
- 레저는 부키(bookie)가 관리하며, 부키는 레저 데이터를 복제하는 서버, 레저 데이터는 주키퍼 내에 저장되지 않고 오직 메타데이터만 저장됨을 명심하자
- 헤드윅(Hedwig)
- 북키퍼를 활용하여 구축된 토픽 기반의 발행-구독 시스템, 주키퍼 덕분에 헤드윅은 예상보다 길어진 시간 동안 구독자가 오프라인 상태에 있더라도 메시지 전송이 보장되는 고가용성 서비스
- 북키퍼
- 주키퍼의 실 서비스
- 탄력성과 성능
- 주키퍼 서버는 장비와 네트워크 장애로부터 영향을 최소화하도록 배치되어야 함
- 실 운영에서 서버를 랙, 전원 공급 장치, 스위치 전반에 고르게 배치해서 어떤 것이 장애가 발생하더라도 앙상브리 서버의 반수 이하로 내려가지 않도록 주의해야함
- 탄력성과 성능
- 캐스케이딩(Cascading)은 오픈 소스 자바 라이브러리로, 맵리듀스의 추상화 계층을 제공하는 API
- 개발자는 캐스케이딩으로 하둡 클러스터에서 동작하는 복잡하고 중요한 데이터 처리 애플리케이션을 만들 수 있음
- 맵과 리듀스 연산은 강력한 프리미티브를 제공함, 그들은 서로 다른 개발자들이 공유해야 하는 복잡하고도 고도로 합성 가능한 코드를 작성할 때 세분화 수준을 잘못 선택할 가능성이 높음
- 캐스케이딩은 맵리듀스에서 사용되는 키와 값을 간단한 필드 이름과 데이터 튜플 모델로 대체함
- 캐스케이딩은 더 높은 수준의 추상화 개념인 함수(Function), 필터(Filter), 집계자(Aggregator), 버퍼(Buffer)를 도입하여 맵과 리듀스 연산에서 탈피함
- 필드,튜플,파이프
- 맵리듀스 모델은 입력 데잍터를 맵 함수로, 맵 함수에서 리듀스 함수로, 그리고 리듀스 함수에서 출력 데이터로 보내기 위해 키와 값을 사용함
- 캐스케이딩은 키와 값을 사용하지 않고 상응하는 필드 이름이 있는 튜플로 대체하여 일련의 맵리듀스 연산을 단순화시켰음
- 파이프 종류
- Each : 한 번에 하나의 입력 튜플을 처리함, 입력 튜플에 함수나 필터 연산을 적용할 수 있음
- GroupBy : 그룹 필드를 기준으로 튜플을 그룹화함, 여러 개의 입력 튜플 스트림이 같은 필드 이름을 공유하고 있다면 하나의 스트림으로 병합할 수 있음
- CoGroup : 여러 개의 튜플 스트림을 공통 필드 이름으로 조인하고, 또한 공통 그룹 필드를 기준으로 튜플을 그룹화함, 둘 또는 그이상의 튜플 스트림에 모든 표준 조인(내부,외부 등)과 사용자 지정 조인을 사용할 수 있음
- Every : 한 번에 하나의 튜플 그룹을 처리함
- SubAssembly : 하나의 파이프 내부에 어셈블리 중첩을 허용함, 반복적인 중첩도 가능함
- 연산
- 함수 : 개별 입력 튜플에 동작하고, 모든 입력에 대해 0 또는 하나 이상의 출력 튜플을 반환함, 함수는 Each 파이프에 의해 적용됨
- 필터 : 특별한 종류의 함수로, 튜플 스트림에서 현재 입력 튜플의 제거 여부를 가리키는 불린값을 반환함
- 집계자 : 공통의 필드 값(예를 들면 동일한 last-name 값을 가진 모든 튜플)으로 그룹화된 튜플에 적용되는 연산
- 버퍼 : 유일한 그룹의 모든 튜플에 걸쳐 슬라이딩 윈도우(sliding window)처럼 동작하는 데 최적화되어 있다는 점을 제외하면 집계자와 비슷함, 버퍼는 개발자가 순서가 있는 튜플 안에 누락된 값을 추가할 필요가 잇을 때(누락된 날짜 혹은 기간과 같은)나 수행 평균(running average)을 생성할 때 유용함
- 탭, 스킴, 플로
- 탭 : 데이터 접근 방법과 위치를 담당함
- 스킴 : 원시 데이터를 읽고 그것을 하나의 튜플로 변환하거나 튜플을 원시 데이터에 쓰는 작업을 담당함
- 하둡은 다양한 아키텍처 구성요소 간의 데이터 이동을 조정하고 처리할 수 있는 매우 강력한 플랫폼, 유일한 단점은 핵심 컴퓨팅 모델이 맵리듀스라는 것
- 캐스케이딩의 목표는 개발자가 데이터 분산,복제,분산 프로세스 관리 및 유지와 같은 힘든 일은 모두 하둡에 맡기고, 맵리듀스 관점에서 사고할 필요성을 못 느끼도록 매우 논리적인 API로 강력한 애플리케이션을 신속하고 간단하게 만들 수 있도록 돕는 것
- 하둡의 세 가지 모드
- 독립(로컬 모드)
- 데몬이 실행되지 않고 모든 것이 단독 JVM 내에서 실행됨, 독립 모드는 시험과 디버깅을 쉽게 할 수 있기 때문에 개발 단계에서 맵리듀스 프로그램을 실행할 때 적합함
- 의사분산 모드
- 모든 하둡 데몬을 로컬 머신에서 실행함, 따라서 작은 규모의 클러스터에서 실행하는 것과 같은 효과가 있음
- 완전분산 모드
- 하둡 데몬을 여러 대의 머신으로 구성된 클러스터에서 실행함
- 독립(로컬 모드)
- SSH 설정
- 하둡은 단지 SSH를 이용하여 slaves 파일에 정의된 클러스터에 포함된 일련의 호스트에서 데몬 프로세스를 실행하기 때문
- 로컬 컴퓨터에서 네임노드, 보조 네임노드, 데이터노드(HDFS), 리소스 매니저, 노드 매니저(YARN), 히스토러 서버(맵리듀스)의 데몬 프로세스가 시작될 것
- 클라우데라 아파치 하둡 배포판(Cloudera's Distribution Including Apache Hadoop - CDH)은 통합된 아파치 하둡 기반 스택으로, 실제 운영 환경에서 필요한 모든 구성요소를 포함하고 있으며 각 구성요소가 함께 잘 작동하도록 검증되고 묶여 있음, 클라우데라는 리눅스 패키지, 가상 머신 이미지, 타르볼 파일, 클라우드 기반의 CDH 실행 도구 등 다양한 형태의 배포판을 제공함
- 아파치 에이브로
- 언어 호환 데이터 직렬화 라이브러리, 풍부한 데이터 구조, 빠르고 간결한 바이너리 포맷, RPC 제공
- 아파치 크런치
- 맵리듀스 또는 스파크에서 실행되는 데이터 처리 파이프라인을 작성할 수 있는 고수준 자바 API
- 아파치 데이터푸(시험용)
- 대규모 분석을 위한 통계 UDF 라이브러리
- 아파치 플룸
- 안정성이 높고 설정이 가능한 스트리밍 데이터 수집
- 아파치 하둡
- 확장성이 높은 데이터 저장소(HDFS), 리소스 관리(YARN), 처리(맵리듀스)
- 아파치 HBase
- 임의의 읽기/쓰기 접근이 가능한 컬럼 기반 실시간 데이터베이스
- 아파치 하이브
- 대용량 데이터셋에 대한 SQL 유사 질의와 테이블
- 휴
- 하둡 데이터를 쉽게 다룰 수 있는 웹 UI
- 클라우데라 임팔라
- HDFS 또는 HBase 기반의 낮은 지연 시간의 대화형 SQL 질의
- 카이트 SDK
- 하둡 기반의 애플리케이션을 구축할 때 필요한 API, 예제, 문서
- 아파치 머하웃
- 확장성이 높은 기계 학습 및 데이터 마이닝 알고리즘
- 아파치 오지
- 상호의존적인 하둡 잡을 위한 워크플로 스케줄러
- 아파치 파케이(시험용)
- 중첩 데이터를 위한 효율적인 컬럼 기반 저장 포맷
- 아파치 피그
- 대규모 데이터셋을 처리할 수 있는 데이터 플로 언어
- 클라우데라 서치
- 구글 스타일의 하둡 데이터 자유 구문 검색
- 아파치 센트리(시험용)
- 세분화된 규칙 기반의 하둡 사용자 접근 제어
- 아파치 스파크
- 스칼라, 자바, 파이썬으로 대규모 인메모리 처리가 가능한 클러스터 컴퓨팅 프레임워크
- 아파치 스쿱
- 구조화된 데이터 저장소(관계형 데이터베이스)와 하둡 간의 효율적인 데이터 전송
- 아파치 주키퍼
- 분산 애플리케이션을 위한 고가용성 코디네이션 서비스
- 클라우데라는 또한 CDH로 실행되는 하둡 클러스터를 배포하고 운영할 수 있는 클라우데라 관리자(Cloudera Manager)를 제공함