Chapter3 - 하둡 분산 파일시스템

이 글은 “하둡 완벽 가이드” 책 내용을 정리한 글입니다.

저작권에 문제가 있는 경우 “gunjuko92@gmail.com”으로 연락주시면 감사하겠습니다.

하둡 분산 파일시스템

  • 데이터가 단일 물리 머신의 저장 용량을 초과하게 되면 전체 데이터셋을 분리된 여러 머신에 나눠서 저장할 필요가 있음
  • 네트워크로 연결된 여러 머신의 스토리지를 관리하는 파일 시스템을 분산 파일시스템이라고 함
  • 분산 파일시스템은 네트워크 기반이므로 네트워크 프로그램의 복잡성을 모두 가지고 있다.

HDFS (Hadoop Distributed FileSystem)

  • 하둡은 HDFS라는 분산 파일 시스템을 제공
  • HDFS는 하둡의 대표적인 파일시스템이다. 하둡은 범용 파일시스템을 추구하기 때문에 추상화 개념을 가지고 있다.

3.1 HDFS 설계

  • HDFS는 범용 하드웨어로 구성된 클러스터에서 실행되고 스트리밍 방식의 데이터 접근 패턴으로 대용량 파일을 다룰 수 있도록 설계된 파일 시스템이다.
  • 설계 특성
    • 매우 큰 파일
    • 스트리밍 방식의 데이터접근 : HDFS는 가장 효율적인 데이터 처리 패턴은 한 번 쓰고 여러번 읽는 것이라는 아이디어에서 시작됨. 데이터셋은 생성되거나 원본으로부터 복사되고 시간이 흐르면서 다양한 분석을 수행할 수 있음
    • 범용 하드웨어 : 범용 하드웨어로 구성된 대형 클러스터에서 문제없이 실행되도록 설계
  • 적합하지 않은 경우
    • 빠른 데이터 응답 시간 : HDFS는 높은 데이터 처리량을 제공하기 위해 최적화되어 있음
    • 수 많은 작은 파일 : 네임노드는 파일시스템의 메타데이터를 메모리에서 관리하기 때문에 저장할 수 있는 파일 수는 네임노드의 메모리 용량에 좌우된다. 대략 파일, 디렉토리, 블록은 각각 150 바이트 정도의 메모리가 필요하다.
    • 다중 라이터와 파일의 임시 수정 : HDFS는 단일 라이터로 파일을 쓴다. 파일의 끝에 덧붙이는건 가능하지만 파일에서 임의 위치에 있는 내용을 수정하는 것은 허용하지 않으며 다중 라이터는 하둡 3.0부터 지원한다.

빠른 데이터 응답이 필요한 경우 HBase가 하나의 대안이 될 수 있다.

3.2 HDFS 개념

3.2.1 블록

  • 디스크 블록 크기 : 한 번에 읽고 쓸 수 있는 데이터 최대량
  • 단일 디스크를 위한 파일 시스템은 디스크 블록 크기의 정배수인 파일 시스템 블록 단위로 데이터를 다룬다. 보통 디스트 블록 크기는 512 바이트이고 파일 시스템 블록의 크기는 수 킬로바이트이다.
  • HDFS는 블록 개념을 가지고 있으며 기본적으로 128MB와 같이 굉장히 큰 단위이다. HDFS의 파일은 특정 블록 크기의 chunk로 쪼개지고 각 청크는 독립적으로 저장된다.
  • 단일 디스크를 위한 파일 시스템은 디스크 블록 크기보다 작은 데이터라도 한 블록 전체를 점유하지만, HDFS 파일은 블록 크기보다 작은 데이터일 경우 전체 블록 크기에 해당하는 하위 디스크를 모두 점유하지는 않는다.

HDFS 블록이 큰 이유는?

  • 탐색 비용을 최소화 하기 위해
  • 블록 추상화 개념 도입의 장점
    • 파일 하나의 크기가 단일 디스크의 용량보다 더 커질 수 있다.
    • 스토리지의 서브시스템을 단순하게 만들 수 있다.
    • 블록은 fault tolerance, availability을 제공하는데 필요한 replication를 구현할 때 매우 적합하다. 읽기 부하를 클러스터 전체에 분산시키기 위해 특정 블록의 복제 계수를 높게 설정할 수도 있다.

3.2.2 네임노드와 데이터노드

  • HDFS 클러스터는 master-worker 패턴으로 동작하는 두 종류의 노드 (마스터인 하나의 네임노드와 워커인 여러 개의 데이터 노드)로 구성되어 있다.
  • 네임노드 : 파일시스템의 네임스페이스를 관리. 네임노드는 파일시스템 트리와 그 트리에 포함된 모든 파일과 디렉터리에 대한 메타데이터를 유지한다. 이 정보는 네임스페이스 이미지와 에디터 로그라는 두 종류의 파일로 로컬 디스크에 영속적으로 저장된다.
    • 네임노드는 파일에 속한 모든 블록이 어느 데이터노드에 있는지 파악하고 있다.
    • 네임노드가 없으면 파일 시스템은 동작안함
  • 데이터노드 : 파일시스템의 실질적인 일꾼
    • 클라이언트나 네임노드의 요청이 있을 때 블록을 저장하고 탐색한다.
    • 블록의 목록을 주기적으로 네임노드에 보고
  • HDFS 클라이언트
    • 사용자를 대신해서 네임노드와 데이터노드 사이에서 통신하고 파일시스템에 접근
  • 하둡이 지원하는 네임노드 장애 복구 기능
    • 첫번째 : 파일 시스템의 메타데이터를 지속적인 상태로 보존하기 위해 파일로 백업
    • 두번째 : 보조 네임노드 운영
  • 보조 네임노드
    • 에디트 로그가 너무 커지지 않도록 주기적으로 네임스페이스 이미지를 에디트 로그와 병합하여 새로운 네임스페이스 이미지를 만든다.
    • 주 네임노드에 장애가 발생할 것을 대비해서 네임스페이스 이미지의 복제본을 보관. 약간의 시간차가 있기 때문에 네임노드 장애시 어느 정도의 데이터 손실은 불가피함

3.2.3 블록 캐싱

  • 데이터노드는 디스크에 저장된 블록을 읽는다. 하지만 빈번하게 접근하는 블록 파일은 오프-힙 블록 캐시라는 데이터노드의 메모리에 명시적으로 캐싱할 수 있다.
  • 잡 스케줄러(맵리뷰스, 스파크 등)은 블록이 캐싱된 데이터노드에서 태스크가 실행되도록 할 수 있다.
  • 블록 캐시의 장점을 활용하면 읽기 성능을 높일 수 있다.
  • 사용자나 애플리케이션은 캐시풀에 캐시 지시자를 추가하여 특정 파일을 캐시하도록 명령할 수 있다.

3.3 명령행 인터페이스

psudo-distributed 모드로 하둡 설치시 중요한 설정

  • fs.defaultFS : 하둡의 기본 파일시스템을 설정한다.
    • 기본값 : hdfs://localhost/
  • dfs.replication : 기본 복제 계수를 설정 (기본값 : 3)

3.3.1 기본적인 파일시스템 연산

  • 파일 복사
    • URI의 스킴과 호스트를 생략하면 core-site.xml에 설정된 기본값을 가져온다.
hadoop fs -copyFromLocal input/docs/quangle.txt hdfs://localhost/user/tom/quangle.txt
  • 디렉토리 생성 : hadoop fs -mkdir {directoryName}
  • 목록 출력 : hadoop fs -ls {directoryPath}

HDFS 파일 권한

  • HDFS는 읽기 권한(r), 쓰기 권한(w), 실행 권한(x) 등 세 가지 종류의 파일 권한이 존재한다.
  • HDFS는 파일의 실행은 지원하지 않으므로 파일에 대한 실행 권한은 무시되지만 디렉터리에 대한 실행 권한은 하위 디렉토리에 접근을 위해 필요하다.
  • 각 파일과 디렉터리는 소유자, 그룹, 모드를 가진다. 모드는 소유자, 그룹 멤버, 그 밖의 사용자에 대한 권한으로 구성된다.
  • 권한 검사가 가능하도록 설정되면 클라이언트는 사용자 이름이 소유자와 일치할 때 소유자 권한으로 체크되고, 클라이언트가 그룹의 멤버와 일치할 때 그룹 권한이 체크되고, 일치하지 않는다면 그 밖의 사용자 권한으로 체크된다.

3.4 하둡 파일시스템

  • 하둡은 파일시스템의 추상화 개념을 가지고 있고, HDFS는 그 구현체 중 하나일 뿐이다. 자바 추상 클래스 org.apache.hadoop.fs.FileSystem 은 하둡의 파일 시스템을 접근할 수 있는 클라이언트 인터페이스다.
  • 하둡 파일 시스템은 file, hdfs, webhdfs 등이 존재함
파일 시스템 URL 스킴 자바 구현체 설명
Local file fs.localFileSystem 클라이언트 측의 체크섬을 사용하는 로컬 디스크를 위한 파일 시스템
HDFS hdfs hdfs.DistributedFileSystem 하둡 분산 파일시스템. HDFS는 맵리듀스와 효율적으로 연동하기 위해 설계됨
WebHDFS webhdfs hdfs.web.WebHdfsFileSystem HTTP를 통해 HDFS에 인증을 통한 읽기/쓰기를 제공하는 파일시스템
  • 하둡은 다양한 파일시스템을 위한 인터페이스를 제공하는데, 접근할 파일시스템의 인스턴스를 선택할 때 일반적으로 URL 스킴을 사용한다.

3.4.1 인터페이스

  • 하둡은 자바로 작성되었기 때문에 자바 API를 통해 하둡 파일시스템과 연동할 수 있다. 예를 들어 파일시스템 쉘은 자바 FileSystem 클래스이다.

3.5 자바 인터페이스

  • 자바에서 하둡과 연동하기 위해선 주로 FileSystem 클래스를 사용한다.
  • 하둡 파일시스템의 파일은 하둡 Path 객체로 표현된다. 여기서 Path는 hdfs://localhost/user/tom/quangle.txt 같은 하둡 파일시스템 URL을 의미한다.
  • Configuration 객체는 클라이언트나 서버의 환경 설정을 포함하고 있으며, 클래스패스에 있는 etc/hadoop/core-site.xml 과 같은 설정 파일에서 관련 설정을 읽어 드린다.

3.6 데이터 흐름

3.6.1 파일 읽기 상세

  1. 클라이언트는 HDFS가 DistributedFileSystem 인스턴스인 FileSystem 객체의 open() 메서드를 호출하여 원하는 파일을 연다.
  2. DistributedFileSystem은 파일의 첫 번째 블록 위치를 파악하기 위해 RPC를 사용하여 네임노드를 호출한다. 네임노드는 블록별로 해당 블록의 복제본을 가진 데이터노드 주소를 반환한다. 이 때 클러스터의 네트워크 위상에 따라 클라이언트와 가까운 순으로 데이터노드가 정렬된다.
  3. DistributedFileSystem은 클라이언트가 데이터를 읽을 수 있도록 FSDataInputStream을 반환한다. 클라이언트는 스트림을 읽기 위해 read() 메소드를 호출한다. FSDataInputStream은 데이터노드와 네임노드의 IO를 관리하는 DFSInputStream을 래핑한다. DFSInputStream은 가장 가까운 데이터노드와 연결해서 데이터를 읽은뒤 블록끝에 도달하면 데이터노드의 연결을 닫고 다음 블록의 데이터노드를 찾는다.
  4. 모든 블록에 대한 읽기가 끝나면 클라이언트는 FSDataInputStream의 close() 메서드를 호출한다.
  • DFSInputStream은 데이터노드로부터 전송된 데이터의 체크성을 검증한다. 블록이 손상되었으면 다른 데이터노드에 있는 복제본을 읽는다.
  • 클라이언트는 데이터를 얻기 위해 데이터노드에 직접적으로 접촉한다. 네임노드는 각 블록에 접한한 데이터노드를 안내해주는 역할만한다. 따라서 데이터노드에 트래픽이 고르게 분산되므로 HDFS는 동시에 실행되는 클라이언트 수를 크게 늘릴 수 있다.
  • 네임노드는 메타데이터를 메모리에 저장하고 단순히 블록의 위치 정보 요청만 처리한다. 데이터를 저장하거나 전송하는 역할은 맡지 않으므로 병목현상이 발생하지 않는다.

3.6.2 파일 쓰기 상세

  • DistributedFileSystem의 create()를 호출하여 파일을 생성한다. DistributedFileSystem는 네임노드에 요청을 보내 파일을 생성한다.
  • 네임노드는 요청한 파일과 동일한 파일이 있는지, 클라리언트가 파일 생성 권한이 있는지 등 다양한 검사를 수행한다. 검사가 통과하면 네임노드는 새로운 파일의 레코드를 만든다.
  • DistributedFileSystem은 데이터를 쓸 수 있도록 클라이언트에 FSDataOutputStream을 반환한다. FSDataOutputStream은 데이터노드와 네임노드의 통신을 처리하는 DFSOutputStream으로 래핑된다.
  • 데이터를 쓰는 중에 데이터노드에 장애가 발생하면 복구 작업이 시작된다.

3.6.3 일관성 모델

  • 파일에 대한 읽기와 쓰기의 데이터 가시성(visibility)은 파일시스템의 일관성 모델로 설명할 수 있다.
  • 데이터가 한 블록 이상 기록되면 새로운 리더는 첫번째 블록의 내용을 볼 수 있다. 쓰기 작업이 진행 중인 블록의 내용을 다른 리더가 볼 수 없다.
  • HDFS는 FSDataOutputStream의 hflush() 메서드를 통해 데이터노드에 있는 모든 버퍼의 내용이 플러시되도록 강제하는 방법을 제공한다. HDFS의 파일을 닫는 것은 암묵적으로 hflush()를 수행하는 것이다.
  • hflush()나 hsync()를 호출하지 않은 상황에서 클라이언트나 시스템에 장애가 발생하면 데이터 블록을 잃어버릴 수 있다.

3.7 distcp로 병렬 복사하기

  • 하둡은 병렬로 다량의 데이터를 하둡 파일시스템으로 복사하기 위한 distcp라는 유용한 프로그램을 제공한다.
// 파일복사
hadoop distcp file1 file2
// 디렉토리 복사
hadoop distcp dir1 dir2
// 다른 클러스터에 복사
hadoop distcp -update -delete -p hdfs://namenode1/foo hdfs://namenode2/foo
  • dir2 디텍터리가 이미 존재한다면 dir1은 dir2 하위에 복사된다. (dir2/dir1 구조) -overwrite 옵션을 통해 덮어쓰기 형태로 복사하는것도 가능하다.
  • distcp로 HDFS 클러스터간의 데이터 이동도 가능하다