Apache Hadoop: HDFS

아파치 하둡(Apache Hadoop)은 대량의 데이터를 분산 스토리지에 저장하고 이를 분산 처리하는 프레임워크 또는 에코시스템이다. 보통 하둡이 HDFS라고 생각할 수 있는데, 다시 생각해보면 HDFS는 하둡 에코시스템에 포함된 하나의 개념이다. 하둡은 HDFS와 YARN, MapReduce 등이 있는 에코시스템이다. 여기서 YARN은 리소스 관리를 담당하고 MapReduce는 데이터를 분산 처리를한다. 이 하둡 에코시스템 중 HDFS에 대해서 살펴보자. 모든 정리는 현재 내가 직접 맞닿아 있는 업무 시스템 구성에 따른다. 따라서 아파치 하둡의 다른 구성과는 정리가 조금 다를 수 있다. 그래도 큰 틀에서는 벗어나지 않을 것으로 보인다. 

HDFS Architecture

HDFS의 구조를 살펴보자. 참고로 살펴볼 HDFS의 구조는 HDFS High Availability with QJM 로서 문서를 보면 보다 명확히 이해할 수 있다. 이 시스템 구조는 HA를 위해 스탠바이 노드(Standby Node)와 저널 노드(Journal)를 추가로 가지고 있다. 여기서 스탠바이 노드와 저널 노드에 대해서 얘기하기 전에 HDFS의 기본 구조에 대해서 먼저 정리하자.

HDFS Namenode and Datanode

HDFS는 우리가 익히 알고 있는 마스터(Master)-슬레이브(Slave) 구조다. 요즘에는 슬레이브가 아닌 다른 명칭을 사용하기도 하지만 다 같은 얘기다. HDFS에서는 마스터 노드를 네임 노드(Name node, NN)로 부르고 슬레이브 노드를 데이터 노드(Data node, DN)으로 부른다. 마스터 - 슬레이브 구조와 같이 네임 노드가 하나 존재하고 다수의 데이터 노드가 존재한다. 그리고 네임 노드와 데이터 노드들 간의 통신하며 시스템을 이룬다. 이 구조에서 핵심은 네임 노드가 연결된 데이터 노드들을 관리한다는 점이다. 네임 노드에서 관리하는 데이터 노드들 중 원활하지 못한 상황의 데이터 노드가 있다면 해당 데이터 노드를 제외시킨다. 네임 노드가 데이터 노드에 대한 상태를 파악할 수 있는 이유는 데이터 노드가 주기적으로 네임 노드에게 헬스체크(Heartbeat)를 하기 때문이다. 사실 데이터 노드가 헬스 체크를 위해 Hearbeats 데이터를 보내기도 하지만 Block Report라고 하는 데이터도 보내기도 한다. 여기서 데이터 노드가 네임 노드를 인식할 수 있는 이유는 데이터 노드를 구성할 때 네임 노드에 대한 정보를 설정해야하기 때문이다. 만약 HDFS의 HA 구성에서는 네임 노드와 별도로 스탠바이 네임 노드(Standby Node)가 존재하기 때문에 데이터 노드 설정 파일에 이 두 노드들에 대한 정보를 입력해야한다.

그러면 데이터 노드들의 상태는 헬스체크(Heartbeats)라는 매커니즘을 통해 파악할 수 있지만, 네임 노드에 대한 상태는 어떻게 판단할까. 네임 노드에 대한 상태 판단은 주키퍼(Apache Zookeeper)가 한다. 주키퍼를 HDFS 시스템에 별도로 구성하여 네임 노드에 대한 상태를 파악한다. 만약 네임 노드의 상태가 원할하지 않으면 스탠바이 네임 노드를 활성화시켜 HA 목적을 달성한다. 주키퍼가 어떻게 네임 노드에 대한 상태 파악을 하는지는 나중에 다시 정리해보고 여기서 중요한 부분은 스탠바이 노드가 활성화되는 과정이다. 스탠바이 노드가 활성화하기 전에 세이프 모드(Safe Mode)로 진입하게 되는데, 이 세이프 모드 상태에서 네임 노드로서 역할을 하기 위해 준비하는 과정이 필요하다. 준비하는 과정은 FS Image 파일과 Edit Log 파일들을 읽어 합치는 과정을 거치고 네임 노드의 메모리에 이 데이터를 저장한다. 그리고 이 과정에서 데이터 노드들로부터 받아온 Block Report 데이터를 메모리에 저장하기도 한다. FS Image, Edit Log, Block Report가 어떤 데이터인지는 나중에 설명하겠다. 결과적으로 이 세이프 모드 상태에서 네임 노드로서의 준비 과정이 끝나야만 활성화가 될 수 있다. 

여기까지 간단하게 요약하면 HDFS 구조는 네임 노드와 다수의 데이터 노드들로 이뤄져있고 네임 노드가 데이터 노드들의 상태에 따라 이를 관리한다. HDFS의 HA를 위해 네임 노드와는 별도로 스탠바이 노드와 저널 노드가 있으며 네임 노드가 원할하지 못한 상황일 때, 스탠바이 노드가 네임 노드로 활성화 된다. 네임 노드의 상태를 파악하기 위해 주키퍼라는 별도의 구성이 필요하다.

Namenode

앞서 네임 노드가 데이터 노드들을 관리한다고 정리했다. 이외의 어떤 역할을 하는지 정리해보자. 먼저 클라이언트(Client)로부터의 모든 요청은 네임 노드가 처리한다. 데이터(HDFS에서는 파일)의 읽기 작업과 쓰기 작업은 반드시 네임 노드를 먼저 거쳐야만 이뤄질 수 있다. 파일 읽기와 쓰기 작업에서 파일이 있는지, 파일을 쓸 수 있는 권한이 있는지에 대한 모든 작업이 이 네임 노드에서 이뤄진다. 다시 생각하면 네임 노드는 HDFS에 저장된 모든 파일들에 대한 데이터를 가지고 있다. 여기서 모든 파일들에 대한 데이터는 어떤 데이터고 어떻게 네임 노드가 가지고 있는지 이해가 필요하다.

네임 노드는 요청을 처리하기 위해 HDFS의 모든 파일들에 대한 이름, 크기, 파일의 계층 구조 및 파일이 저장된 위치 데이터를 네임 노드의 메모리에 저장하고 있다. 네임 노드가 이러한 데이터들이 있어야 파일을 쓰고 읽는 작업을 할 수 있다. 한 가지 유의할 점은 여기서 네임 노드가 원인 모를 이유로 죽어버렸을 때다. 앞서 얘기했듯이 스탠바이 노드가 네임 노드로 활성화가 될텐데 어떻게 네임 노드의 메모리에 있는 데이터를 똑같이 구성할 수 있을까. 이 부분에 설명하기 전에 파일 쓰기 및 읽기 작업에 대해서 알아보자.

File Read & Write Operation

파일 쓰기 작업은 먼저 네임 노드가 해당 파일이 HDFS에 존재하는 확인하고 파일을 쓸 수 있는 권한이 있는지 확인한다. 파일에 대한 권한은 우리가 익히 알고 있듯이 유닉스 계열의 파일 시스템의 권한과 비슷하다. 모든 확인이 끝난 후, 네임 노드는 해당 파일의 크기, 파일 시스템 상의 위치 등의 메타데이터(Metadata)를 Edit Log 데이터를 적재한다. 여기서 Edit Log는 모든 파일 쓰기 작업을 포함한 파일에 변경에 대한 이력을 남기는 transaction log 데이터다. 네임 노드는 실제 파일 데이터를 데이터 노드에 전송하기 전에 이 Edit Log 데이터를 먼저 저장한다. 그 이후 네임 노드의 메모리에 저장된 데이터에도 해당 쓰기 작업에 대한 데이터를 갱신한다. 마지막으로 앞서 요청한 클라이언트에게 파일 데이터를 전송할 수 있도록 데이터 노드들에 대한 데이터를 반환한다. 클라이언트는 주어진 정보를 바탕으로 파일 데이터를 전송한다. 데이터 노드들은 파일이 다 적재가 되면 네임 노드에게 이를 알린다. 네임 노드는 이에 따라 파일이 저장이 끝난 이력을 Edit Log에 적재하고 메모리에 저장된 데이터 갱신한다. 

여기서 데이터 노드들이 하나의 파이프라인(Pipeline)을 구성하여 파일 데이터가 데이터 노드들에 저장이 된다고 하지만, 여기서 확실히 알아야할 점은 블락(block)과 레플리케이션(replication)다. 하나의 파일은 다수의 블락들로 나누어져 저장이 된다. 그리고  레플리케이션의 수에 따라 복사된 데이터도 저장이 된다. 이 부분을 통해 HDFS가 분산 스토리지인 것을 알 수 있다. 하나의 파일 데이터를 다수의 블락들로 분산하여 저장한다. 추후 MapReduce와 같은 분산 처리 시스템으로 해당 데이터들을 분산 처리한다.

데이터 읽기 작업은 데이터 쓰기 작업과 비슷하다. 먼저 데이터 읽기 요청이 네임 노드에게 전달이 된다. 네임 노드는 해당 데이터가 존재하는지 확인한다. 해당 데이터가 HDFS에 있다면 네임 노드는 데이터를 읽을 수 있도록 데이터의 블락들과 데이터 노드들의 정보를 반환한다. 클라이언트는 해당 정보를 이용하여 직접 데이터 노드에서 데이터를 읽는다. 여기서 알아야 할 점은 데이터의 블락들과 데이터 노드들의 정보를 네임 노드로부터 받은 이후다. 해당 정보를 가진 클라이언트는 더 이상 네임노드를 거치지 않고 바로 데이터 노드들과 파이프라인을 구성하여 데이터를 읽을 수 있다.

Checkpoint

네임 노드는 모든 데이터에 대한 이름, 크기, 파일의 계층 구조 및 파일이 저장된 위치 데이터를 메모리에 저장한다. 이러한 데이터를 메타데이터라고 하는데, 메모리는 휘발성으로 영구적인 저장 시스템이 아니다. 따라서 네임 노드가 가진 이러한 메타데이터를 주기적으로 영구적인 저장소를 저장해야한다. 왜 저장해야하냐고, 데이터에 대한 메타데이터를 잃어버리면 데이터의 존재 유무도 알 수 없고 접근도 불가능하기 때문이다. 네임 노드가 메모리로 가지고 있는 모든 메타데이터를 하나의 파일로 적재하는데, 이 파일을 FS Image(fsimage) 라고 한다. 그리고 체크포인트는 이전에 저장한 fsimage와 네임 노드 메모리에 새롭게 저장한 메타데이터를 합치는 작업이다. 즉, 체크포인트 과정을 통해 fsimage를 주기적으로 최신의 상태로 만들어주는 것이다. 앞서 HA 구성을 통해 네임노드가 죽었을 때, 스탠바이 노드가 새로운 네임 노드로 역할이 바뀐다고 말했다. 이 과정에서 fsimage를 통해서 네임 노드가 죽기 전에 저장한 HDFS의 메타데이러를 가져올 수 있다. 마지막 체크포인트 시점과 네임 노드가 죽었을 때의 시점에서의 데이터는 edit log를 통해 복구할 수 있다.