상세 컨텐츠

본문 제목

HDFS 아키텍처 특징

Hadoop

by 견오수 2022. 1. 6. 15:50

본문

728x90

1.  HDFS 1.0 아키텍처 특징

 

  • HDFS는 블록 구조의 파일 시스템이며, HDFS에 저장하는 파일은 특정 크기의 블록으로 나눠져 분산된 서버에 저장이 된다.
  • 블록 크기는 기본적으로 64MB이며, 크기는 하둡 환경설정 파일을 수정하여 변경할 수 있다.
  • 여러 개의 블록은 동일한 서버에 저장되는 것이 아니라 여러 서버에 나눠서 저장되기 때문에 큰 규모의 데이터를 저장할 수 있다.

 

2. 디스크 블록 개념

 

  • 물리적인 디스크는 블록 크기란 개념이 있다. 블록 크기는 한 번에 읽고 쓸 수 있는 데이터의 최대량이다.
  • 보통 파일시스템의 블록의 크기는 KB이고, 디스크 블록의 크기는 기본적으로 512byte이다.

 

3. 블록의 크기가 왜 64MB나 되고, 일반적인 디스크 블록크기 보다 큰 이유는?

 

64MB, 128MB, 256MB …… 설정하는 이유 : 데이터를 메모리에 쌓을 때 비트를 낭비하지 않기 때문이다.

 

  • 첫째,디스크 시크 타임(seek time)의 감소 때문이다.
  • 디스크 탐색 시간 = 시크 타임(데이터의 위치를 찾는데 걸리는 시간) + 서치 타임(원하는 데이터의 섹터에 도달하는 데 걸리는 시간)
  • 하둡이 개발됐던 시기의 일반적인 디스크 시크 타임은 10ms, 디스크 전송 대역폭은 100MB/s였고, HDFS는 시크 타임이 디스크 전송 대역폭의 1%만을 사용하는데 주안점을 뒀기 때문에  100MB에 근접한 64MB를 사용함. (하둡 2.0128MB로 늘어남.)

 

  • 둘째, 네임노드가 유지하는 메타데이터의 크기 감소입니다.
  • 네임노드는 블록 위치, 파일명, 디렉토리 구조, 권한 정보와 같은 메타데이터 정보를 메모리에 저장하고 관리한다.
  • 블록의 크기가 작으면 저장해야 하는 메타 파일이 많아지면 네임노드 메모리 힙에 많은 영향이 가기 때문이다.

 

  • 셋째, 클라이언트와 네임노드의 통신 감소입니다.
  • 클라이언트가 HDFS에 저장된 파일을 접근할 때 네임노드에서 해당 파일을 구성하는 블록의 위치를 조회한다.
  • 클라이언트는 스트리밍 방식으로 데이터를 읽고 쓰기 때문에 특별한 경우를 제외하고는 네임노드와 통신할 필요가 없어집니다.

 

 

4. 200MB크기의 파일을 HDFS에 저장했을 경우

 

 

 

  • HDFS는 블록을 저장할 때 기본적으로 3개씩 블록의 복제본을 저장한다. 필요시 하둡 환경설정파일에서 복제본 수 설정이 가능하다.
  • 특정 서버의 하드디스크에 오류가 생기더라도 복제된 블록을 이용해 데이터 조회가 가능하다.
  • 크기가 작은 파일이더라도 무조건 64MB 크기의 블록을 차지하는 것이 아니라 크기에 맞게 블록이 저장된다.
  • 64MBHDFS10KB인 파일을 저장할 경우 해당 파일은 10KB 디스크 공간만을 차지한다.

 

5. 네임노드와 데이터노드

 

 

네임노드의 기능 –> 마스터 슬레이브(Master - Slave) 아키텍처이다.

 

  • 메타데이터 관리

네임노드는 파일 시스템을 유지하기 위한 메타데이터를 관리한다. 메타데이터는 파일 시스템 이미지(파일명, 디렉터리, 크기, 권한)와 파일에 대한 블록 매핑 정보로 구성됩니다. 네임노드는 클라이언트에게 빠르게 응답할 수 있게 메모리에 전체 메타 데이터를 로딩해서 관리한다.

 

  • 데이터노드 모니터링

데이터노드는 네임노드에게 3초마다 하트비트(heartbeat) 메시지를 전송한다. 하트비트는 데이터노드 상태 정보와 저장돼 있는 블록의 목록(blockreport)으로 구성이 된다.  네임노드는 하트비트를 이용해 데이터 노드의 실행 상태와 용량을 모니터링을 하고, 일정 기간 동안 하트비트가 오지 않는 데이터노드가 있을 경우 장애가 발생한 서버로 판단한다.

 

  • 블록관리

네임노드는 다양한 블록을 관리한다. 우선, 네임노드는 장애가 발생한 데이터 노드를 발견하면 해당 데이터노드의 블록을 새로운 데이터노드로 복제합니다. 또한 용량이 부족한 데이터노드가 있다면 용량에 여유가 있는 데이터 노드로 블록을 이동한다. 네임노드는 복제본 수도 관리한다. 만약 복제본 수와 일치하지 않는 블록이 발견될 경우 추가로 블록을 복제하거나 삭제해준다.

 

  • 클라이언트 요청 접수

클라이언트가 HDFS에 접근하려면 반드시 네임노드에 먼저 접속해야한다. HDFS에 파일을 저장하는 경우 기존 파일의 저장 여부와 권한 확인의 절차를 거쳐서 저장을 승인한다. 또한 HDFS에 저장된 파일을 조회하는 경우 블록의 위치 정보를 반환합니다.

 

  • 데이터 노드

데이터노드는 클라이언트가 HDFS에 저장하는 파일을 로컬 디스크에 유지합니다. 이때 로컬 디스크에 저장되는 파일은 두 종류로 구성된다. 첫 번째 파일은 실제 데이터가 저당돼 있는 로우 데이터이며, 두 번째 파일은 체크섬이나 파일 생성 일자와 같은 메타데이터가 설정돼 있는 파일입니다.

 

 

6. HDFS의 파일 저장 요청

 

 

  1. 하둡은 FileSystem이라는 추상 클래스에 일반적인 파일 시스템을 관리하기 위한 메서드를 정의한다. 그리고 이 추상 클래스를 상속받아 각 파일 시스템에 맞게 구현된 다양한 파일 시스템을 제공한다. HDFS에 파일을 저장하는 경우에는 파일 시스템 클래스 중  DistributedFileSystem을 사용하고 클라이언트는 DistributedFileSystemcreate 메서드를 호출해 스트림 객체를 생성한다.

  2. DistributedFileSystem은 클라이언트에게 반환할 스트림 객체로, FSDataOutputStream을 생성한다. FSDataOutputStream은 데이터노드와 네임노드의 통신을 관리하는 DFSOutputStream을 래핑하는 클래스이다. DistributedFileSystemDFSOutputStream을 생성하기 위해 DFSClientcreate 메서드를 호출한다.

  3. DFSClientDFSOutputStream을 생성한다. 이때 DFSOutputStreamRPC 통신으로, 네임노드의 create 메소드를 호출한다. 네임노드는 클라이언트의 요청이 유효한지 검사를 진행한다. 이미 생성된  파일이거나, 권한에 문제가 있거나, 현재 파일 시스템의 용량을 초과한다면 오류가 발생한다. 네임노드는 파일의 유효성 검사 결과가 정상일 경우 파일 시스템 이미지에 해당 파일의 엔트리를 추가한다. 마지막으로 네임노드는 클라이언트에게 파일을 저장할 수 있는 제어권을 부여한다.

  4. 네임노드의 유효성 검사를 통과했다면 DFSOutputStream 객체가 정상적으로 생성이 된다. DistributedFileSystemDFSOutputStream을 래핑한 FSDataOutputStream을 클라이언트에게 반환한다.

 

7. 패킷 전송

 

 

클라이언트가 네임노드한테 파일 제어권을 얻게 되면 파일 저장을 진행 한다. 이때 클라이언트는 파일을 네임노드에 전송하지 않고 각 데이터 노드에 전송을 한다. 저장할 파일은 패킷 단위로 나눠서 전송한다.  

 

  1. 클라이언트는 스트림 객체의 write 메서드를 호출해 파일 저장을 시작한다. DFSOutputStream은 클라이언트가 저장하는 파일을 64K 크기의 패킷으로 분할한다.

  2. DFSOutputStream은 전송할 패킷을 내부 큐인 데이터 큐에 등록을 한다. DFSOutputStream의 내부 스레드가 데이터 큐에 패킷이 등록된 것을 확인하면 DFSOutputStream의 내장 클래스인 DataStreamer는 네임노드의 addBlock 메서드를 호출한다.

  3. 네임노드는 DataStreamer에게  블록을 저장할 데이터 노드 목록을 반환한다. 이 목록은 복제본 수와 동일한 수의 데이터 노드를 연결할 파이프라인을 형성한다.  EX) HDFS 복제본 수가 3으로 설정돼 있다면 데이터 노드 3개가 파이프 라인을 형성합니다.

  4. DataStreamer는 파이프라인의 첫 번째 데이터 노드부터 패킷 전송을 시작한다. 데이터 노드는 클라이언트와 다른 데이터 노드로부터 패킷을 주고받기 위해 DataXceiverServer 데몬을 실행한다. DataXceiverServer는 클라이언트  및 다른 데이터노드와 패킷 교환 기능을 제공한다.

  5. 첫 번째 데이터노드는 패킷을 저장하면서, 두 번째 데이터 노드에게 패킷을 저장을 요청하고, 두 번째 데이터 데이터노드도 패킷을 저장하면서 세 번째 데이터노드에게 패킷 저장을 요청한다. 마지막 데이터 노드는 패킷을 저장한다. 패킷을 저장할 때 DFSOutPutStream은 내부 큐인 승인 큐에 패킷을 등록을 하고 데이터 노드한테 패킷을 받았다는 ACK 신호가 오면 큐에서 하나씩 패킷을 제거한다.

  6. 각 데이터 노드는 패킷이 정상적으로 저장이 되면 패킷을 전송한 데이터 노드에게 ACK 메시지를 전송을 한다. ACK 메시지는 파이프 라인을 통해 DFSOutPutStream에게 전달을 한다.

  7. 각 데이터 노드는 패킷 저장이 완료되면 네임 노드의 blockReceived 메서드를 호출한다.

  8. DFSOutputStream의 내부 스레드인 ResponseProcessor는 파이프라인에 있는 모든 데이터 노드로부터 승인 메시지를 받게 되면  해당 패킷을 승인 큐에서 제거한다. 만약 패킷을 전송하는 와중에 장애가 발생이 되면 승인 큐에 있는 모든 패킷을 데이터 큐로 이동을 한다. 네임노드한테 장애가 발생한 데이터 노드가 제거된 새로운 데이터 노드 목록을 받고 새로운 파이프 라인을 생성 후 패킷 전송 작업을 시작한다.      

 

8. 파일 닫기

 

  1. 클라이언트는 DistributdFileSystemclose 메서드를 호출해 닫기를 요청합니다.

  2. DistributdFileSystemDFSOutputStreamclose 메서드를 호출한다. DFSOutputStream에 남아 있는 모든 패킷을 파이프라인으로 플러시(flush) 한다.

  3. DFSOutputStream은 네임노드의 complete 메서드를 호출해 패킷이 정상적으로 저장됐는지 확인한다. 네임 노드의 최소 블록 복제본 수만 저장됐다면 complete 메서드는 true를 반환을 하고 true면 저장이 완료된 것으로 설정한다.

 

9. HDFS의 파일 읽기 파일 조회 요청

 

 

  1. 클라이언트는 DistributedFileSystemopen 메서드를 호출해 스트림 객체 생성을 요청한다.

  2. DistributedFileSystemFSDataInputStream 객체를 생성한다.  이때 FSDataInputStreamDFSDataInputStreamDFSInputStream을 차례대로 래핑 한다. DistributedFileSystem은 마지막에 래핑이 되는 DFSInputStream을 생성하기 위해 DFSClientopen 메서드를 호출합니다.

  3. DFSClientDFSInputStream을 생성한다. 이때 DFSInputStream은 네임 노드의 getBlockLocations 메서드를 호출해 조회 대상 파일의 블록 위치 정보를 조회한다. 참고로 DFSInputStream은 한 번에 모든 블록을 조회하지 않고, 기본 블록 크기의 10배수 만큼 조회한다.  예를 들어, HDFS 기본 블록 크기가 64MB이면 640MB의 블록을 조회한다.

  4. 네임노드는 조회 대상 파일의 블록 위치 목록을 생성한 후 목록을 클라이언트에 가까운 순으로 정렬한다. 정렬이 완료되면 DFSInputStream에 정렬된 블록 위치 목록을 반환한다. DistributedFileSystemDFSClient로부터 전달 받은 DFSInputStream을 이용하여 FSDataInputStream으로 생성해서 클라이언트에게 반환한다.

 

10. 블록 조회

 

 

  1. 클라이언트는 입력 스트림 객체의 read 메서드를 호출해 스트림 조회를 요청한다.

  2. DFSInputStream은 첫 번째 블록과 가장 가까운 데이터 노드를 조회한 후, 해당 블록을 조회하기 위한 리더기를 생성한다. 클라이언트와 블록이 저장된 데이터 노드가 같은 서버에 있다면 로컬 블록 리더기인 BlockReaderLocal 생성, 데이터 노드가 원격에 있을 경우 RemoteBlockReader 생성.

  3. DFSInputStream은 리더기의 read 메서드를 호출해 블록을 조회하고 BlockReaderLocal은 로컬 파일 시스템에 저장된 블록을 DFSInputStream에게 반환을 한다. RemoteBlockReader는 원격에 있는 데이터노드에게 블록을 요청하고 DataXceiverServer가 블록을 DFSInputStream에게 반환. 참고로 DFSInputStream은 조회한 데이터의 체크섬을 검증하고 문제가 있으면 다른 데이터 노드에게 블록 조회 요청.

  4. DFSInputStream은 파일을 모두 읽을 때 까지 블록을 조회하고 그 후 네임노드는 정렬된 블록의 위치 목록을 반환한다.

 

11. 입력 스트림 닫기

 

 

  1. 클라이언트는 입력 스트림 객체의 close 메서드를 요청해 스트림 닫기를 요청한다.

  2. DFSInputStream은 데이터 노드와 연결돼 있는 커넥션을 종료한다. 그리고 블록 조회용으로 사용했던 리더기도 닫아준다.

12. 보조 네임 노드

 

네임노드에서 메타데이터를 메모리에서 처리 -> 메모리에만 데이터를 유지하면 서버가 재부팅 될 경우 메타데이터가 유실 될 수 있음 -> HDFS는 이러한 문제점을 극복하기 위해 editslogfsimage 라는 2개의 파일을 생성.

 

  1. editslogHDFS의 모든 변경 이력을 저장을 함. HDFS는 클라이언트가 파일을 저장, 삭제, 파일 이동하는 경우 메모리에 로딩돼 있는 메타데이터에 기록한다.

  2. fsimage는 메모리에 저장된 메타데이터의 파일 시스템 이미지를 저장한 파일이다.

 

네임노드가 구동될 경우 다음과 같은 단계로 2개의 파일을 사용

 

  1. 네임노드가 구동되면 로컬에 저장된 fsimageeditslog를 조회한다.
  2. 메모리에 fsimage를 로딩해 파일 시스템 이미지를 생성한다.
  3. 메모리에 로딩된 파일 시스템 이미지에 editslog 기록된 변경 이력을 적용한다.
  4. 메모리에 로딩된 파일 시스템 이미지를 이용해 fsimage 파일을 갱신한다.
  5. editslog를 초기화 한다.
  6. 데이터노드가 전송한 블록리포트를 메모리에 로딩된 파일 시스템 이미지에 적용한다.

*(주의)

 

위 단계를 평상시에 아무런 문제가 없지만 editslog의 크기가 클 경우 문제가 될 수 있다. 왜냐하면 editslog는 별도의 크기 제한이 없기 때문에 무한대로 커질 수 있어서 3번 단계를 진행할 때 많은 시간이 소요가 된다. -> 해결하기 위해 HDFS는 보조네임노드(Secondary Name Node)가 주기적으로  fsimage를 갱신하는 역할을 하며 이러한 작업을 체크포인트(checkpoint)라고 한다. 그래서 보조네임노드를 체크포인팅 서버라고도 한다.

 

 

 

 

  1. 보조네임노드는 네임노드에게 editslog를 롤링할 것을 요청한다.(로그 롤링은 현재 로그 파일의 이름을 변경하고 원래 이름으로 새 로그 파일을 만드는 것이다).
  2. 네임노드는 기존 editslog를 롤링한 후, editslog.new를 생성한다.
  3. 보조네임노드는 네임노드에 저장된 롤링된 editslogfsimage를 다운로드 한다.
  4. 보조네임노드는 다운받은 fsimage를 메모리에 로딩하고, editslog에 있는 변경이력을 메모리에 로딩된 파일 시스템 이미지에 적용한다. 메모리에 갱신이 완료되면 새로운 fsimage를 생성하며, 이 파일을 체크포인팅할 때 사용한다. fsimage.ckpt로 생성.
  5. 보조네임노드는 fsimage.ckpt를 네임노드에게 전송을 한다.
  6. 네임노드는 로컬에 저장돼 있던 fsimage를 보조네임노드가 전송한 fsimage.ckpt로 변경을 한다. 그리고 editslog.new 파일명을 editslog로 변경한다.

참고로 체크포인팅은 1시간마다 한번씩 일어나며, 하둡 환경설정 파일에서 fs.checkpoint.period 속성에서 변경 가능.

하둡을 운영할 때 보조네임노드도 editslog 용량을 체크 해야 한다.

 

728x90

'Hadoop' 카테고리의 다른 글

맵리듀스(MapReduce) 개념 정리  (0) 2023.07.29
7. 빅데이터 실시간 적재 - HBase & Redis  (0) 2021.10.18
6. 빅데이터 적재 개요  (0) 2021.09.16
5. 아파치 플럼과 카프카란?  (1) 2021.09.13
4. 빅데이터 수집 개요  (0) 2021.09.13

관련글 더보기

댓글 영역