학부생에 있을때 3학년부터 4학년까지 분산처리 관련 프로젝트를 진행하며, Hadoop을 기술적으로 이용만 했을 뿐, 필요한 부분 이외에는 그 속에 남긴 의미를 이해하려하지 않았다.
하지만 2011년 Hadoop을 처음 접했을 때와 지금은 많은 부분이 달라졌다. 클라우데라(Cloudera)와 같이 CDH(Cloudera's Destributed in Apache Hadoop) 배포판으로 쉽게 하둡을 설치하고 사용 할 수 있으며, Hadoop Eco System에 포함된 전반적인 솔루션을 쉽게 설치해 사용 할 수 있다는 점이다.
서론은 여기까지 하고, 하둡에 대해 이야기 해보자.
(1) HDFS (Hadoop Distributed File System)
① HDFS 설계원칙
데이터를 많은 사용자가 네트워크 환경에서 이용하기 위해 개발된 분산파일시스템으로는 NFS (Network File System)가 대표적이다. 그러나 NFS는 하나의 기기에 보관된 하나의 논리볼륨 (logical volume) 만을 원격에서 액세스한다는 제한점을 가진다. HDFS는 이러한 NFS의 한계를 극복하기 위해 고안되었고 설계원칙 상 다음과 같은 특징을 가진다.
HDFS는 대용량 데이터 (terabyte 또는 petabyte)를 저장하도록 고안되었다. 이를 위해서 데이터를 여러 대의 컴퓨터에 나누어 저장시킨다. 즉, NFS보다 훨씬 큰 파일도 지원한다.
HDFS에서 데이터 저장의 신뢰성이 훨씬 높아서 개별 컴퓨터가 이상을 일으켜도 데이터를 이용할 수 있다.
HDFS는 데이터 액세스에 대한 성능개선도 용이하다. 클러스터에 컴퓨터 node만 추가하면 이용할 수 있는 클라이언트 숫자는 계속 늘어날 수 있다.
HDFS는 Hadoop의 MapReduce와 잘 통합된다.
반면 HDFS의 성능은 개선되었지만 설계원칙 상 불가피하게 특정 응용프로그램에는 적합하지 않은 결과를 초래한다. 즉, NFS만큼 범용은 아니라는 뜻이다. HDFS를 이용 시 다음의 상충되는 요소들을 함께 고려해야 한다.
HDFS는 파일을 순차적 스트리밍 방식으로 읽는 (long sequential streaming reads) 응용프로그램을 전제로 하였다. 따라서 무작위로 random access하는 경우에는 탐색시간 (seek times)이 길어지는 단점이 있다.
HDFS는 한번 기록한 후 읽기를 여러 번 반복하는 것(write-once, read-many)을 기준으로 하였다. (파일에 데이터를 추가하는 기능이 Hadoop 0.19부터 지원되기는 하지만 성능상 한계가 있다.)
작업 대상 파일의 크기가 크고 읽기 작업이 순차적으로 이루어지다 보니 HDFS에서는 데이터의 캐싱 (local caching)을 하지 않는다. 실제로 캐싱작업에서는 시스템의 부담이 커지므로 차라리 데이터의 소스로부터 읽기작업을 다시 실행하는 것이 오히려 더 나은 경우가 많다.
개별 기기가 장애를 일으키는 일이 빈번할 뿐 아니라 여러 대의 기기가 동시에 문제를 발생시키는 경우도 있으므로 (예: rack 의 장애로 인해 여러 대 컴퓨터가 동시에 동작하지 않는 경우) 클러스터는 이러한 것들을 견딜 수 있도록 해야 한다. 이 때 비록 일부 기기의 성능이 저하되는 한이 있더라도 시스템 전체가 느려지거나 데이터를 이용할 수 없는 결과가 초래되지 않도록 대책을 세워야 한다.
당초 HDFS는 GFS (Google File System)을 기초로 설계된 블록 기반의 (block-structured) 파일시스템이다. 따라서 각각의 파일을 일정한 크기의 블록(block)으로 나눈 후 클러스터 내의 여러 기기에 분산 저장하는데 이때의 개별 기기에는 DataNode라는 파일시스템 데몬이 동작한다. 이때 Hadoop은 이들 각각의 블록을 보관하는 컴퓨터를 블록 별로 (on a block-by-block basis) 무작위로 선택한다. 결과적으로 파일을 이용하는 데에는 여러 컴퓨터 사이의 협력이 필요해지는 대신 단일기기용 분산파일시스템보다는 지원하는 파일의 크기가 훨씬 커지는 장점이 있다.
파일을 이용하는데 여러 대 컴퓨터가 협력해야 한다는 점에서는 이들 중 한 대만 고장을 일으켜도 파일작업을 할 수 없게 된다는 문제가 발생하는데 HDFS에서는 각각의 블록을 여러 대의 컴퓨터에 중복하여 저장하는 (이때의 중복 저장하는 숫자를 replication factor라고 하며 3을 기본으로 하되 조정이 가능하다) 상식으로 이 문제를 해결한다.
대부분의 파일시스템에서 블록의 크기는 4 또는 8 KB이다. 반면 HDFS에서의 기본 (default) 블록사이즈는 64MB로서 훨씬 큰데 이로 인해 파일 당 필요한 메타데이터는 작아지는 결과가 초래된다 (파일 당 필요한 블록의 개수 자체가 줄어든다).
또한 HDFS에서는 데이터를 순차방식으로 고속 stream read하므로 대용량 데이터를 효율적으로 읽어 들일 수 있다. NTFS 또는 EXT 같은 일반 파일시스템에서는 파일의 평균 크기가 작다고 전제하고 있지만 HDFS는 크기가 큰 파일을 전제로 한다. 예컨대 100MB 크기의 파일이라고 해도 블록 2개면 충분하다. PC의 경우 파일 크기도 작고 이곳 저곳의 내용을 random하게 액세스하는 경우가 대부분이지만 HDFS는 프로그램이 블록을 처음부터 끝까지 읽어 들인다고 가정하였으며 이로 인해 MapReduce 스타일의 프로그래밍이 편리해진다.
HDFS에서의 데이터 파일을 처리하는 주된 기준은 레코드 단위이다. 즉, 입력파일을 레코드를 기준으로 절단(split)하며 각 프로세스는HDFS 파일의 위치에 따라 (이를 지역성(locality)이라 한다) 할당된 record만 처리하게 되는 것이다. 이는 일견 당연해 보이지만 실제로는 기존 데이터처리 방식과는 정 반대이다. 즉, 기존에는 작업대상 파일(즉, 스토리지)을 전산시스템의 중앙부에 놓고 – 이때 관리효율을 높이기 위해 SAN (Storage Area Network) 내지 NAS (Network Attached Storage)를 이용함 – 모든 컴퓨터 node는 이들 중앙의 데이터 중 필요한 부분을 가져와서 작업하고 결과를 다시 중앙 스토리지에 반환/저장하는 방식을 취하였다. 그러나 과정을 유기적으로 조정하기 위해 많은 통신 오버헤드 – 예컨대 socket 프로그램 내지 응용프로그램에서의 marshalling 등- 가 과도하게 발생하였다.
그러나 Hadoop에서는 데이터를 중앙에 모으는 대신 이를 처리할 컴퓨터에게 보내준다[1]는 (Moving computation to the data) 발상의 전환을 통해 기존방식에서의 관리부담 (overhead)이 원천적으로 사라지게 되었다.
Hadoop의 프로그래밍 프레임워크에서 데이터는 논리적 차원에서 레코드 단위로 처리(record-oriented)된다. 따라서 각각의 입력파일은 여러 개의 줄(line) 또는 별도로 응용프로그램의 로직에 의해 지정된 나름의 형식으로 분해된다. 클러스터 내의 각 node에서 수행되는 프로세스들 역시 이들 레코드 단위로 작업을 수행한다.
구체적으로는 대상 데이터 세트(dataset)[2]을 블록단위로 나누고 중복적으로 slave node에게 분배하는 한편 이들에 대한 MapReduce의 작업 결과를 읽거나 파일에 기록하는 일련의 파일작업을 포함한다. 다만, HDFS는 일반적인 Linux 의 파일시스템과는 독립된 것이므로 반드시 Hadoop 명령어를 통해서만 이를 관리할 수 있다.
일반적으로 Hadoop에서는 데이터파일을 Linux 파일로 생성한 후 이를 HDFS로 복사해 와서 작업하는 방식을 취한다. 그리고 그 파일 대해서 응용프로그램을 통해 MapReduce 작업을 수행할 때도 모든 작업은 HDFS 파일을 직접 다루기 보다는 MapReduce를 통해 (key/value)의 쌍으로 이루어진 record단위로 작업을 수행하는 방식을 취한다. 즉, 대부분의 경우 HDFS 파일에 대해 직접 기록하거나 읽는 대신 응용 프로그램에서의 MapReduce를 통해 파일작업이 진행되는 것이다.