하둡 완벽 가이드 - 5. 하둡 I/O
본문 바로가기


Diana/review

하둡 완벽 가이드 - 5. 하둡 I/O

사용자의 입장으로만 하둡을 바라보게 되어 깊이가 부족하다는 생각을 하게 되었다.
하둡 완벽 가이드를 읽고 이해한대로 정리한다.


하둡은 데이터 I/O를 위한 프리미티브(primitive - 내장된 기본 기능)를 제공한다. 일부 일반적인 데이터 무결성, 압축과 같은 프리미티브가 있지만, 멀티테라바이트의 데이터셋을 처리할 때 사용하는 직렬화 프레임워크디스크 기반 데이터 구조와 같은 분산 시스템을 개발하기 위한 구성요소를 제공하는 하둡 도구나 API 같은 프리미티브들은 특별하게 볼 필요가 있다. 

5.1 데이터 무결성

하둡 사용자는 당연히 저장 또는 처리 과정에서 어떠한 데이터도 잃어버리거나 손상되지 않기를 기대한다. 체크섬 방법이 있다.

신뢰할 수 없는 통신 채널로 데이터가 전송되었을 때마다 체크섬을 계산한다. 데이터 원상 복구는 하지 않고 에러 검출만 수행하므로, 저가의 하드웨어를 권장하지 않으며, 메모리 에러 처리를 위해 ECC 메모리를 사용해야 한다.

일반적으로 32비트 정수 체크섬을 계산하는 CRC-32(32비트 순환 중복 검사)를 사용한다. 하둡의 ChecksumFileSystem에서 사용하고, HDFS는 CRC-32C 변형을 사용한다.

5.1.1 HDFS의 데이터 무결성

HDFS의 모든 데이터 쓰기 과정에서 내부적으로 체크섬을 계산하고, 데이터를 읽는 과정에서 체크섬을 기본적으로 검증한다. dfs.bytes-per-checksum에 설정한 크기만큼 모든 바이트 데이터에 대해 별도의 체크섬이 생성된다. 기본적으로 512 바이트고, CRC-32C 체크섬이 4바이트의 long 타입이므로 스토리지 오버헤드는 1%보다 작다.

데이터노드는 데이터&체크섬을 저장하기 전에 데이터 검증을 해야한다. 이 검증은 클라이언트 부터 or 복제 과정에서 다른 데이터노드로부터 수신한 데이터에 대해 수행된다. 파이프라인의 마지막 데이터노드에 데이터가 도착하면 체크섬을 검증한다. 검증을 실패하면 IOException의 서브클래스를 예외로 뱉는다. 

클라이언트는 데이터를 읽을 때 데이터 노드에 저장된 체크섬과 수신된 데이터로부터 계산된 체크섬을 검증 해야한다. 각 데이터노드는 체크섬 검증 로그를 클라이언트로부터 전달받고 영구 저장하기 때문에 각각의 블록이 검증되었던 마지막 시간을 알고있다. 이 통계치로 오류 디스크를 검출할 수 있다. 

백그라운드에서 DataBlockScanner 로 주기적으로 검증한다. 물리적 저장 매체에서 발생할 수도 있는 '비트 로드'에 의한 데이터 손실을 피하기 위한 목적을 가진다.

클라이언트가 데이터를 읽으며 손실을 확인하면 네임노드에 훼손된 블록과 데이터노드에 대한 정보를 보고하고 ChecksumException을 발생시킨다. 네임노드는 그 블록 복제본이 손상되었다고 표시하고 사용하지 못하도록 설정 후 다른 데이터노드에 복제하도록 스케줄링하여 복제 계수를 원래 수준으로 복구한다. 그 후 손상된 복제본은 삭제한다.

손상된 파일을 조사하려 하는 등의 이유로 원하지 않는다면 open() 매서드 호출 전에  FileSystem의 setVerifyChecksum( ) 메서드에 false를 전달해서 체크섬 검증을 비활성 할 수 있다. 쉘에서 -get 또는 -copyToLocal 명령어에 -ignoreCrc 옵션을 사용할 수도 있다. 

Hadoop fs -checksum을 이용해서 파일의 체크섬을 확인할 수 있다. 

5.1.2 LocalFileSystem

해당 프리미티브는 클라이언트 측 체크섬을 수행한다. 
파일을 쓸 때 파일 시스템 클라이언트는 파일과 같은 위치의 디렉터리에 그 파일의 각 청크별 체크섬이 담긴 .{파일명}.crc라는 숨겨진 메타데이터 파일을 내부적으로 생성한다. 

에러가 나면 ChecksumException을 발생시킨다.

기존 파일시스템이 자체적으로 체크섬을 지원하면 LocalFileSystem 대신 RawLocalFileSystem을 사용하면 된다.
애플리케이션에 전역적으로 체크섬을 비활성화하려면 fs.file.impl 속성을 org.apache.hadoop.fs.RawLocalFileSystem 값으로 설정해서 파일 URI 구현을 변경(remap)하면 된다.
대안으로는 RawLocalFileSystem 인스턴스를 직접 생성할 수도 있다.

Configuration conf = ...
FileSystem fs = new RawLocalFileSystem();
fs.initialize(null, conf);

5.1.3 ChecksumFileSystem

LocalFileSystem이 동작할 때 ChecksumFileSystem을 사용하며, 이 클래스는 단순한 FileSystem의 래퍼(wrapper)로 구현되어 있기 때문에 다른 체크섬이 없는 파일시스템에 체크섬 기능을 췹게 추가할 수 있다. 다음과 같이 쓴다.

FileSystem rawFs = ...
FileSystem checksummedFs = new ChecksumFileSystem(rawFs);

내부의 파일 시스템은 raw 파일시스템이라 불리며, ChecksumFilesystem의 getRawFileSystem() 메서드를 사용해서 얻을 수 있다. ChecksumFileSystem은 체크섬과 관련된 몇개의 유용한 메서드를 가지고 있다.

ChecksumFilesystem은 파일을 읽을 때 에러를 검출하면 reportChecksumFailure() 메서드를 호출한다. 
해당 메서드는 기본적으로 아무일도 하지 않지만, LocalFileSystem에서 문제가 되는 파일과 체크섬을 같은 디바이스를 bad_files라는 별도의 디렉터리로 이동시키는 일을 한다.

 

5.2 압축

파일 압축은 파일 저장 공간을 줄이고, 네트워크 또는 디스크로부터 데이터 전송을 고속화 할 수 있다는 큰 이점이 있어 대용량 처리할 때 하둡에서 압축을 사용한다.

Compression format Tool Algorithm File extention Splittable
DEFLATE n/a DEFLATE .deflate No
gzip gzip DEFLATE .gz No
bzip2 bizp2 bzip2 .bz2 Yes
LZO lzop LZO .lzo Yes if indexed
Snappy N/A Snappy .snappy No