하둡 완벽 가이드 책에서 HDFS 에 대해 공부 한 내용을 여기 적는다.

 

 

- HDFS 기본 block size 는 (20년 7월 29일 기준) 128mb 이다.

 

- 원본 데이터가 block size 보다 작아도 disk 에 block size만큼의 데이터를 사용하지 않는다.

예를 들어 block size 128mb, 원본 데이터가 1mb 일 때

디스크에서 사용되는 용량을 1mb 이다.

 

- block size 가 큰 이유는, 탐색 비용을 최소화하기 위함이다.

block size 가 크니까 block 의 시작점을 탐색하는 데 걸리는 시간을 줄일 수 있고

데이터 전송에 더 많은 시간을 할애할 수 있다.

 

- Name Node (NN) 은 파일 시스템의 네임스페이스를 관리한다.

파일 시스템 트리와 그 트리에 포함된 모든 파일과 디렉터리에 대한 메타데이터를 유지한다.

이는 namespace iamge 와 edit log 라는 두 종류의 파일로 로컬 디스크에 영구 저장된다.

데이터의 위치는 시스템이 재시작할 때 DataNode(DN)로부터 받기 때문에 영구 저장되지 않는다.

 

- HDFS Client 는 사용자를 대신해 NN와 DN 사이에서 통신하고 파일시스템에 접근한다.

 

- DN 는 파일시스템 Client 나 NN의 요청이 있을 때 블록을 저장하고 탐색하며,

저장하고 있는 블록의 목록을 주기적으로 NN에 보고한다.

 

- DN 가 자주 접근하는 블록은 off-heap 블록 캐시 (메모리)에 넣어 캐싱 가능하다.

 

- NN 는 filesystem 의 모든 파일과 각 블록에 대한 참조 정보를 메모리에서 관리한다.

HDFS 페더레이션을 사용하면 각 NN가 파일 시스템의 Namespace 일부를 나눠 관리하는 방식으로

새로운 NN를 추가 가능하다.

예를 들어 첫번째 NN는 /user 디렉터리 아래 모든 파일을 관리하고

두번째 NN 는 /share 디렉터리 아래 모든 파일을 관리한다.

 

HA 클러스터 참고 : https://eyeballs.tistory.com/251

 

- HA 클러스터 구성에서 standby 를 active 로 전환시키는 전환 작업은

failover controller(FC) 라는 새로운 객체로 관리된다.

다양한 방법으로 구현 가능하지만 기본 구현체는

'단 하나의 NN만 active 상태라는 것을 보장해주는' 주키퍼를 사용한다.

경량의 FC 들은 하트비트를 통해 각 NN의 장애를 감시하고 NN 장애가 발생하면 복구를 지시한다.

 

- 장애가 발생한 NN가 현재 실행되지 않고 있단 것을 확신하기 어렵다.

네트워크가 느려지거나 ,단절되어 장애 복구 작업이 시작된 상황에서도

기존의 active NN 는 여전히 실행되고 있고 자신이 아직 Active 라고 생각할 것이다.

기존의 active NN 가 시스템을 손상시키거나 망가뜨리지 않도록

기존 active NN를 확실하게 죽이기 위해 펜싱(fencing) 메소드를 제공한다고 한다.

 

- HDFS 는 기본적으로 보안이 비활성화된 상태로 실행되므로

클라이언트의 사용자 계정을 인증하지 않음.

 

- HDFS 로부터 파일을 읽는 절차

하둡 완벽 가이드 4판

- HDFS client는 DistributedFileSystem 인스턴스인 Filesystem 객체의

   open() 메소드를 호출하여 원하는 파일을 연다. (1단계)

- DistributedFileSystem 은 파일의 첫 번째 블록 위치를 파악하기 위해

   RPC 를 이용하여 NN를 호출한다. (2단계)

- NN는 블록별로 해당 블록의 복제본을 갖는 DN 의 주소를 반환한다.

   이때 client와 가까운 순으로 DN가 정렬된다.

   (만약 client 자체가 DN 이고, 해당 블록의 복제본을 갖고 있다면 client 는 로컬 DN에서 데이터를 읽는다.)

- DistributedFileSystem 은 Client 가 데이터를 읽을 수 있도록 FSDataInputStream 을 반환한다.

   FSDataInputStream 은 파일 탐색을 지원하는 입력 스트림이며,

   DN 와 NN 의 IO를 관리하는 DFSInputStream 을 래핑한다.

- Client 는 스트림을 읽기 위해 read() 메소드를 호출 (3단계)

   파일의 첫 번째 block 의 DN 주소를 저장하고 있는 DFSInputStream은

   Client 와 가장 가까운 DN 와 연결

- 해당 스트림에 대해 read() 메서드를 반복적으로 호출하며 DN 에서 Client 로 모든 데이터 전송 (4단계)

- blcok의 끝에 도달하면 DFSInputStream 은 DN 의 연결을 닫고 다음 block 의 DN 를 찾음 (5단계)

   Client 는 이러한 내부 과정 없이 연속적인 스트림을 읽는 것처럼 느낌.

- Client는 스트림을 통해 block 을 순서대로 하나씩 읽음.

   이때 DFSInputStream 은 블록마다 DN 와 새로운 연결을 맺음

   Client 는 다음 block 의 DN 위치를 얻기 위해 NN 호출

   모든 block 읽기가 끝나면 Client 는 FSDataInputStream 의 close() 메소드를 호출 (6단계)

 

- 데이터를 읽는 중에 DN 와의 통신장애 발생시 DFSInputStream은 해당 블록을 저장하고 있는 다른 DN 와 연결 시도

   이후 block 에 대한 불필요한 재시도 방지를 위해 장애 발생한 DN 기억

- DFSInputStream은 DN 로부터 전송된 데이터 체크섬도 검증

   block 손상시 DFSInputStream 이 다른 DN 에 있는 block copy 읽으려 시도

   물론 손상된 block 정보는 NN에 보고됨

 

- Client 가 데이터를 얻기 위해 DN 에 직접 접촉하고 NN는 각 블록에 적합한 DN 안내하는 것이 핵심

- 데이터 트래픽은 클러스터 내 모든 DN 에 고르게 분산

   HDFS 는 동시 실행되는 Client 수를 크게 늘릴 수 있음

- NN는 효율적인 서비스를 위해 meta data를 메모리에 저장

   단순히 block 위치 정보 요청만 처리

   데이터 저장이나 전송 역할은 모두 DN 에게 넘김으로써 Client 증가에 따른 병목 현상이 거의 발생하지 않음

 

 

- HDFS 에 파일을 쓰는 절차

하둡 완벽 가이드 4판

 

- 쓰기 진행 과정은 크게, 새로운 파일을 생성하고, 파일에 데이터를 쓰고, 파일을 닫는 순으로 진행됨

- HDFS Client 는 DistributedFileSystem 의 create() 를 호출하여 파일 생성 (1단계)

- DistributedFileSystem 은 파일시스템의 네임스페이스에 새로운 파일을 생성하기 위해 NN 에 RPC 요청 (2단계)

   이땐 block 에 대한 정보는 보내지 않음.

- NN 는 요청한 파일과 동일한 파일이 이미 존재하는지, Client 가 파일 생성 권한을 갖고 있는 지 등의 검사를 수행

   검사를 통과하면 NN 는 새로운 파일의 레코드를 만듦

   검사에 실패하면 파일 생성은 실패하고 Client 에게 IOException 발생

- DistributedFileSystem 은 데이터를 쓸 수 있도록 Client 에 FSDataOutputStream을 반환

   읽을 때와 마찬가지로, FSDataOutputStream 은 DN 와 NN 의 통신 처리를 하는 DFSOutputStream으로 래핑됨

- Client 가 데이터를 쓸 때 (3단계) DFSOutputStream은 데이터를 패킷으로 분리

   데이터 큐 라 불리는 내부 큐로 패킷을 보냄

- DataStreamer 는 데이터 큐에 있는 패킷을 처리하기 위해 NN에 복제본을 저장할 DN 의 목록을 요청

   DN 목록에 포함된 노드는 파이프라인을 형성하는데, 복제 수준이 3이면 3개의 노드가 파이프라인에 속하게 됨

- DataStreamer는 pipeline 의 첫 번째 DN 로 패킷 전송

  첫 번째 DN 는 각 패킷을 저장한 후 그것을 pipeline 을 통해 두번째 DN 로 보냄

  두 번쨰 DN  역시 각 패킷을 저장한 후 그것을 pipeline 을 통해 세번째 DN 로 보냄

  새 번째 DN 역시 각 패킷을 저장 (4단계)

- DFSOutputStream 은 DN 의 승인 여부를 기다리는 ack 큐 라 불리는 내부 패킷 큐를 유지

   ack 큐에 있는 패킷은 pipeline 의 모든 DN 로부터 ack 응답을 받아야 제거됨 (5단계)

 

- 데이터를 쓰는 중에 DN 에 장애 발생시 다음과 같은 장애 복구 작업이 시작됨.

- 먼저 pipeline 이 닫히고 ack 큐에 있는 모든 패킷은 데이터 큐 앞쪽에 다시 추가

   이렇게 함으로써 다운스트림 노드가 실패해도 패킷이 하나도 유실되지 않음

- 정상 DN 는 NN 로부터 새로운 ID 다시 받음.

- 장애가 발생한 DN 가 나중에 다시 복구되면 불완전한 block 은 삭제가 됨

- 장애 DN 는 pipeline 에서 제거되고 정산인 나머지 두 DN 로 새로운 pipeline 이 구성됨

- 블록의 남은 데이터는 파이프라인의 정상 DN 로 전송

- NN는 해당 block 이 불완전 복제 라는 것을 인식하고 있으므로 나중에 다른 노드에 복제본이 생성되도록 조치를 취함

   이어 후속 블록을 정상적으로 처리

- 두 대 이상의 DN 에서 장애가 발생할 확률은 극히 희박

 

- 데이터 쓰기 완료시 Client 는 스트림에 close() 메서드를 호출 (6단계)

   이 메서드는 DN 파이프라인에 남아있는 모든 패킷을 flush 하고, 승인이 나기를 기다림

- 모든 패킷이 완전히 전송되면 NN 에 파일 완료 신호를 보냄 (7단계)

- NN는 DataStreamer 를 통해 블록 할당 요청을 받았기 때문에 파일의 블록이 어떻게 구성되어있는지 이미 알고 있음

   최소한의 블록 복제가 완료되길 기다렸다가 최종적으로 성공 신호 반환

 

- NN가 복제본을 저장할 데이터노드 선택하는 방법

첫번째 복제본은 클라이언트와 같은 노드에 배치

그런데 Client 가 클러스터 외부에 있거나 데이터 노드가 아니면, 무작위로 노드를 선택.

(무작위긴 해도 너무 바쁘거나 파일이 많은 노드는 제외)

두번째 복제본은 첫번째 노드와 다른 랙의 노드 중 하나를 무작위로 선택

세번째 복제본은 두번째 노드와 같은 랙의 다른 노드에 배치

그 이상의 복제본은 클러스터에서 무작위로 선택

(물론 같은 랙에 너무 많은 복제본이 배치되지 않도록 잘 조절함)

 

 

 

 

+ Recent posts