Hadoop의 코어 프로젝트(Framework)인 하둡 분산형 파일 시스템에 대해 정리해보겠습니다.
하둡의 저장소을 담당한다. (MapReduce는 하둡의 계산을 담당)
하둡 분산형 파일 시스템이란 의미로, Hadoop 네트워크에 연결된 기기에 데이터를 저장하는 분산형 파일 시스템이다.
범용 하드웨어로 구성된 클러스터에서 실행되고, 데이터 액세스 패턴을 스트리밍 방식으로 지원하여 매우 커다란 파일을 저장할 수 있도록 설계된 파일 시스템이다.
Hadoop Framework를 위해 Java로 작성된 분산 확장 파일 시스템이다. HDFS는 여러 머신에 대용량의 파일들을 나눠서(분산처리) 저장을 하게 된다. 여러 서버에 분산 및 중복 저장을 하기 때문에 서버에 오류가 발생하여도 다른 서버에서 복구할 수 있다. (데이터 안정성을 얻음)
(출처 : http://www.incodom.kr/hadoop_%EC%B4%9D%EC%A0%95%EB%A6%AC)
Apache Hadoop의 부사장인 아룬 머시는 하둡에서는 하둡 네트워크에 연결된 아무 기기에나 데이터를 밀어 넣는다고 표현했다. 관계형 데이터베이스 시스템인 RDBMS(외부, 개념, 내부 스키마를 통한 체계적으로 구성된 DB 시스템)에 비하면 HDFS는 돼지우리라고 표현할 정도이다. 하지만 Hadoop은 분산형 파일시스템을 통하여 대용량의 파일을 Block 구조로 우겨 넣을 뿐이다.
분산형 파일시스템은 기존의 분산처리시스템과는 다르다!! 여러 대의 머신이 데이터를 처리한다는 점에서 같지만 MPI(Message Passing Interface)를 사용하는 기존의 분산처리시스템은 일부 컴퓨터에 오류가 발생할 시 시스템이 동작하지 않고, 인터페이스가 복잡하여 프로그래밍하기 힘든 문제가 존재한다.
BUT 하둡 시스템의 구성요소 중 하나인 분산형 파일시스템은 데이터를 분산처리한 후 3개의 복제를 나누어 저장한다. 따라서 한 컴퓨터에서 오류가 발생하여도 다른 서버에서 데이터를 접근할 수 있다는 차이점이 있다.
파일을 Block 단위로 나눠서 저장한다. (기본 : 64MB)
- 추상화 단위로 파일보다 Block을 사용하는 것이 스토리지 서브시스템을 단순하게 만듬. -> 단순화는 모든 시스템에서 추구하는 방식이지만 장애 유형이 너무나도 다양한 분산 시스템에 서는 더더욱 중요하다.
- 오류 허용 오차(Fault-Tolerance)와 가용성(Availability)을 제공하기 위한 복제(Replication)를 효율적으로 수행할 수 있게 한다.
Block을 다중 노드에 분산해서 저장 -> 파일 하나가 네트워크에 있는 어떤 하나의 디스크보다 더 커질 수 있음
하나의 Block을 여러 노드에 복제
HDFS는 데이터를 저장하면, 다수의 노드에 복제 데이터도 저장하기 때문에 데이터의 유실을 방지한다.
HDFS에 파일을 저장 or 저장된 파일을 조회하려면 스트리밍 방식으로 데이터에 접근해야한다.
한번 저장한 데이터는 수정 X -> 읽기만 가능하여 데이터의 무결성을 유지한다.
데이터의 수정 X -> BUT 파일의 읽기, 이동, 복사, 삭제할 수 있는 Interface(쉘 스크립트)를 제공한다.
(출처 : https://opentutorials.org/course/2908/17055)
HDFS는 마스터(master) / 슬레이브(slave) 구조를 가진다.
HDFS에서 마스터 역할 -> NameNode 서버 1대
HDFS에서 슬레이브 역할 -> DataNode 서버 여러 대로 구성
Block 구조의 파일 시스템으로, 저장하는 파일은 특정 사이즈의 Block으로 나눠져 분산된 서버에 저장되게 된다.
하나의 Block은 3개로 복제되며 (수정 가능), 각각 다른 HDFS의 노드에 분산 저장된다.
HDFS 클러스터
- 하나의 NameNode & FileSystem을 관리
- 클라이언트의 접근을 통제하는 Master Server로 구성
- 클러스터의 각 노드들에는 DataNode가 하나씩 존재하고, 이 DataNode는 실행될 때 마다 Node의 추가되는 스토리지를 관리
- HDFS는 네임스페이스를 공개해서 유저 데이터가 파일에 저장되는 것을 허용
NameNode
- HDFS의 모든 메타데이터(Block들이 저장되는 디렉토리의 이름, 파일명 등...)을 관리
- 클라이언트가 메타데이터를 이용하여 HDFS에 저장된 파일에 접근 가능
- 파일과 디렉토리의 읽기(open), 닫기(close), 이름 바꾸기(rename) 등 파일 시스템의 네임스페이스의 여러 기능을 수행하고, DataNode와 Block들의 매핑을 결정
DataNode
- 주기적으로 NameNode에서 블록 리포트(노드에 저장되어 있는 블록의 정보)를 전송 -> 이를 통해 NameNode는 DataNode가 정상 동작하는지 확인
- 파일 시스템의 클라이언트가 요구하는 읽기(read), 쓰기(write) 기능을 담당 -> DataNode는 NameNode에서의 생성, 삭제, 복제 등과 같은 기능도 수행
하둡 어플리케이션은 HDFS에 파일을 저장하거나, 저장된 파일을 일기 위해 HDFS 클라이언트를 사용하며, 클라이언트는 API 형태로 사용자에게 제공된다.
★ 클라이언트는 NameNode에 접속해서 원하는 파일이 저장된 Block의 위치를 확인 -> 해당 블록이 저장된 DataNode에서 직접 데이터를 조회한다.
NameNode & DataNode는 GNU/Linux OS를 기반으로 하는 머신에서 실행하기 위해 설계된 소프트웨어의 일부이다. HDFS는 Java언어를 사용하므로 Java가 동작하는 어떠한 컴퓨터에서 NameNode와 DataNode 소프트웨어를 실행할 수 있다.
(출처 : https://628story.tistory.com/3)
NameNode (Master)
NameNode는 HDFS에서 마스터의 역할, 슬레이브 역할인 DataNode에게 I/O 작업을 할당 -> NameNode는 메타데이터를 관리하기 위해 EditLog & FsImage 파일을 사용
- EditLog : HDFS의 메타데이터에 대한 모든 변화를 기록하는 로그 파일으로 NameNode의 로컬에 저장
- FsImage : 파일 시스템의 네임스페이스(디렉토리명, 파일명, 상태 정보)와 파일에 대한 블록 매핑 정보를 저장하는 파일로 NameNode의 로컬에 저장 된다. 하지만 이 위치정보는 시스템 시작과 동시에 DataNode로부터 재구성되기 떄문에 NameNode가 블록의 위치 정보를 지속적으로 저장하지는 않는다.
NameNode를 실행 중인 장비가 손상되면 DataNode에 저장된 블록으로부터 파일을 재구성하는 방법을 알 수 없기 때문에 파일시스템의 모든 파일을 찾을 수 없게 됨 -> 이러한 이유로 NameNode는 장애복구 능력을 갖추는 것이 중요하고, 하둡은 이를 위해 2가지 매커니즘을 제공한다.
- 파일시스템 메타데이터의 지속 상태를 보완해주는 파일을 백업 & 일반적인 구성 선택 사항은 원격의 NFS 마운트에도 쓰고 동시에 로컬 디스크에도 쓴다.
- Secondary NameNode를 운영. BUT Secondary NameNode의 상태는 NameNode의 상태에 뒤쳐지기 대문에 NameNode Data에 총체적인 장애가 발생하게 되면 어느정도의 데이터 손실이 발생 (즉 Secondary NameNode를 사용해도 데이터의 손실이 발생) -> 이럴 때 일반적인 복구 과정은 NFS에 복제되는 NameNode의 메타데이터 파일을 Secondary NameNode에 복사하여 최신 네임스페이스 이미지로 병합하고 이것들을 새로운 NameNode에서 실행하면 된다.
- Hadoop 2.x Release 부터 이 문제를 해결하기 위해 한 쌍의 NameNode를 활성화-대기 상태로 구성함 -> HDFS 고가용성을 지원함 (아키텍처의 변화가 있음!!)
Secondary NameNode
- 주된 역할로는 EditLog가 너무 커지지 않도록 주기적으로 네임스페이스 이미지를 EditLog와 병합
- HDFS의 블록이 변경되더라도 실시간으로 변경정보를 갱신 X -> Secondary NameNode는 NameNode의 블록정보를 합칠 때 사용하기 위한 노드이다! (NameNode의 백업 노드가 아님!!)
- Secondary NameNode는 주기적으로 NameNode의 파일 시스템 이미지 파일을 갱신하는 역할을 하며, 이러한 작업을 체크포인트 라고 한다. 따라서 Secondary NameNode = 체크포인팅 서버 라고 표현하기도 함
DataNode (Slave)
- 실제 데이터는 블록으로 쪼개 DataNode에 저장
- 클라이언트가 HDFS에 파일을 읽거나 쓰기 위해 NameNode에게 요청 -> NameNode는 어느 DataNode의 어디 블록에 파일이 있는지 위치 알려줌 -> 클라이언트는 DataNode와 직접 통신하여 파일을 읽거나 씀
즉, DataNode와 블록 위치가 정해지면 클라이언트는 NameNode와 전혀 통신하지 않고, 해당 DataNode와 직접 통신한다!
- 클러스터가 처음 시작될 때, 각 DataNode에서 자신의 블록 정보를 NameNode에게 알려줌
- DataNode는 주기적으로 NameNode에게 Heartbeat 와 블록의 목록이 저장된 블록 리포트 를 보냄. 또한 자신의 로컬 디스크에 변경사항이 발생할 때 마다 NameNode에게 변경사항을 알려주게 됨.
Heartbeat : DataNode는 NameNode에게 하트비트를 3초마다 보냄. 하트비트에는 디스크 가용 공간 정보, 데이터 이동, 적재량 등의 정보가 들어있다. // HandShaking에 사용되며 10초 이상 하트비트를 받지 못하면 사용할 수 없는 DataNode라고 인식됨!!
JobTracker
- JobTracker란 TaskTracker의 리소스가 이용 가능한지, 얼마나 사용되고 있는지 등을 관리하는 리소스 관리 기능을 수행한다.
- 실제 분석을 수행하는 MapReduce Job을 배포하고, 스케줄링, 모니터링하는 실행 관리 기능 -> 만약 어느 노드에서 Task가 실패하면 Task를 다른 노드에 재할당하고 재실행 하도록 함.
- 일반적으로 JobTracker는 Master Node 즉, NameNode가 설치된 노드에서 실행!!
TaskTracker
- Task를 실제로 처리하는 일은 TaskTracker가 수행.
- DataNode에는 오직 하나의 TaskTracker만 존재. -> 여러개의 JVM을 생성하여 다수의 Map & Reduce를 실행하게 됨.
- TaskTracker는 동시에 여러개의 Task를 수행 가능. -> 서버당 몇 개의 Task를 동시에 수행할 것인지 환경설정으로 설정 가능하다.
- 만약 TaskTracker에 문제가 발생하거나, 새로운 TaskTracker가 추가되면 JobTracker는 자동으로 이를 인식 -> TaskTracker를 추가 및 제거 작업을 수행함.
- 장애가 발생한 TaskTracker의 작업은 다른 TaskTracker에게 재할당 -> 새롭게 배정받은 TaskTracker에서 Task 재시작 -> BUT TaskTracker에서 장애가 발생하는 경우 HDFS와 동일하게 현재 수행중인 Task 모두 실패 처리 된다!
어플리케이션이 HDFS 클라이언트에게 파일 저장을 요청 -> HDFS 클라이언트는 NameNode에게 파일 블록들이 저장될 경로 생성을 요청 -> NameNode는 해당 파일 경로가 존재하지 않으면 경로를 새로 생성 -> 다른 클라이언트가 해당 경로를 수정하지 못하도록 Lock을 검 (보안 & 무결성 유지) -> NameNode는 클라이언트에게 해당 파일 블록들을 저장한 DataNode의 목록을 반환
클라이언트는 1번째 DataNode에게 데이터를 전송
1번째 DataNode는 데이터를 로컬에 저장한 후 -> 데이터를 2번째 DataNode로 전송
2번째 DataNode는 데이터를 로컬에 저장한 후 -> 데이터를 3번째 DataNode로 전송
(6번 포함) 로컬에 데이터를 저장하였으면 자기에게 데이터를 넘겨준 DataNode (이전의 DataNode)에게 데이터의 로컬 저장이 완료 되었음을 응답 (ACK 신호로 알려준다. -> "데이터 복제 잘 됬고 저장 잘 됬어~" 라는 의미)
어플리케이션이 클라이언트에게 파일 읽기를 요청
클라이언트는 NameNode에게 요청된 파일이 어떤 블록에 저장되어 있는지의 정보를 요청
메타데이터(디렉토리명, 파일명 등)를 통해 파일이 저장된 블록 리스트를 반환
클라이언트는 DataNode에 접근하여 블록 조회 요청
DataNode는 클라이언트에게 요청된 블록을 전송
클라이언트에서 어플리케이션에 데이터를 전달
클라이언트로부터 작업요청을 받은 JobTracker는 TaskTracker 별로 처리할 작업목록을 구성
TaskTracker는 주기적으로 Heartbeat를 전송하고, JobTracker는 이 메시지의 반환값에 처리할 작업 ID를 반환
작업 ID를 부여받은 TaskTracker는 관련된 작업의 정보를 하둡 파일시스템에서 가져오고, 수행할 프로그램도 하둡 파일시스템으로부터 로컬에 저장
TaskTracker에서는 fork(복제) 명령을 이용해 Map과 Reduce를 실행하고, JobTracker에게 메시지를 전달하면서 파일에 대한 변경사항은 DataNode와 통신 -> 다시 NameNode에게 파일 블럭에 대한 정보를 전달