Compression — 테이블 압축

Compression — 테이블 압축

Cassandra는 테이블 단위로 압축(compression)을 구성할 수 있어요. 압축은 사용자가 설정한 chunk_length_in_kb 단위로 SSTable을 압축해 디스크의 데이터 크기를 줄여요. 압축 알고리즘 선택과 설정, 운영상 영향까지 알아볼게요.

출처: Compression

본문

Cassandra는 테이블 단위로 압축을 구성할 수 있어요. 압축은 사용자 구성 가능한 chunk_length_in_kb 단위로 SSTable을 압축하여 디스크의 데이터 크기를 줄여요. Cassandra SSTable은 불변(immutable)이라 압축의 CPU 비용은 SSTable을 쓸 때만 필요해요. 이후의 데이터 갱신은 다른 SSTable에 들어가므로, UPDATE 명령이 실행되어도 Cassandra가 데이터를 압축 해제·덮어쓰기·재압축할 필요가 없어요. 읽기 시에는 디스크에서 관련 압축 청크를 찾아 전체 청크를 압축 해제한 뒤 나머지 읽기 경로(디스크·멤테이블 병합, 읽기 복구 등)를 진행해요.

압축 알고리즘은 보통 다음 세 영역 사이에서 트레이드오프가 있어요.

  • 압축 속도 (Compression speed): 압축 알고리즘이 데이터를 얼마나 빨리 압축하는지. 데이터가 디스크에 쓰이기 전에 압축되어야 하므로 플러시·컴팩션 경로에서 중요해요.
  • 압축 해제 속도 (Decompression speed): 압축 알고리즘이 데이터를 얼마나 빨리 압축 해제하는지. 데이터가 디스크에서 전체 청크로 읽혀 반환되기 전에 압축 해제되어야 하므로 읽기·컴팩션 경로에서 중요해요.
  • 비율 (Ratio): 압축되지 않은 데이터가 얼마나 줄었는가. Cassandra는 보통 압축되지 않은 크기 대비 디스크 데이터 크기로 측정해요. 예를 들어 비율 0.5는 디스크 데이터가 압축 전 크기의 50%임을 뜻해요. 이 비율은 테이블별로 nodetool tablestatsSSTable Compression Ratio 필드로 노출돼요.

Cassandra는 기본적으로 이 영역에서 서로 다른 트레이드오프를 갖는 다섯 가지 압축 알고리즘을 제공해요. 압축 알고리즘 벤치마크는 많은 요소(압축 수준 같은 알고리즘 파라미터, 입력 데이터의 압축 가능성, 기본 프로세서 종류 등)에 의존하지만, 아래 표는 애플리케이션 요구사항에 따라 시작점을 고르는 데 도움을 줄 거예요. 성능 등급은 대략적이며(A는 상대적으로 좋음, F는 상대적으로 나쁨):

압축 알고리즘 Cassandra 클래스 압축 압축 해제 비율 C* 버전
LZ4 LZ4Compressor A+ A+ C+ >=1.2.2
LZ4HC LZ4Compressor C+ A+ B+ >= 3.6
Zstd ZstdCompressor A- A- A+ >= 4.0
Snappy SnappyCompressor A- A C >= 1.0
Deflate (zlib) DeflateCompressor C C A >= 1.0

일반적으로 성능(지연 시간·처리량)이 중요한 애플리케이션에는 LZ4가 적합한데, CPU 사이클당 우수한 비율을 얻기 때문이에요. 그래서 Cassandra의 기본 선택이에요.

저장(디스크 공간)이 중요한 애플리케이션에는 Zstd가 더 나은 선택일 수 있는데, LZ4보다 상당히 추가 비율을 얻을 수 있기 때문이에요.

Snappy는 이전 버전 호환용으로 유지되며, 보통 LZ4가 선호돼요.

Deflate도 이전 버전 호환용으로 유지되며, 보통 Zstd가 선호돼요.

Configuring Compression (압축 구성)

압축은 CREATE TABLE 또는 ALTER TABLE의 선택 인자로 테이블 단위로 구성해요. 모든 압축기에 공통으로 쓰는 세 가지 옵션이 있어요.

  • class (default: LZ4Compressor) — 사용할 압축 클래스를 지정해요. "fast" 압축기는 LZ4CompressorSnappyCompressor, "good" 비율 압축기는 ZstdCompressorDeflateCompressor예요.
  • chunk_length_in_kb (default: 16KiB) — 압축 청크당 킬로바이트 수를 지정해요. 청크가 클수록 압축 알고리즘에 더 많은 문맥을 주고 비율이 좋아지지만, 읽기 시 디스크에서 더 많이 역직렬화·읽어야 해요.

LZ4Compressor는 다음 추가 옵션을 지원해요.

  • lz4_compressor_type (default fast) — LZ4의 high(일명 LZ4HC) 비율 버전을 쓸지, fast(일명 LZ4) 버전을 쓸지 지정해요. high 모드는 구성 가능한 수준(level)을 지원하며, 운영자는 lz4_high_compressor_level 옵션으로 성능 ↔ 비율 트레이드오프를 조정할 수 있어요. 4.0 이상에서는 Zstd 압축기를 사용하는 게 더 나을 수 있다는 점에 주의하세요.
  • lz4_high_compressor_level (default 9) — 더 많은 압축 비율을 얻기 위해 사용할 CPU 시간을 나타내는 1 이상 17 이하의 숫자예요. 일반적으로 낮은 수준은 "더 빠르지만" 비율이 낮고, 높은 수준은 느리지만 압축 비율이 더 좋아요.

ZstdCompressor는 다음과 같은 추가 옵션을 지원해요.

  • compression_level (default 3) — 더 많은 압축 비율을 얻기 위해 사용할 CPU 시간을 나타내는 -131072 이상 22 이하의 숫자예요. 수준이 낮을수록 속도가 빨라져요(비율 희생). 20~22 값은 "울트라 레벨"이라고 하며 메모리를 더 요구하므로 주의해서 써야 해요. 기본 3은 Deflate 비율과 경쟁하기 좋고, 1은 LZ4와 경쟁하기 좋아요.

사용자는 다음 문법으로 압축을 설정할 수 있어요:

CREATE TABLE keyspace.table (id int PRIMARY KEY)
   WITH compression = {'class': 'LZ4Compressor'};

또는

ALTER TABLE keyspace.table
   WITH compression = {'class': 'LZ4Compressor', 'chunk_length_in_kb': 64};

한번 활성화한 압축은 ALTER TABLE에서 enabled를 false로 설정해 해제할 수 있어요:

ALTER TABLE keyspace.table
   WITH compression = {'enabled':'false'};

주의할 점은 압축 변경이 즉시 적용되지 않는다는 거예요. 데이터는 SSTable이 기록될 때 압축되며, SSTable은 불변이므로 테이블이 컴팩션될 때까지 압축이 수정되지 않아요. ALTER TABLE로 압축 옵션을 변경해도 기존 SSTable은 컴팩션될 때까지 수정되지 않아요. 압축 변경을 즉시 적용해야 한다면 nodetool scrub 또는 nodetool upgradesstables -a로 SSTable 재작성을 트리거하면 되는데, 둘 다 디스크의 SSTable을 다시 만들면서 데이터를 재압축해요.

Other options (기타 옵션)

  • crc_check_chance (default: 1.0) — 읽기 중 각 압축 청크의 체크섬을 검증할 확률을 결정해 데이터 손상을 방지해요. 이 옵션이 성능 문제라는 프로파일이 없으면 끄지 않는 것이 좋아요. 데이터 부패(bitrot)에 대한 Cassandra의 유일한 보호 수단이기 때문이에요. 이전 Cassandra 버전에서는 이 옵션의 중복이 압축 구성에 존재했는데, 후자는 Cassandra 3.0에서 deprecated되고 Cassandra 5.0에서 제거됐어요.

Benefits and Uses (이점과 용도)

압축의 주요 이점은 디스크에 쓰는 데이터 양을 줄인다는 거예요. 크기가 줄어 저장 요구사항을 절약할 뿐 아니라, 데이터 압축의 CPU 오버헤드가 더 큰 압축 전 데이터를 디스크에서 읽고 쓰는 시간보다 빠르므로 읽기·쓰기 처리량이 늘어나는 경우가 많아요.

압축은 행이 많고 행들이 서로 비슷한 테이블에서 가장 유용해요. 비슷한 텍스트 컬럼(반복되는 JSON blob 등)을 담은 테이블은 보통 아주 잘 압축돼요. 이미 압축된 데이터나 무작위 데이터(예: 벤치마크 데이터셋)를 담은 테이블은 보통 잘 압축되지 않아요.

Operational Impact (운영상 영향)

  • 압축 메타데이터는 off-heap에 저장되며 디스크 데이터와 함께 커져요. 디스크 데이터 1TB당 종종 1-3GB의 off-heap RAM이 필요하지만, 정확한 사용량은 chunk_length_in_kb와 압축 비율에 따라 달라져요.
  • 스트리밍 작업은 압축 테이블의 데이터를 압축·압축 해제하는 과정을 포함해요. 일부 코드 경로(예: non-vnode 부트스트랩)에서는 압축의 CPU 오버헤드가 제한 요소가 될 수 있어요.
  • 느린 압축기(Zstd, Deflate, LZ4HC)가 플러시를 너무 오래 막지 않도록, 셋 모두 기본 fast LZ4 압축기로 플러시한 뒤 일반 컴팩션이 데이터를 원하는 압축 전략으로 재압축하는 데 의존해요. 자세한 내용은 CASSANDRA-15379를 참고하세요.
  • 압축 경로는 데이터의 정확성을 보장하기 위해 체크섬을 수행해요. 전통적인 Cassandra 읽기 경로는 디스크 데이터의 정확성을 보장할 방법이 없지만, 압축 테이블은 사용자가 crc_check_chance(0.0~1.0의 float)를 설정해 읽기 시 청크를 확률적으로 검증하고 디스크 비트가 손상되지 않았는지 확인하게 할 수 있어요.

Advanced Use (고급 사용)

고급 사용자는 org.apache.cassandra.io.compress.ICompressor 인터페이스를 구현해 자신만의 압축 클래스를 제공할 수 있어요.

더 알아보기 (Learn more)