HDFS 튜토리얼: Archi강의, 읽기 및 쓰기 Opera기

⚡ 스마트 요약

HDFS는 하둡의 분산 스토리지 계층으로, 매우 큰 파일을 일반 머신에 복제된 블록으로 분할하여 단일 네임노드가 여러 개의 대용량 파일을 저장할 수 있도록 합니다. trac많은 DataNode가 읽기 및 쓰기 요청을 안정적으로 처리하는 동안 ks 메타데이터가 저장됩니다.

  • 🔘 Archi강의: 네임노드는 네임스페이스 이미지와 편집 로그를 저장하고, 데이터노드는 실제 블록 복제본을 저장합니다.
  • ☑️ 블록 크기 조정: Hadoop 1.x는 기본적으로 64MB 블록 크기를 사용했지만, Hadoop 2.x 및 3.x는 기본적으로 128MB 블록 크기를 사용합니다.
  • ✅ 복제: 블록당 3개의 복제본이 기본 설정이며, 랙 전체에 분산되어 하드웨어 장애 발생 시에도 데이터 손실이 발생하지 않습니다.
  • 🧪 읽기 경로: FSDataInputStream 및 DFSInputStream은 NameNode에서 블록 위치를 가져온 다음 DataNode에서 바이트를 직접 스트리밍합니다.
  • 🛠️ 쓰기 경로: DFSOutputStream은 패킷을 큐에 저장하고, DataStreamer는 DataNode 파이프라인을 구축하며, Ack Queue는 패킷 손실을 방지합니다.
  • 🧭 액세스 옵션: org.apache.hadoop.fs Java API와 HDFS DFS 셸 모두 열기, 읽기, 쓰기 및 닫기 기능을 제공합니다.

HDFS 튜토리얼

HDFS란 무엇입니까?

HDFS는 대용량 데이터 파일을 저장하기 위한 분산 파일 시스템으로, 일반적인 하드웨어 클러스터에서 실행됩니다. 내결함성이 뛰어나고 확장성이 우수하며, 확장이 매우 간단합니다. 하둡에는 HDFS(하둡 분산 파일 시스템)가 기본으로 포함되어 있습니다.

데이터가 단일 물리적 머신의 저장 용량을 초과하면 여러 개의 별도 머신에 데이터를 나누는 것이 필수적입니다. 머신 네트워크에서 저장 특정 작업을 관리하는 파일 시스템을 분산 파일 시스템이라고 합니다. HDFS는 그러한 소프트웨어 중 하나입니다.

HDFS Archi강의

HDFS 클러스터는 주로 다음으로 구성됩니다. 네임 노드 파일 시스템 메타데이터를 관리하는 것 데이터 노드 실제 데이터를 저장하는 곳입니다.

  • 네임노드: 네임노드는 시스템의 마스터 역할을 합니다. 네임노드는 파일 시스템 트리와 시스템에 있는 모든 파일 및 디렉터리의 메타데이터를 관리합니다. 메타데이터 정보는 '네임스페이스 이미지'와 '편집 로그'라는 두 파일에 저장됩니다. 네임노드는 특정 파일의 데이터 블록을 포함하는 모든 데이터노드의 위치를 ​​알고 있지만, 블록 위치 정보는 영구적으로 저장하지 않습니다. 이 정보는 시스템이 시작될 때마다 데이터노드에서 다시 불러옵니다.
  • 데이터노드: 데이터노드는 클러스터의 각 머신에 상주하는 슬레이브로, 실제 스토리지를 제공합니다. 데이터노드는 클라이언트의 읽기 및 쓰기 요청을 처리하는 역할을 합니다.

단일 네임노드는 단일 장애 지점이 될 수 있으므로, 현재 클러스터는 활성 네임노드와 대기 네임노드를 함께 운영하며, 저널노드 쿼럼을 통해 편집 로그를 공유하고 두 네임노드 간에 자동 장애 조치가 이루어집니다.

HDFS에서의 읽기 및 쓰기 작업은 블록 단위로 이루어집니다. HDFS의 데이터 파일은 블록 크기의 청크로 나뉘어 독립적인 단위로 저장됩니다. Hadoop 1.x의 기본 블록 크기는 64MB입니다. Hadoop 2.x부터는 기본 블록 크기가 변경되었습니다. dfs.블록 크기 128MB입니다.

HDFS는 데이터 복제라는 개념을 기반으로 작동합니다. 데이터 블록의 여러 복제본을 생성하여 클러스터 전체의 노드에 분산시킴으로써 노드 장애 발생 시에도 데이터의 고가용성을 보장합니다. 기본 복제 계수는 3입니다.dfs.복제그리고 DataNode가 하트비트 전송을 중단하면 NameNode는 자동으로 해당 블록을 다른 위치에 다시 복제합니다.

당신은 알고 계십니까? 단일 블록보다 작은 HDFS의 파일은 블록의 전체 저장소를 차지하지 않습니다.

읽기 OperaHDFS에서

데이터 읽기 요청은 HDFS, 네임노드(NameNode) 및 데이터노드(DataNode)에서 처리됩니다. 읽기 작업을 수행하는 주체를 '클라이언트'라고 부르겠습니다. 아래 다이어그램은 하둡에서의 파일 읽기 작업을 보여줍니다.

클라이언트, 네임노드 및 데이터노드 간의 HDFS 읽기 작업 데이터 흐름

  1. 클라이언트는 FileSystem 객체의 'open()' 메서드를 호출하여 읽기 요청을 시작합니다. FileSystem 객체는 DistributedFileSystem 형식의 객체입니다.
  2. 이 객체는 RPC를 사용하여 NameNode에 연결하고 파일 블록의 위치와 같은 메타데이터 정보를 가져옵니다. 이러한 주소는 파일의 처음 몇 개 블록에 대한 주소라는 점에 유의하십시오.
  3. 이 메타데이터 요청에 대한 응답으로 해당 블록의 사본을 보유한 DataNode의 주소가 반환됩니다.
  4. DataNode의 주소를 수신하면 FSDataInputStream 형식의 객체가 클라이언트로 반환됩니다. FSDataInputStream에는 DataNode 및 NameNode와의 상호 작용을 처리하는 DFSInputStream이 포함되어 있습니다. 위 다이어그램의 4단계에서 클라이언트는 'read()' 메서드를 호출하여 DFSInputStream이 파일의 첫 번째 블록을 보유한 첫 번째 DataNode와 연결을 설정하도록 합니다.
  5. 데이터는 스트림 형태로 읽히며, 클라이언트는 'read()' 메서드를 반복적으로 호출합니다. 이 'read()' 작업은 블록의 끝에 도달할 때까지 계속됩니다.
  6. 블록의 끝에 도달하면 DFSInputStream은 연결을 닫고 다음 블록에 대한 다음 DataNode를 찾습니다.
  7. 클라이언트가 읽기를 마치면 close() 메서드를 호출합니다.

쓰다 OperaHDFS에서

이 섹션에서는 파일을 통해 데이터가 HDFS에 기록되는 방식을 살펴보겠습니다. 아래 다이어그램을 참조하세요. trac경로를 쓰는 es.

DataQueue, DataStreamer 및 Ack Queue를 사용하는 HDFS 쓰기 작업 파이프라인

  1. 클라이언트는 DistributedFileSystem 객체의 'create()' 메서드를 호출하여 새 파일을 생성함으로써 쓰기 작업을 시작합니다. 이는 위 다이어그램의 1단계에 해당합니다.
  2. DistributedFileSystem 객체는 RPC 호출을 사용하여 NameNode에 연결하고 새 파일 생성을 시작합니다. 그러나 이 파일 생성 작업은 파일에 블록을 연결하지 않습니다. NameNode는 생성하려는 파일이 이미 존재하는지, 그리고 클라이언트가 새 파일을 생성할 수 있는 올바른 권한을 가지고 있는지 확인해야 합니다. 파일이 이미 존재하거나 클라이언트에게 새 파일을 생성할 충분한 권한이 없는 경우, 클라이언트에게 IOException이 발생합니다. 그렇지 않으면 작업이 성공하고 NameNode는 해당 파일에 대한 새 레코드를 생성합니다.
  3. NameNode에 새 레코드가 생성되면 FSDataOutputStream 형식의 객체가 클라이언트로 반환됩니다. 클라이언트는 이 객체를 사용하여 HDFS에 데이터를 기록합니다. 데이터 쓰기 메서드가 호출됩니다(다이어그램의 3단계).
  4. FSDataOutputStream은 DataNode 및 NameNode와의 통신을 담당하는 DFSOutputStream 객체를 포함합니다. 클라이언트가 데이터를 계속 쓰는 동안 DFSOutputStream은 해당 데이터를 담은 패킷을 계속 생성합니다. 이러한 패킷은 DataQueue라는 큐에 추가됩니다.
  5. 이 DataQueue를 소비하는 DataStreamer라는 구성 요소가 하나 더 있습니다. DataStreamer는 NameNode에 새 블록 할당을 요청하여 복제에 사용할 적절한 DataNode를 선택합니다.
  6. 이제 DataNode를 사용하여 파이프라인을 생성하는 것으로 복제 프로세스가 시작됩니다. 우리의 경우 복제 수준을 3으로 선택했으므로 파이프라인에 3개의 DataNode가 있습니다.
  7. DataStreamer는 파이프라인의 첫 번째 DataNode에 패킷을 쏟아 붓습니다.
  8. 파이프라인의 각 데이터노드는 자신이 수신한 패킷을 저장하고 파이프라인의 두 번째 데이터노드로 해당 패킷을 전달합니다.
  9. DFSOutputStream은 데이터노드로부터 승인 응답을 기다리는 패킷을 저장하기 위해 '승인 대기열(Ack Queue)'이라는 또 다른 대기열을 관리합니다.
  10. 파이프라인의 모든 DataNode에서 큐에 있는 패킷에 대한 확인을 받으면 'Ack Queue'에서 제거됩니다. DataNode에 장애가 발생하는 경우 이 큐의 패킷을 사용하여 작업을 다시 시작합니다.
  11. 클라이언트가 데이터 쓰기를 완료하면 close() 메서드를 호출합니다(다이어그램의 9단계). close() 호출은 나머지 데이터 패킷을 파이프라인으로 보내고, 그 후 확인 응답을 기다립니다.
  12. 최종 확인 응답을 받으면 네임노드에 연락하여 파일 쓰기 작업이 완료되었음을 알립니다.

HDFS에 액세스하려면 다음을 사용하세요. Java API

이 섹션에서는 다음을 이해하려고 합니다. Java Hadoop의 파일 시스템에 액세스하는 데 사용되는 인터페이스입니다.

Hadoop의 파일 시스템과 프로그래밍 방식으로 상호 작용하기 위해 Hadoop은 여러 가지 방법을 제공합니다. Java 클래스. org.apache.hadoop.fs라는 패키지에는 Hadoop 파일 시스템에서 파일을 조작하는 데 유용한 클래스가 포함되어 있습니다. 이러한 작업에는 열기, 읽기, 쓰기 및 닫기가 포함됩니다. Hadoop 파일 API는 범용적이며 HDFS 외의 다른 파일 시스템과 상호 작용하도록 확장할 수 있습니다.

프로그래밍 방식으로 HDFS에서 파일 읽기

객체 java.net.URL 파일의 내용을 읽는 데 사용됩니다. 우선, 우리는 다음을 만들어야 합니다. Java Hadoop의 HDFS를 인식합니다 URL 계획. 이는 집합을 호출함으로써 이루어집니다.URLStreamHandlerFactory 메서드 URL 객체를 생성하고 FsUrlStreamHandlerFactory 인스턴스를 전달합니다. 이 메서드는 객체당 한 번만 실행하면 됩니다. JVM이므로 정적 블록으로 묶입니다.

예제 코드는 다음과 같습니다.

public class URLCat {
    static {
        URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
    }
    public static void main(String[] args) throws Exception {
        InputStream in = null;
        try {
            in = new URL(args[0]).openStream();
            IOUtils.copyBytes(in, System.out, 4096, false);
        } finally {
            IOUtils.closeStream(in);
        }
    }
}

이 코드는 파일을 열고 내용을 읽습니다. HDFS 상의 해당 파일 경로는 명령줄 인수로 프로그램에 전달됩니다.

명령줄 인터페이스를 사용하여 HDFS에 액세스하기

이는 HDFS와 상호 작용하는 가장 간단한 방법 중 하나입니다. 명령줄 인터페이스는 파일 읽기, 디렉터리 생성, 파일 이동, 데이터 삭제 및 디렉터리 목록 보기와 같은 파일 시스템 작업을 지원합니다.

우리는 달릴 수 있습니다 '$HADOOP_HOME/bin/hdfs dfs -help' 각 명령어에 대한 자세한 도움말을 보려면 다음을 참조하세요. 여기서 'dfs'는 여러 하위 명령어를 지원하는 HDFS 셸 명령어입니다. 최신 Hadoop 릴리스에서는 hdfs dfs 선호되는 형태이며, 이전 형태는 다음과 같습니다. 하둡 파일 시스템 이 명령어는 지원되는 모든 파일 시스템에 대해 동일한 작업을 수행합니다.

널리 사용되는 명령 중 일부를 아래에 나열하고 각 명령에 대한 자세한 내용을 설명하겠습니다.

1. 로컬 파일 시스템에서 HDFS로 파일 복사

$HADOOP_HOME/bin/hdfs dfs -copyFromLocal temp.txt /

이 명령은 아래와 같이 로컬 파일 시스템에서 HDFS로 temp.txt 파일을 복사합니다.

hdfs dfs -copyFromLocal 명령어를 사용하여 temp.txt 파일을 HDFS로 복사합니다.

2. `-ls` 명령어를 사용하면 디렉터리에 있는 파일 목록을 나열할 수 있습니다.

$HADOOP_HOME/bin/hdfs dfs -ls /

아래 목록에서 ' / ' 디렉터리 아래에 'temp.txt' 파일(이전에 복사한 파일)이 있는 것을 확인할 수 있습니다.

hdfs dfs -ls 명령의 출력 결과는 HDFS 루트 디렉터리에 있는 temp.txt 파일을 보여줍니다.

3. HDFS에서 로컬 파일 시스템으로 파일을 복사하는 명령

$HADOOP_HOME/bin/hdfs dfs -copyToLocal /temp.txt

이 명령어는 `-get` 명령어와 동일하며 두 번째 인수로 로컬 대상 경로를 명시적으로 지정할 수 있습니다. 아래 출력은 `temp.txt` 파일이 로컬 파일 시스템에 복사된 것을 보여줍니다.

`hdfs dfs -copyToLocal` 명령의 출력 결과는 temp.txt 파일이 로컬 파일 시스템에 복사되었음을 보여줍니다.

4. 새 디렉터리를 생성하는 명령

$HADOOP_HOME/bin/hdfs dfs -mkdir /mydirectory

아래 메시지에서 볼 수 있듯이 명령은 아무런 안내 없이 완료됩니다.

`hdfs dfs -mkdir` 명령어를 사용하여 HDFS에 `/mydirectory` 폴더를 생성합니다.

디렉토리가 생성되었는지 확인하세요. 이제 어떻게 하는지 아셨겠죠? 😉

자주 묻는 질문

대용량 블록을 사용하면 NameNode 메타데이터 크기가 작아지고, 매퍼가 다시 탐색하기 전에 긴 바이트 시퀀스를 순차적으로 읽을 수 있습니다. 따라서 디스크 탐색 시간은 전송 시간의 극히 일부분에 불과하게 되므로 전체 파일 스캔 속도가 빨라집니다.

네임노드는 하트비트 수신을 중단하고 노드가 비활성 상태임을 표시한 다음, 복제 계수 미만으로 떨어진 모든 블록을 정상적인 데이터노드로 재복제하도록 예약합니다. 전송 중인 쓰기 작업은 승인 대기열에서 복구되므로 클라이언트는 패킷 손실을 방지합니다.

제대로 구성된 클러스터에서는 그렇지 않습니다. HDFS 고가용성은 활성 및 대기 NameNode를 실행하고, 이 두 NameNode는 JournalNode를 통해 편집 내용을 공유하며, ZooKeeper 장애 조치 컨트롤러는 활성 노드가 응답하지 않을 때 대기 노드를 자동으로 승격시킵니다.

두 명령어 모두 데이터를 HDFS에 업로드합니다. `-copyFromLocal` 옵션은 소스를 로컬 파일 시스템으로 제한하는 반면, `-put`은 다른 HDFS 경로 또는 표준 입력(stdin)을 포함하여 지원되는 모든 소스를 허용합니다. 그 외의 동작은 동일하므로 `-copyFromLocal`은 단순히 의도를 설명하는 데 사용됩니다.

NameNode에서는 모든 파일, 디렉터리 및 블록이 메모리를 차지하므로 수백만 개의 작은 파일이 디스크 용량이 차기 훨씬 전에 힙 메모리를 소진합니다. 이러한 파일들을 시퀀스 파일, Avro, ORC, Parquet 또는 HAR 아카이브로 결합하면 메타데이터를 관리하기 쉽게 유지할 수 있습니다.

복제는 전체 복사본 3개를 유지하므로 저장 공간이 200% 더 많이 필요합니다. 하둡 3에 추가된 이레이저 코딩은 패리티 셀을 저장하여 비슷한 내구성을 제공하지만 오버헤드는 약 50%에 불과합니다. 이는 저장 공간은 저렴하지만 복구 시 CPU 및 네트워크 비용이 더 많이 드는 방식입니다.

NameNode 감사 로그와 DataNode 메트릭으로 학습된 머신 러닝 모델은 용량 고갈을 예측하고, 자주 사용되는 블록을 표시하며, 디스크 장애가 발생하기 전에 이를 감지할 수 있습니다. 또한 액세스 패턴에 대한 이상 탐지 기능을 통해 폭주하는 작업도 조기에 파악할 수 있습니다.

Copilot은 FileSystem.get, FSDataInputStream 반복문, IOUtils.copyBytes 호출과 같은 익숙한 org.apache.hadoop.fs 상용구 코드를 신속하게 생성합니다. 생성된 코드는 사용 중인 Hadoop 버전과 항상 일치하는지 확인하십시오. Hadoop 2.x와 3.x 버전 간에는 API 이름과 더 이상 사용되지 않는 메서드가 상당히 다르기 때문입니다.

이 게시물을 요약하면 다음과 같습니다.