티스토리 뷰

오픈 때문에 바쁘다는 핑계로 이제서야 포스팅을 하네요. ^^;;

오늘은 Lzo 압축 라이브러리를 적용하다가, 우연히 알게 된 Snappy(이하: 스내피)를 소개해드리려고 합니다.

 

하둡 관련 서적이나 화이트 페이퍼에서 맵리듀스 튜닝을 가이드할 때 꼭 나오는 주제가 있습니다.

그건 바로 매퍼의 출력 데이터를 압축하는 방법인데요.

 

로컬 디스크에 저장되는 사이즈와 네트워크로 전송되는 사이즈가 줄기 때문에 성능 개선에 좋습니다.
물론 당연히 압축된 매퍼의  출력 데이터는 리듀서가 압축 해제해서 분석할 수 있고요. 

 

이때 압축이 가능한 라이브러리는 gzip, b2zip 등이 있습니다.

지난번 포스팅에서 소개해드린 lzo의 경우 라이센스 이슈로 하둡 공식 패키지에서는 제외됐지만,

사용자가 원할 경우 약간의 번거로운(?) 셋팅만 해주면 사용할 수 있습니다. ㅠㅠ

 

그리고 오늘 소개해드릴 스내피는 하둡 1.0.2 버전부터 하둡 패키지에 포함이 되었으며,

하둡 1.0.2를 설치할 경우, 하둡에서 시스템에 설치된 스내피를 로딩하게 되어 있습니다.

 

제가 스내피를 접하게 된 것도, 하둡 1.0.2를 설치한 후 맵리듀스 잡을 돌릴 때 처음보는 로그 메시지를 봤기 때문인데요.

 

12/04/10 08:54:43 INFO input.FileInputFormat: Total input paths to process : 1

12/04/10 08:54:43 INFO util.NativeCodeLoader: Loaded the native-hadoop library

12/04/10 08:54:43 WARN snappy.LoadSnappy: Snappy native library not loaded

12/04/10 08:54:43 INFO mapred.JobClient: Running job: job_201204100843_0001

 

위 로그를 보시면, 스내피 라이브러리가 로딩되지 않았다는 WARNING 로그가 발생하는데요.

이 로그를 보고 스내피를 알아보기 시작했습니다.

 

스내피는 구글에서 자체 개발한 압축 라이브러리이며,

최고의 압축률 보다는 적정 수준의 압축률을 제공하면서 빠르게 압축하고 해제하는 것을 목표로 합니다.

또한 초당 250MB 정도를 압축하고, 다른 압축에 비해 CPU 자원도 덜 소모합니다.

 

아래 주소가 스내피의 공식 홈피이며, 여기서 간단한 소개문서와 라이브러리를 다운 받으실 수 있습니다.

http://code.google.com/p/snappy/

 

설치는 다음과 같이 진행하시면 되며, 일반적인 tar 패키지처럼 매우 쉽게 할 수 있습니다. ^^

 

1.     Tar 파일 다운로드 à http://code.google.com/p/snappy/downloads/detail?name=snappy-1.0.5.tar.gz

2.     Tar 파일을 리눅스에 업로드 (wget으로 다운받았다면 Skip)

3.     root 계정으로 스내피 설치

A.     tar -xvf snappy-1.0.5.tar.gz

B.      ./configure --enable-shared

C.      make

D.     make install

4.     네이티브 스내피 라이브러리를 하둡으로 복사

A.     cp /usr/local/lib/libsnappy.* 하둡홈/lib/native/Linux-amd64-64

B.      cp /usr/local/iib/libsnappy*.* 하둡홈/lib/native/Linux-i386-32

 

스내피 설치 후 하둡을 재시작하고 맵리듀스 잡을 실행하면, 스내피 관련 로그가 다음과 같이 변경될 것을 확인할 수 있습니다.

12/04/10 13:34:39 INFO input.FileInputFormat: Total input paths to process : 1

12/04/10 13:34:39 WARN snappy.LoadSnappy: Snappy native library is available

12/04/10 13:34:39 INFO util.NativeCodeLoader: Loaded the native-hadoop library

12/04/10 13:34:39 INFO snappy.LoadSnappy: Snappy native library loaded

12/04/10 13:34:40 INFO mapred.JobClient: Running job: job_201204101328_0001

 

하둡 1.0.2 이전 버전을 사용하시는 경우는 core-site.xml에 다음과 같은 설정을 추가하셔야 할 것입니다.

테스트는 안해 봤으니 참고만 하시고요. ^^;;

  <property>
    <name>io.compression.codecs</name>
    <value>
      org.apache.hadoop.io.compress.GzipCodec,
      org.apache.hadoop.io.compress.DefaultCodec,
      org.apache.hadoop.io.compress.BZip2Codec,
      org.apache.hadoop.io.compress.SnappyCodec
    </value>
  </property>

 

맵리듀스 자바 코드에서 스내피를 사용할 때는 다음과 같이 코딩 하시면 됩니다.

Configuration conf = new Configuration();

 

// 맵 태스크 출력 데이터 압축 설정

conf.set("mapred.compress.map.output","true"); //압축 여부
conf.set("mapred.map.output.compression.codec","org.apache.hadoop.io.compress.SnappyCodec"); //
압축 포맷

//
맵리듀스 출력 데이터 압축 설정
conf.set("mapred.output.compress","true"); //
압축 여부
conf.set("mapred.output.compression","org.apache.hadoop.io.compress.SnappyCodec"); //
압축 포맷

 

마지막으로 매퍼의 출력 데이터를 압축하지 않았을 때, Gzip과 스내피로 매퍼의 출력 데이터를 압축했을 때의 성능을 비교해보겠습니다.

스터디용으로 만든 500메가 정도의 데이터를 분석했더니 아래와 같은 결과가 나왔습니다.

 

카운터

압축 미적용

Gzip 적용

스내피 적용

맵리듀스 잡 수행 시간

114

140

12

FILE_BYTES_READ

370,448,652

908,885

17,652,690

HDFS_BYTES_READ

445,384,492

445,384,492

445,384,492

FILE_BYTES_WRITTEN

555,848,855

1,536,514

26,649,694

HDFS_BYTES_WRITTEN

1,766

725

917

Reduce shuffle bytes

157,260,456

383,211

8,820,643

Spilled Records

27783,630

27,783,630

27,783,630

Map output bytes

166,701,780

166,701,780

166,701,780

CPU time spent (ms)

165,200

245,940

140,870

Total committed heap usage

2,068,316,160

2,064,973,824

2,010,644,480

 

압축을 적용했을 때가 파일 I/O가 확실히 감소했으며,

Gzip에 비해 스내피의 압축율이 떨어지지만, 실행 시간과 CPU 점유율은 Gzip 보다 눈에 띄게 좋아졌습니다.

 

실제로 수십 기가 이상의 데이터를 압축했을 때 얼마나 차이가 날지 기대가 되네요. ^^

 

P.S 참고로 스내피는 64비트 OS에 최적화가 되어 있으니, 32비트를 사용하시는 분들 꼭 미리 확인하세요!

저작자 표시 비영리 변경 금지
신고
댓글
  • 프로필사진 papa 안녕하세요. 처음 뵙겠습니다.
    제가 싱글모드로 설치/테스트를 해보고 있습니다.

    그런데 아래와 같은 메세지를 만났습니다. 도저히 어디가 잘 못 되었는지 모르겠습니다.
    hadoop-1.0.3 입니다. snappy는 1.0.5 centos 6.x 64비트 빌드했습니다.

    Exception in thread "main" java.lang.IllegalArgumentException: Compression codec

    org.apache.hadoop.io.compress.SnappyCodec
    not found.
    at org.apache.hadoop.io.compress.CompressionCodecFactory.getCodecClasses(CompressionCodecFactory.java:96)
    at org.apache.hadoop.io.compress.CompressionCodecFactory.<init>(CompressionCodecFactory.java:134)
    at org.apache.hadoop.mapreduce.lib.input.TextInputFormat.isSplitable(TextInputFormat.java:46)
    at org.apache.hadoop.mapreduce.lib.input.FileInputFormat.getSplits(FileInputFormat.java:258)
    at org.apache.hadoop.mapred.JobClient.writeNewSplits(JobClient.java:962)
    at org.apache.hadoop.mapred.JobClient.writeSplits(JobClient.java:979)
    at org.apache.hadoop.mapred.JobClient.access$600(JobClient.java:174)
    at org.apache.hadoop.mapred.JobClient$2.run(JobClient.java:897)
    at org.apache.hadoop.mapred.JobClient$2.run(JobClient.java:850)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:396)
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1121)
    at org.apache.hadoop.mapred.JobClient.submitJobInternal(JobClient.java:850)
    at org.apache.hadoop.mapreduce.Job.submit(Job.java:500)
    at org.apache.hadoop.mapreduce.Job.waitForCompletion(Job.java:530)
    at wordcount.WordCountJobWithComp.main(WordCountJobWithComp.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.hadoop.util.RunJar.main(RunJar.java:156)
    Caused by: java.lang.ClassNotFoundException:

    org.apache.hadoop.io.compress.SnappyCodec

    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:247)
    at org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:820)
    at org.apache.hadoop.io.compress.CompressionCodecFactory.getCodecClasses(CompressionCodecFactory.java:89)
    ... 20 more
    2012.07.16 15:09 신고
  • 프로필사진 papa 한 가지 더 궁금한 것은 위의 표 같은 것을 만들어야 하는데요.
    어떻게 만들어야 할까요?
    2012.07.16 16:02 신고
  • 프로필사진 papa
    하루종일 여기 블로그에 쓰네요. ^^ 죄송합니다. ^^

    압축되고 안되고는 확인을 했습니다. 그런데
    "WARN snappy.LoadSnappy: Snappy native library not loaded" 이 메세지는 계속 뜹니다.

    라이브러리 복사까지 다 했는데... 메세지가 뜹니다. 왜 그럴까요????
    2012.07.16 17:29 신고
  • 프로필사진 blrunner 안녕하세요~papa님.
    아무래도 snappy 라이브러리가 제대로 설치되지 않은 것 같네요.
    제가 포스팅한 내용을 보면 snappy 네이티브 파일을 하둡홈의 lib/native로 복사하라고 되어 있는데요. 네이티브 파일 복사를 하신 게 맞나요?

    그리고 표는 mapred.output.compression의 포맷을 GZip, Snappy를 적용해서 작성하시면 됩니다. 압축을 적용하지 않는 경우는 compression 옵션을 빼면 되겠지요.^^;;
    2012.07.18 14:39 신고
댓글쓰기 폼