의사 분산(pseudo-distributed) 모드로 실행
org.apache.hadoop.fs.FileSystem p83. [STUDY:표3-1]하둡 파일시스템 참고
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(uri), conf);
InputStream in = null;
try{
in = fs.open(new Path(uri));
IOUtils.copyBytes(in, System.out, 4096, false);
} finally{
IOUtils.closeStream(in);
}
FSDataInputStream :
public class FSDataInputStream extends DataInputStream implements Seekable, PositionedReadable{
...
}
Seekable :
public interface Seekable{
void seek(long pos) throws IOException;
long getPos() throws IOException;
}
PositionedReadable :
public interface PositionedReadable {
public int read(long position, byte[] buffer, int offset, int length) throws IOException;
public void readFully(long position, byte[] buffer, int offset, int length) throws IOException;
public void readFully(long position, byte[] buffer) throws IOException;
}
모든 메서드는 현재의 파일 offset을 유지하고, thread-safe하므로, 파일의 특정 부분을 읽는 동안, 그 파일의 다른 부분에 액세스할 수 있는 기능을 제공한다.
seek() 메서드는 비용이 많이 든다.
public FSDataOutputStream create(Path f) throws IOException;`
Progressable : 데이타 쓰기 진행상황을 통보받을 수 있다.
public interface Progressable {
public void progress();
}
append 와 sequential write 만 지원. 탐색은 지원하지 않는다.
public interface PathFilter {
boolean accept(Path path);
}
java.io.FileFilter 와 대응됨
제한사항 : 필터는 Path에 표현된 파일명으로만 동작하고, 필터의 대상으로 파일의 생성시간과 같은 파일 속성을 사용할 수 없다.
public boolean delete(Path f, boolean recursive) throws IOException
파일 읽기 해부
DistributedFileSystem 의 open()을 호출하여 파일을 연다 => 블록 위치를 파악하기 위해 RPC를 사용하여 네임노드를 호출한다 =>
요청된 블록의 복제본을 가지고 있는 데이타 노드를 반환한다 => 데이타 노드는 클러스터의 네트워크 토폴로지에 따라 정렬된다 =>
DFSInputStream의 read() 를 호출한다 => 해당 파일의 첫번째 블록과 첫번째 데이터노드를 연결한다 =>
클라이언트는 스트림에 대해 반복적으로 read()를 호출하고, 데이타는 데이타 노드로부터 전송된다. =>
블록의 끝에 이르면 데이타 노드로의 연결을 닫고, 다음 블록을 위해 가장 적합한 네임노드를 찾는다
네트워크 토폴로지와 하둡
파일쓰기 상세
DistributedFileSystem의 create() 호출하여 파일을 생성한다 => 네임스페이스에 파일을 생성하기 위해 네임노드로 RPC 호출 =>
파일 존재 여부, 권한 등 검사 수행 => FSDataOutputStream 반환 => DFSOutputStream으로 래핑 =>
data queue에 데이타를 패킷으로 쪼개서 쓴다 => queue는 DataStreamer 에 의해 소비된다 (데이타 복제본을 저장하기 적합한 데이타노드의 리스트를 선별하여 네임노드가 새로운 블록을 할당하도록 요청) =>
데이타 리스트는 하나의 파이프라인을 형성하고, DataStreamer는 패킷을 파이프라인의 첫번째 데이타 노드로 전송하고, 전송되고 있는 패킷을 저장하고 그다음 데이터노드로 전달한다 =>
DFSOutputStream은 데이터노드로부터 승인되기를 기다리는 ack queue를 관리한다.
하나의 패킷은 파이프라인에 있는 데이타노드로부터 모두 승인되었을 때에만 승인 큐로부터 제거된다 =>
클라이언트는 데이터 쓰기를 완료할때 close를 호출하고, 남아있는 모든 패킷을 파이프라인으로 flush하고, 파일완료 신호를 보내기 전에 패킷에 대한 최종 승인을 기다린다.
일관성 모델
파일 시스템의 읽기 쓰기에 대한 데이타 가시성을 묘사함
FSDataOutputStream#sync() <= close() 수행시 암묵적으로 수행됨
병렬로 다량의 데이타를 hdfs로(부터) 복사하기 위한 명령어
hadoop distcp hdfs://namenode1/foo hdfs://namenode2/bar
맵리듀스 잡으로 구성되어 있고, 클러스터 전반에 병렬로 수행되는 맵으로 복사 작업이 이루어짐. 리듀서는 없음
HFTP를 이용해 버전이 다른 hdfs의 RPC 호환
hadoop distcp hftp://namenode1:50070/foo hdfs://namenode2/bar
하둡 아카이듭 또는 HAR 파일은 더 효율적으로 HDFS 블록을 묶기 위한 파일 아카이빙 기능
네임노드의 메모리 사용량을 감소시킴
hadoop archive -archiveName files.har /my/files /my