HBase의 압축 및 데이터 블록 인코딩

HBase의 압축 및 데이터 블록 인코딩 (Compression and Data Block Encoding In HBase)

HBase가 데이터 블록과 행 키를 압축·인코딩하는 다양한 방법을 설명하는 페이지예요. 저장 공간을 줄이고 성능을 최적화하려는 운영자에게 필수적입니다.

출처: 문서

본문

이 섹션에서 언급하는 codec은 데이터 블록이나 행 키를 인코딩·디코딩하기 위한 것이에요. 복제(replication) codec에 대한 정보는 cluster.replication.preserving.tags를 참고하세요.

HBase는 ColumnFamily에서 활성화할 수 있는 여러 가지 압축 알고리즘을 지원해요. 데이터 블록 인코딩은 정렬된 행 키와 특정 테이블의 스키마 같은 HBase의 기본적인 설계·패턴을 활용해서 키의 정보 중복을 제한하려 해요. Compressor는 셀의 크고 불투명한 바이트 배열 크기를 줄여, 압축되지 않은 데이터를 저장하는 데 필요한 저장 공간을 크게 줄일 수 있어요.

Compressor와 데이터 블록 인코딩은 같은 ColumnFamily에서 함께 사용할 수 있어요.

변경 사항은 컴팩션 시 적용됨 (Changes Take Effect Upon Compaction)

ColumnFamily의 압축이나 인코딩을 변경하면, 변경 사항은 컴팩션 중에 적용돼요.

일부 codec은 GZip 압축 같은 Java에 내장된 기능을 활용해요. 다른 것들은 네이티브 라이브러리에 의존해요. 네이티브 라이브러리는 HBase의 라이브러리 디렉터리에 설치된 codec 의존성을 통해, 또는 Hadoop codec을 활용한다면 Hadoop의 일부로 사용할 수 있어요. Hadoop codec은 일반적으로 네이티브 코드 구성 요소를 가지므로, Making use of Hadoop Native Libraries in HBase의 Hadoop 네이티브 바이너리 지원 설치 지침을 따르세요.

이 섹션은 HBase와 함께 사용·테스트되는 일반적인 codec을 논의해요.

어떤 codec을 사용하든, 제대로 설치되었고 클러스터의 모든 노드에서 사용 가능한지 테스트하세요. 새로 배포된 노드에서 codec을 사용할 수 있게 하려면 추가 운영 단계가 필요할 수 있어요. compression.test 유틸리티를 사용해 특정 codec이 올바르게 설치됐는지 확인할 수 있어요.

HBase가 compressor를 사용하도록 구성하려면 compressor.install을 참고하세요. ColumnFamily에 compressor를 활성화하려면 changing.compression을 참고하세요. ColumnFamily에 데이터 블록 인코딩을 활성화하려면 data.block.encoding.enable을 참고하세요.

블록 Compressor (Block Compressors)

  • NONE 이 압축 타입 상수는 압축 없음을 선택하며 기본값이에요.
  • BROTLI Brotli는 LZ77 알고리즘의 현대적 변형, Huffman 코딩, 2차 컨텍스트 모델링을 결합해 데이터를 압축하는 범용 무손실 압축 알고리즘이며, 현재 사용 가능한 최고의 범용 압축 방법들과 비교될 만한 압축 비율을 제공해요. 속도는 GZ와 비슷하지만 더 밀도 높은 압축을 제공해요.
  • BZIP2 Bzip2는 Burrows-Wheeler 블록 정렬 텍스트 압축 알고리즘과 Huffman 코딩으로 파일을 압축해요. 압축은 일반적으로 사전(LZ) 기반 compressor보다 훨씬 좋지만, 압축과 해제 모두 다른 옵션에 비해 느릴 수 있어요.
  • GZ gzip은 LZ77과 Huffman 코딩의 결합인 DEFLATE 알고리즘에 기반해요. Java Runtime Environment에서 보편적으로 사용 가능하므로 좋은 최소 공통 분모 옵션이에요. 하지만 Zstandard 같은 더 현대적인 알고리즘에 비하면 상당히 느려요.
  • LZ4 LZ4는 압축·해제 속도에 초점을 맞춘 무손실 데이터 압축 알고리즘이에요. Brotli, DEFLATE, Zstandard 등과 마찬가지로 LZ77 계열 압축 알고리즘에 속해요. 우리 마이크로벤치마크에서 LZ4는 그 계열에서 압축·해제 모두 가장 빠른 옵션이며, 우리가 보편적으로 권장하는 옵션이에요.
  • LZMA LZMA는 LZ77 알고리즘과 다소 유사한 사전 압축 방식으로, 계산 비용이 비싼 예측 모델과 가변 크기 압축 사전으로 매우 높은 압축 비율을 달성하면서도 다른 일반적으로 사용되는 압축 알고리즘과 유사한 해제 속도를 유지해요. LZMA는 일반적인 압축 비율에서 모든 옵션을 능가하지만, compressor로서 특히 높은 압축 수준으로 구성하면 극도로 느릴 수 있어요.
  • LZO LZO는 또 다른 LZ 변형 데이터 압축 알고리즘으로, 해제 속도에 초점을 맞춘 구현이에요. 거의 LZ4만큼 빠르지만 완전하진 않아요.
  • SNAPPY Snappy는 LZ77의 아이디어에 기반하지만 매우 높은 압축 속도에 최적화되어, 그 대가로 "합리적인" 압축만 달성해요. LZ4만큼 빠르지만 압축은 그만큼 좋지 않아요. 우리는 어떤 하드웨어 아키텍처의 어떤 Java 런타임에서도 보편적으로 사용 가능한 옵션으로 GZ 대신 쓸 수 있는 순수 Java Snappy codec을 제공해요.
  • ZSTD Zstandard는 사전 매칭 단계(LZ77)와 큰 검색 창, 빠른 엔트로피 코딩 단계를 결합하며 Finite State Entropy와 Huffman 코딩을 모두 사용해요. 압축 속도는 가장 빠른 수준과 가장 느린 수준 사이에서 20배 이상 차이가 날 수 있는 반면, 해제는 균일하게 빠르며 가장 빠른 수준과 가장 느린 수준 사이에서 20% 미만으로 차이가 나요. ZStandard는 사용 가능한 압축 codec 옵션 중 가장 유연해서, 레벨 1에서 LZ4와 유사한 압축 비율(다만 성능은 약간 낮음), 중간 레벨에서 DEFLATE에 비견되는 압축 비율(다만 성능은 더 좋음), 높은 레벨에서 LZMA와 유사한 밀도 높은 압축(및 LZMA와 유사한 압축 속도)을 제공하면서 보편적으로 빠른 해제를 제공해요.

데이터 블록 인코딩 유형 (Data Block Encoding Types)

Prefix

종종 키는 매우 비슷해요. 특히 키는 공통 접두사를 공유하고 끝부분 근처에서만 다른 경우가 많아요. 예를 들어 한 키는 RowKey:Family:Qualifier0이고 다음 키는 RowKey:Family:Qualifier1일 수 있어요. Prefix 인코딩에서 현재 키와 이전 키가 공유하는 접두사의 길이를 담는 추가 컬럼이 더해져요. 여기 첫 키가 그 앞의 키와 완전히 다르다고 가정하면, 접두사 길이는 0이에요.

두 번째 키는 첫 23자를 공유하므로 접두사 길이가 23이에요.

당연히 키들이 공통점이 없는 경향이 있다면 Prefix는 큰 이점을 제공하지 못해요.

다음 이미지는 데이터 블록 인코딩이 없는 가상의 ColumnFamily를 보여줘요.

(이미지)

다음은 같은 데이터에 prefix 데이터 인코딩을 적용한 모습이에요.

(이미지)

Diff

Diff 인코딩은 Prefix 인코딩을 확장해요. 키를 순차적으로 단일 바이트 시리즈로 간주하는 대신, 각 키 필드를 쪼개서 키의 각 부분을 더 효율적으로 압축할 수 있게 해요.

timestamp와 type 두 개의 새 필드가 추가돼요.

ColumnFamily가 이전 행과 같으면 현재 행에서 생략돼요.

키 길이, 값 길이, type이 이전 행과 같으면 해당 필드는 생략돼요.

또한 압축을 높이기 위해 timestamp는 전체로 저장되는 대신 이전 행의 timestamp와의 Diff로 저장돼요. Prefix 예제의 두 행 키가 주어지고 timestamp가 정확히 일치하며 type이 같다면, 두 번째 행에 대해 값 길이나 type을 저장할 필요가 없고, 두 번째 행의 timestamp 값은 전체 timestamp 대신 그냥 0이에요.

Diff 인코딩은 쓰기·스캔이 더 느리고 더 많은 데이터가 캐시되므로 기본적으로 비활성화돼요.

이 이미지는 이전 이미지들과 같은 ColumnFamily에 Diff 인코딩을 적용한 모습이에요.

(이미지)

Fast Diff

Fast Diff는 Diff와 비슷하게 동작하지만 더 빠른 구현을 사용해요. 또한 데이터 자체가 이전 행과 같은지 추적하는 단일 비트를 저장하는 또 다른 필드를 추가해요. 같다면 데이터는 다시 저장되지 않아요.

긴 키나 많은 컬럼이 있다면 Fast Diff가 권장 codec이에요.

데이터 형식은 Diff 인코딩과 거의 동일해서 이를 보여줄 이미지는 없어요.

Prefix Tree

Prefix tree 인코딩은 HBase 0.96에서 실험적 기능으로 도입됐어요. Prefix, Diff, Fast Diff 인코더와 유사한 메모리 절감을 제공하지만, 더 느린 인코딩 속도를 대가로 더 빠른 랜덤 액세스를 제공해요. hbase-2.0.0에서 제거됐어요. 좋은 아이디어였지만 수요가 적었어요. 이 노력을 되살리는 데 관심이 있다면 hbase dev 메일링 리스트에 글을 남기세요.

어떤 Compressor 또는 데이터 블록 인코더를 사용할까 (Which Compressor or Data Block Encoder To Use)

사용할 압축 또는 codec 유형은 데이터의 특성에 따라 달라져요. 잘못된 유형을 선택하면 데이터가 더 적게가 아니라 더 많은 공간을 차지할 수 있고 성능에 영향을 줄 수 있어요.

일반적으로 더 작은 크기와 더 빠른 압축·해제 사이에서 옵션을 저울질해야 해요. 다음은 Documenting Guidance on compression and codecs의 논의를 확장한 일반 지침이에요.

  • 대부분의 경우 LZ4나 Snappy를 기본으로 활성화하는 것이 좋은 선택이에요. 성능 오버헤드가 낮고 합리적인 공간 절감을 제공하니까요. 빠른 압축 알고리즘은 거의 항상 약간의 CPU 사용 증가를 더 나은 I/O 효율과 맞바꿔 전체 시스템 성능을 개선해요.
  • 값이 크다면(이미지처럼 사전 압축되지 않은 경우) 데이터 블록 compressor를 사용하세요.
  • 자주 접근되지 않는 콜드 데이터의 경우, 사용 사례에 따라 높은 압축 수준의 Zstandard나 LZMA, 특히 높은 엔트로피 바이너리 데이터에 적합하고, 웹 데이터와 특성이 비슷한 데이터에는 Brotli를 선택하는 것이 합리적일 수 있어요. Bzip2도 합리적인 옵션이지만 Zstandard가 월등한 해제 속도를 제공할 가능성이 매우 높아요.
  • 자주 접근되는 핫 데이터의 경우 LZ4, Snappy, LZO, 또는 낮은 압축 수준의 Zstandard만 원할 거예요. 이러한 옵션은 압축 비율이 그렇게 높지는 않지만 그 대가로 시스템 성능을 과도하게 저하시키지 않아요.
  • (값에 비해) 긴 키나 많은 컬럼이 있다면 prefix 인코더를 사용하세요. FAST_DIFF가 권장돼요.
  • WAL 값 압축을 활성화한다면 LZ4나 SNAPPY 압축, 또는 레벨 1의 Zstandard를 고려하세요. WAL의 읽기·쓰기는 성능에 중요해요. 그렇지만 이러한 압축 옵션의 I/O 절감이 전체 시스템 성능을 개선할 수 있어요.

HBase에서 Hadoop 네이티브 라이브러리 활용하기 (Making use of Hadoop Native Libraries in HBase)

Hadoop 공유 라이브러리에는 압축 라이브러리와 빠른 crc'ing(칩셋이 지원하면 하드웨어 crc'ing)을 포함한 여러 기능이 있어요. 이 기능을 HBase에서 사용할 수 있게 하려면 다음을 하세요. HBase/Hadoop은 네이티브 라이브러리 버전을 찾지 못하면 대안을 사용하거나 — 명시적 compressor를 요청했는데 대안도 없다면 — 그냥 실패해요.

먼저 Hadoop을 확인하세요. Hadoop 프로세스를 시작할 때 다음 메시지가 보이면 수정하세요.

16/02/09 22:40:24 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable

이는 네이티브 라이브러리를 제대로 가리키고 있지 않거나, 네이티브 라이브러리가 다른 플랫폼용으로 컴파일됐다는 뜻이에요. 먼저 이것을 수정하세요.

그런 다음 HBase 로그에 다음이 보이면 HBase가 Hadoop 네이티브 라이브러리를 찾지 못했다는 것을 알 수 있어요.

2014-08-07 09:26:20,139 WARN [main] util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable

라이브러리가 성공적으로 로드되면 WARN 메시지가 표시되지 않아요. 보통 이는 잘 되고 있다는 뜻이지만 계속 읽어보세요.

Hadoop에 HBase를 실행하는 플랫폼에 맞는 네이티브 라이브러리가 포함되어 있다고 가정해 봐요. Hadoop 네이티브 라이브러리가 HBase에서 사용 가능한지 확인하려면(Hadoop 2.1 이상에서 사용 가능한) 다음 도구를 실행하세요.

$ ./bin/hbase --config ~/conf_hbase org.apache.hadoop.util.NativeLibraryChecker 2014-08-26 13:15:38,717 WARN [main] util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable Native library checking: hadoop: false zlib: false snappy: false lz4: false bzip2: false 2014-08-26 13:15:38,863 INFO [main] util.ExitUtil: Exiting with status 1

위는 네이티브 hadoop 라이브러리가 HBase 컨텍스트에서 사용 가능하지 않음을 보여줘요.

NativeLibraryChecker 도구는 모든 것이 좋다고 — 즉 모든 lib가 'true'로 사용 가능하다고 — 돌아올 수 있지만, 아래 처방을 그래도 따라 HBase가 사용할 때 네이티브 lib가 HBase 컨텍스트에서 사용 가능하도록 보장하세요.

위 문제를 해결하려면 Hadoop과 HBase 설치가 파일시스템에서 인접하다면 Hadoop 네이티브 라이브러리를 로컬로 복사하거나 심링크하세요. hbase-env.sh에서 LD_LIBRARY_PATH 환경 변수를 설정해 위치를 가리킬 수도 있어요.

JVM이 네이티브 라이브러리를 찾는 위치는 "시스템 종속적"이에요(java.lang.System#loadLibrary(name) 참고). Linux에서 기본적으로 HBase가 설치된 플랫폼의 라벨인 PLATFORM의 lib/native/PLATFORM을 찾아봐요. 로컬 Linux 머신에서 이는 java 속성 os.name과 os.arch의 연결에 32비트인지 64비트인지가 붙은 것 같아요. HBase는 시작 시 모든 java 시스템 속성을 출력하므로 로그에서 os.name과 os.arch를 찾으세요. 예:

... 2014-08-06 15:27:22,853 INFO [main] zookeeper.ZooKeeper: Client environment:os.name=Linux 2014-08-06 15:27:22,853 INFO [main] zookeeper.ZooKeeper: Client environment:os.arch=amd64 ...

이 경우 PLATFORM 문자열은 Linux-amd64-64예요. lib/native/Linux-amd64-64에 Hadoop 네이티브 라이브러리를 복사하거나 심링크하면 그것들이 발견되도록 보장돼요. 이 변경 후 롤링 재시작하세요.

다음은 심링크를 설정하는 방법의 예시예요. hadoop과 hbase 설치가 홈 디렉터리에 있다고 하죠. hadoop 네이티브 lib가 ~/hadoop/lib/native에 있다고 가정해요. Linux-amd64-64 플랫폼이라고 가정해요. 이 경우 hbase가 그것들을 찾을 수 있도록 hadoop 네이티브 lib를 링크하려면 다음을 하면 돼요.

... $ mkdir -p ~/hbaseLinux-amd64-64 -> /home/stack/hadoop/lib/native/lib/native/ $ cd ~/hbase/lib/native/ $ ln -s ~/hadoop/lib/native Linux-amd64-64 $ ls -la

Linux-amd64-64 -> /home/USER/hadoop/lib/native

...

스택 트레이스에 PureJavaCrc32C가 보이거나 perf trace에 아래 같은 것이 보이면 네이티브가 작동하지 않는 거예요. 네이티브 대신 java CRC 함수를 사용하고 있는 거예요.

5.02% perf-53601.map [.] Lorg/apache/hadoop/util/PureJavaCrc32C;.update

네이티브 체크섬 지원에 대한 자세한 내용은 HBASE-11927 Use Native Hadoop Library for HFile checksum (And flip default from CRC32 to CRC32C)를 참고하세요. 특히 프로세서가 하드웨어 CRC를 지원하는지 확인하는 방법은 릴리스 노트를 참고하세요. 또는 Apache Checksums in HBase 블로그 글을 확인하세요.

LD_LIBRARY_PATH 환경 변수로 Hadoop lib를 가리키는 방법의 예시는 다음과 같아요.

$ LD_LIBRARY_PATH=~/hadoop-2.5.0-SNAPSHOT/lib/native ./bin/hbase --config ~/conf_hbase org.apache.hadoop.util.NativeLibraryChecker 2014-08-26 13:42:49,332 INFO [main] bzip2.Bzip2Factory: Successfully loaded & initialized native-bzip2 library system-native 2014-08-26 13:42:49,337 INFO [main] zlib.ZlibFactory: Successfully loaded & initialized native-zlib library Native library checking: hadoop: true /home/stack/hadoop-2.5.0-SNAPSHOT/lib/native/libhadoop.so.1.0.0 zlib: true /lib64/libz.so.1 snappy: true /usr/lib64/libsnappy.so.1 lz4: true revision:99 bzip2: true /lib64/libbz2.so.1

HBase를 시작할 때 hbase-env.sh에서 LD_LIBRARY_PATH 환경 변수를 설정하세요.

Compressor 설정, 설치 및 사용 (Compressor Configuration, Installation, and Use)

Compressor용 HBase 설정 (Configure HBase For Compressors)

압축 codec은 HBase compressor 모듈이나 Hadoop의 네이티브 압축 지원으로 제공돼요. 위에서 설명한 대로 테이블이나 컬럼 패밀리 스키마 또는 사이트 설정에서 짧은 라벨(예: Snappy의 snappy, ZStandard의 zstd)로 압축 유형을 선택해요. 어떤 codec 구현이 그 라벨을 지원하기 위해 동적으로 로드될지는 사이트 설정으로 구성할 수 있어요.

Algorithm label Codec implementation configuration key Default value
BROTLI hbase.io.compress.brotli.codec org.apache.hadoop.hbase.io.compress.brotli.BrotliCodec
BZIP2 hbase.io.compress.bzip2.codec org.apache.hadoop.io.compress.BZip2Codec
GZ hbase.io.compress.gz.codec org.apache.hadoop.hbase.io.compress.ReusableStreamGzipCodec
LZ4 hbase.io.compress.lz4.codec org.apache.hadoop.io.compress.Lz4Codec
LZMA hbase.io.compress.lzma.codec org.apache.hadoop.hbase.io.compress.xz.LzmaCodec
LZO hbase.io.compress.lzo.codec com.hadoop.compression.lzo.LzoCodec
SNAPPY hbase.io.compress.snappy.codec org.apache.hadoop.io.compress.SnappyCodec
ZSTD hbase.io.compress.zstd.codec org.apache.hadoop.io.compress.ZStandardCodec

사용 가능한 codec 구현 옵션은 다음과 같아요.

Label Codec implementation class Notes
BROTLI org.apache.hadoop.hbase.io.compress.brotli.BrotliCodec Implemented with Brotli4j
BZIP2 org.apache.hadoop.io.compress.BZip2Codec Hadoop native codec
GZ org.apache.hadoop.hbase.io.compress.ReusableStreamGzipCodec Requires the Hadoop native GZ codec
LZ4 org.apache.hadoop.io.compress.Lz4Codec Hadoop native codec
LZ4 org.apache.hadoop.hbase.io.compress.aircompressor.Lz4Codec Pure Java implementation
LZ4 org.apache.hadoop.hbase.io.compress.lz4.Lz4Codec Implemented with lz4-java
LZMA org.apache.hadoop.hbase.io.compress.xz.LzmaCodec Implemented with XZ For Java
LZO com.hadoop.compression.lzo.LzoCodec Hadoop native codec, requires GPL licensed native dependencies
LZO org.apache.hadoop.io.compress.LzoCodec Hadoop native codec, requires GPL licensed native dependencies
LZO org.apache.hadoop.hbase.io.compress.aircompressor.LzoCodec Pure Java implementation
SNAPPY org.apache.hadoop.io.compress.SnappyCodec Hadoop native codec
SNAPPY org.apache.hadoop.hbase.io.compress.aircompressor.SnappyCodec Pure Java implementation
SNAPPY org.apache.hadoop.hbase.io.compress.xerial.SnappyCodec Implemented with snappy-java
ZSTD org.apache.hadoop.io.compress.ZStandardCodec Hadoop native codec
ZSTD org.apache.hadoop.hbase.io.compress.aircompressor.ZstdCodec Pure Java implementation, limited to a fixed compression level, not data compatible with the Hadoop zstd codec
ZSTD org.apache.hadoop.hbase.io.compress.zstd.ZstdCodec Implemented with zstd-jni, supports all compression levels, supports custom dictionaries

주어진 압축 알고리즘에 대해 선호하는 codec 구현 옵션을 사이트 설정에서 다음과 같이 지정하세요.

... hbase.io.compress.lz4.codec org.apache.hadoop.hbase.io.compress.lz4.Lz4Codec ...

Compressor 마이크로벤치마크 (Compressor Microbenchmarks)

https://github.com/apurtell/jmh-compression-tests를 참고하세요.

IntegrationLoadTestCommonCrawl로 수집된 Common Crawl 데이터를 포함한 두 HFile에서 256MB(정확히 258,126,022 바이트)의 블록 데이터를 추출했고, 총 2,680개 블록이었어요. 이 데이터는 각 새 codec 구현으로 마치 HFile에 쓰기 위해 블록 데이터를 다시 압축하듯 처리됐지만 아무것도 쓰지 않고, codec 자체의 CPU 시간과 리소스 요구만 비교했어요. 절대 성능 수치는 배포의 하드웨어·소프트웨어 특성에 따라 달라져요. 상대적 차이가 흥미로운 부분이에요. 측정 시간은 256MB 파일의 모든 블록을 압축하는 데 필요한 평균 시간(밀리초)이에요. 이것은 이 내용을 포함한 HFile을 쓰는 데 걸리는 시간에서 블록 인코딩과 실제 영속화의 I/O 오버헤드를 뺀 값이에요.

결과는 다음과 같아요.

Codec Level Time (milliseconds) Result (bytes) Improvement
AirCompressor LZ4 - 349.989 ± 2.835 76,999,408 70.17%
AirCompressor LZO - 334.554 ± 3.243 79,369,805 69.25%
AirCompressor Snappy - 364.153 ± 19.718 80,201,763 68.93%
AirCompressor Zstandard 3 (effective) 1108.267 ± 8.96 955,129,189 78.64%
Brotli 1 593.107 ± 2.376 58,672,319 77.27%
Brotli 3 1345.195 ± 27.327 53,917,438 79.11%
Brotli 6 2812.411 ± 25.372 48,696,441 81.13%
Brotli 10 74615.936 ± 224.854 44,970,710 82.58%
LZ4 (lz4-java) - 303.045 ± 0.783 76,974,364 70.18%
LZMA 1 6410.428 ± 115.06 549,948,535 80.65%
LZMA 3 8144.620 ± 152.119 49,109,363 80.97%
LZMA 6 43802.576 ± 382.025 46,951,810 81.81%
LZMA 9 49821.979 ± 580.110 46,951,810 81.81%
Snappy (xerial) - 360.225 ± 2.324 80,749,937 68.72%
Zstd (zstd-jni) 1 654.699 ± 16.839 56,719,994 78.03%
Zstd (zstd-jni) 3 839.160 ± 24.906 54,573,095 78.86%
Zstd (zstd-jni) 5 1594.373 ± 22.384 52,025,485 79.84%
Zstd (zstd-jni) 7 2308.705 ± 24.744 50,651,554 80.38%
Zstd (zstd-jni) 9 3659.677 ± 58.018 50,208,425 80.55%
Zstd (zstd-jni) 12 8705.294 ± 58.080 49,841,446 80.69%
Zstd (zstd-jni) 15 19785.646 ± 278.080 48,499,508 81.21%
Zstd (zstd-jni) 18 47702.097 ± 442.670 48,319,879 81.28%
Zstd (zstd-jni) 22 97799.695 ± 1106.571 48,212,220 81.32%

Master에서의 Compressor 지원 (Compressor Support On the Master)

HBase 0.95에서 새 설정 항목이 도입됐는데, Master를 확인해 어떤 데이터 블록 인코더가 설치·구성됐는지 판단하고 전체 클러스터가 동일하게 구성됐다고 가정해요. 이 옵션 hbase.master.check.compression은 기본적으로 true예요. 이는 HBASE-6370에 설명된, region server가 지원하지 않는 codec을 지원하도록 테이블을 생성·수정해 오랜 시간이 지나서야 발생하고 디버깅하기 어려운 실패를 유발하는 상황을 방지해요.

hbase.master.check.compression이 활성화되면 Master가 region server를 실행하지 않더라도 모든 원하는 compressor의 라이브러리를 Master에 설치·구성해야 해요.

네이티브 라이브러리로 GZ 지원 설치 (Install GZ Support Via Native Libraries)

HBase는 CLASSPATH에 네이티브 Hadoop 라이브러리가 없는 한 Java의 내장 GZip 지원을 사용해요. CLASSPATH에 라이브러리를 추가하는 권장 방법은 HBase를 실행하는 사용자에게 HBASE_LIBRARY_PATH 환경 변수를 설정하는 거예요. 네이티브 라이브러리를 사용할 수 없고 Java의 GZIP을 사용한다면 로그에 Got brand-new compressor 보고가 나타날 거예요. brand.new.compressor)를 참고하세요.

Hadoop 네이티브 LZO 지원 설치 (Install Hadoop Native LZO Support)

HBase은 Apache Software License(ASL)를, LZO는 GPL 라이선스를 사용하므로 HBase는 Hadoop 네이티브 LZO codec을 포함할 수 없어요. HBase용 LZO 지원 구성에 대한 정보는 Hadoop-LZO at Twitter를 참고하세요.

LZO 압축에 의존한다면 Hadoop 네이티브 기본값 대신 순수 Java이고 ASL 라이선스인 AirCompressor LZO codec 옵션을 고려하거나, 네이티브 LZO 지원을 사용할 수 없으면 RegionServer가 시작에 실패하도록 구성하세요. hbase.regionserver.codecs를 참고하세요.

Hadoop 네이티브 LZ4 지원 구성 (Configure Hadoop Native LZ4 Support)

LZ4 지원은 Hadoop에 번들되어 있고 기본 LZ4 codec 구현이에요. Hadoop LZ4 codec을 사용해야 하는 것은 아니에요. lz4-java로 구현된 우리 LZ4 codec은 우수한 성능을 제공하고, AirCompressor LZ4 codec은 네이티브 지원을 사용할 수 없는 곳에서 쓸 수 있는 순수 Java 옵션을 제공해요.

그렇긴 해도 Hadoop 옵션을 선호한다면 HBase를 시작할 때 hadoop 공유 라이브러리(libhadoop.so)에 접근할 수 있는지 확인하세요. 플랫폼을 구성한 뒤(hadoop.native.lib 참고), HBase에서 네이티브 Hadoop 라이브러리로 심볼릭 링크를 만들 수 있어요. 두 소프트웨어 설치가 같은 위치에 있다고 가정해요. 예를 들어 'platform'이 Linux-amd64-64라면:

$ cd $HBASE_HOME $ mkdir lib/native $ ln -s $HADOOP_HOME/lib/native lib/native/Linux-amd64-64

compression 도구로 모든 노드에 LZ4가 설치됐는지 확인하세요. HBase를 시작(또는 재시작)하세요. 그 후 테이블을 생성·alter해서 LZ4를 압축 codec으로 활성화할 수 있어요.:

hbase(main):003:0> alter 'TestTable', {NAME => 'info', COMPRESSION => 'LZ4'}

Hadoop 네이티브 Snappy 지원 설치 (Install Hadoop native Snappy Support)

Snappy 지원은 Hadoop에 번들되어 있고 기본 Snappy codec 구현이에요. Hadoop Snappy codec을 사용해야 하는 것은 아니에요. Xerial Snappy로 구현된 우리 Snappy codec은 우수한 성능을 제공하고, AirCompressor Snappy codec은 네이티브 지원을 사용할 수 없는 곳에서 쓸 수 있는 순수 Java 옵션을 제공해요.

그렇긴 해도 Hadoop codec 옵션을 선호한다면 Snappy 바이너리(CentOS에서 +yum install snappy+ 사용 등)를 설치하거나 소스에서 Snappy를 빌드할 수 있어요. Snappy 설치 후 X가 숫자인 libsnappy.so.X라는 공유 라이브러리를 찾으세요. 소스에서 빌드했다면 공유 라이브러리를 /opt/snappy/lib/ 같은 시스템의 알려진 위치로 복사하세요.

Snappy 라이브러리 외에도 HBase는 Hadoop 공유 라이브러리에 접근해야 해요. X와 Y가 모두 숫자인 libhadoop.so.X.Y 같은 이름이 될 거예요. Hadoop 라이브러리의 위치를 기록하거나 Snappy 라이브러리와 같은 위치로 복사하세요.

Snappy와 Hadoop 라이브러리는 클러스터의 각 노드에서 사용 가능해야 해요. 이를 테스트하는 방법은 compression.test를 참고하세요. 주어진 compressor를 사용할 수 없으면 RegionServer가 시작에 실패하도록 구성하려면 hbase.regionserver.codecs를 참고하세요.

이 각 라이브러리 위치는 HBase를 실행하는 운영체제 사용자에게 HBASE_LIBRARY_PATH 환경 변수에 추가되어야 해요. 변경 사항을 적용하려면 RegionServer를 재시작해야 해요.

CompressionTest

CompressionTest 도구로 compressor가 HBase에서 사용 가능한지 확인할 수 있어요:

$ hbase org.apache.hadoop.hbase.util.CompressionTest hdfs://host/path/to/hbase snappy

RegionServer에서 압축 설정 강제 (Enforce Compression Settings On a RegionServer)

hbase-site.xml에 hbase.regionserver.codecs 옵션을 추가하고 그 값을 사용 가능해야 하는 codec의 쉼표 구분 목록으로 설정하면, 압축이 잘못 구성된 경우 RegionServer가 재시작에 실패하도록 구성할 수 있어요. 예를 들어 이 속성을 lzo,gz로 설정하면 두 compressor가 모두 사용 가능하지 않을 때 RegionServer가 시작에 실패해요. 이는 codec이 제대로 구성되지 않은 채 새 서버가 클러스터에 추가되는 것을 방지해요.

ColumnFamily에서 압축 활성화 (Enable Compression On a ColumnFamily)

ColumnFamily의 압축을 활성화하려면 alter 명령을 사용하세요. 테이블을 다시 만들거나 데이터를 복사할 필요는 없어요. codec을 변경한다면 모든 기존 StoreFile이 컴팩트될 때까지 옛 codec이 여전히 사용 가능한지 확인하세요.

HBaseShell로 기존 테이블의 ColumnFamily 압축 활성화 (Enabling Compression on a ColumnFamily of an Existing Table using HBaseShell)

hbase> alter 'test', {NAME => 'cf', COMPRESSION => 'GZ'}

ColumnFamily 압축으로 새 테이블 생성 (Creating a New Table with Compression On a ColumnFamily)

hbase> create 'test2', { NAME => 'cf2', COMPRESSION => 'SNAPPY' }

ColumnFamily의 압축 설정 확인 (Verifying a ColumnFamily's Compression Settings)

hbase> describe 'test' DESCRIPTION ENABLED 'test', {NAME => 'cf', DATA_BLOCK_ENCODING => 'NONE false ', BLOOMFILTER => 'ROW', REPLICATION_SCOPE => '0', VERSIONS => '1', COMPRESSION => 'GZ', MIN_VERSIONS => '0', TTL => 'FOREVER', KEEP_DELETED_CELLS => 'fa lse', BLOCKSIZE => '65536', IN_MEMORY => 'false', B LOCKCACHE => 'true'} 1 row(s) in 0.1070 seconds

압축 성능 테스트 (Testing Compression Performance)

HBase에는 압축 성능을 테스트할 수 있는 메커니즘을 제공하는 LoadTestTool이라는 도구가 포함돼 있어요. 첫 매개변수로 -write 또는 -update-read를 지정해야 하며, 다른 매개변수를 지정하지 않으면 각 옵션에 대한 사용법이 출력돼요.

LoadTestTool 사용법 (LoadTestTool Usage)

$ bin/hbase org.apache.hadoop.hbase.util.LoadTestTool -h usage: bin/hbase org.apache.hadoop.hbase.util.LoadTestTool Options: -batchupdate Whether to use batch as opposed to separate updates for every column in a row -bloom Bloom filter type, one of [NONE, ROW, ROWCOL] -compression Compression type, one of [LZO, GZ, NONE, SNAPPY, LZ4] -data_block_encoding Encoding algorithm (e.g. prefix compression) to use for data blocks in the test column family, one of [NONE, PREFIX, DIFF, FAST_DIFF, ROW_INDEX_V1]. -encryption Enables transparent encryption on the test table, one of [AES] -generator The class which generates load for the tool. Any args for this class can be passed as colon separated after class name -h,--help Show usage -in_memory Tries to keep the HFiles of the CF inmemory as far as possible. Not guaranteed that reads are always served from inmemory -init_only Initialize the test table only, don't do any loading -key_window The 'key window' to maintain between reads and writes for concurrent write/read workload. The default is 0. -max_read_errors The maximum number of read errors to tolerate before terminating all reader threads. The default is 10. -multiput Whether to use multi-puts as opposed to separate puts for every column in a row -num_keys The number of keys to read/write -num_tables A positive integer number. When a number n is speicfied, load test tool will load n table parallely. -tn parameter value becomes table name prefix. Each table name is in format _1..._n -read <verify_percent>[:#threads=20] -regions_per_server A positive integer number. When a number n is specified, load test tool will create the test table with n regions per server -skip_init Skip the initialization; assume test table already exists -start_key The first key to read/write (a 0-based index). The default value is 0. -tn The name of the table to read or write -update <update_percent>[:#threads=20][:#whether to ignore nonce collisions=0] -write <avg_cols_per_key>:<avg_data_size>[:#threads=20] -zk ZK quorum as comma-separated host names without port numbers -zk_root name of parent znode in zookeeper

LoadTestTool 사용 예시 (Example Usage of LoadTestTool)

$ hbase org.apache.hadoop.hbase.util.LoadTestTool -write 1:10:100 -num_keys 1000000
-read 100:30 -num_tables 1 -data_block_encoding NONE -tn load_test_tool_NONE

데이터 블록 인코딩 활성화 (Enable Data Block Encoding)

Codec은 HBase에 내장되어 있어 추가 설정이 필요 없어요. Codec은 DATA_BLOCK_ENCODING 속성을 설정해 테이블에서 활성화돼요. DATA_BLOCK_ENCODING 설정을 변경하기 전에 테이블을 비활성화하세요. 다음은 HBase Shell을 사용한 예시예요.

테이블에서 데이터 블록 인코딩 활성화 (Enable Data Block Encoding On a Table)

hbase> alter 'test', { NAME => 'cf', DATA_BLOCK_ENCODING => 'FAST_DIFF' } Updating all regions with the new schema... 0/1 regions updated. 1/1 regions updated. Done. 0 row(s) in 2.2820 seconds

ColumnFamily의 데이터 블록 인코딩 확인 (Verifying a ColumnFamily's Data Block Encoding)

hbase> describe 'test' DESCRIPTION ENABLED 'test', {NAME => 'cf', DATA_BLOCK_ENCODING => 'FAST true _DIFF', BLOOMFILTER => 'ROW', REPLICATION_SCOPE => '0', VERSIONS => '1', COMPRESSION => 'GZ', MIN_VERS IONS => '0', TTL => 'FOREVER', KEEP_DELETED_CELLS =

'false', BLOCKSIZE => '65536', IN_MEMORY => 'fals e', BLOCKCACHE => 'true'} 1 row(s) in 0.0650 seconds

더 알아보기 (Learn more)