47. 콤팩션 (Compaction)과 툼스톤 (Tombstone)
⚠️ 이 문서는 LSM 트리(Log-Structured Merge-Tree) 기반의 빅데이터 저장소(Cassandra, RocksDB 등)가 데이터를 지우거나 수정할 때 덮어쓰지 않고 '새로운 로그'만 남기는 구조적 특성 때문에 필연적으로 발생하는 데이터 파편화를 청소하고 최적화하는 백그라운드 정리 메커니즘을 다룹니다.
핵심 인사이트 (3줄 요약)
- 본질: 불변(Immutable)의 특성을 가진 SS테이블(디스크 파일)이 계속 쌓일 때, "이 데이터는 지워졌음"이라는 묘비(Tombstone) 마커를 남겨 처리하고, 나중에 여러 파일을 하나로 합치면서(Compaction) 묘비가 붙은 낡은 데이터를 영구 삭제하는 과정이다.
- 가치: 이 작업이 없다면 삭제/수정된 과거 쓰레기 데이터들이 디스크를 무한정 차지하게 되며, 읽기(Read) 요청 시 수만 개의 파일을 다 뒤져야 하므로 시스템 성능이 걷잡을 수 없이 붕괴된다.
- 기술 체계: 쓰기 증폭(Write Amplification)과 디스크 I/O를 최소화하기 위해 Size-Tiered 방식이나 Leveled 방식의 콤팩션 전략을 시스템의 워크로드(Read-heavy vs Write-heavy)에 맞춰 튜닝해야 한다.
Ⅰ. 툼스톤 (Tombstone): 삭제를 의미하는 비석
LSM 구조에서는 "데이터를 디스크에서 직접 지우는 행위(Delete)" 자체가 불가능하다.
- 불변성(Immutability)의 저주:
- 디스크에 이미 기록된 SS테이블 파일은 읽기 전용이다.
- 유저가 "홍길동의 데이터를 지워줘"라고 명령하면, RDBMS처럼 디스크 블록을 찾아 지우는 것이 아니라, 메모리(MemTable)에 새로
[홍길동: 데이터 없음 (Tombstone)]이라는 새 기록을 하나 더 추가한다.
- 읽기 시의 마스킹 효과:
- 나중에 누군가 '홍길동'을 조회하면, 시스템은 가장 최신 기록부터 읽는다.
- 최신 기록에 툼스톤(묘비)이 박혀있으면 "아, 이 사람은 과거 데이터가 디스크에 남아있더라도 최종적으로 사망(삭제)했구나"라고 판단하고 "데이터 없음"을 반환한다.
📢 섹션 요약 비유: 서류에 오타가 났을 때 화이트로 지우고 덮어쓰는(RDBMS) 대신, 그 위에 빨간색 X자 스티커(Tombstone)를 한 장 덧붙여서 "이건 이제 무효야"라고 표시해 두는 초고속 서류 작성법입니다.
Ⅱ. 콤팩션 (Compaction): 파편화된 파일의 대청소
시간이 지나면 묘비(Tombstone)와 수정된 과거 버전의 데이터들이 산더미처럼 쌓인다.
- 읽기 패널티의 증가:
- [버전1: 홍길동 나이 20] 파일, [버전2: 홍길동 나이 21] 파일, [버전3: 툼스톤] 파일이 디스크에 파편화되어 있으면 조회할 때 너무 많은 파일을 뒤져야 한다.
- Merge Sort 기반의 콤팩션:
- 백그라운드 프로세스가 주기적으로 디스크의 오래된 SS테이블 파일 여러 개를 메모리로 읽어 들인다.
- 최신 버전인 [툼스톤]만 살려두고, 낡은 과거의 [버전1], [버전2] 데이터는 과감히 버린다.
- 살아남은 유효한 데이터들만 모아서 하나의 거대한 새 SS테이블 파일로 뭉쳐서(병합) 디스크에 다시 쓴 뒤, 옛날 자잘한 파일들은 한 번에 삭제(unlink)한다.
- 툼스톤의 소멸 (GC Grace Seconds):
- 툼스톤 마커 자체도 영원히 보관할 필요는 없다. 분산 환경의 모든 노드가 "이 데이터가 지워졌다"는 사실을 동기화할 수 있는 충분한 유예 시간(예: 카산드라 기준 10일)이 지나면, 다음번 콤팩션 때 툼스톤 마커 자체도 디스크에서 영구 소멸된다.
📢 섹션 요약 비유: 매일 수십 장씩 쌓이는 쪽지(SSTable)들을 모아두었다가, 주말 밤에 사장이 혼자 남아 쪽지를 훑어보며 "취소된 주문(툼스톤)"이나 "중복된 내용"은 찢어버리고, 진짜 유효한 알짜 정보만 두꺼운 장부 한 권(새 SSTable)에 깔끔하게 옮겨 적는 대청소입니다.
Ⅲ. 콤팩션 전략 (Strategy)의 튜닝
대청소(Compaction) 과정은 엄청난 디스크 I/O와 CPU를 소모하므로 전략이 필요하다.
- Size-Tiered Compaction (STCS):
- 크기가 비슷한 파일이 여러 개(예: 4개) 모이면 하나의 큰 파일로 뭉치는 방식이다.
- 쓰기 속도가 매우 빠르지만, 파일을 뭉칠 때 임시로 디스크 여유 공간이 최대 50%까지 필요하며, 읽기 성능이 다소 떨어져 Write-Heavy 작업에 적합하다.
- Leveled Compaction (LCS):
- 데이터를 크기별 레벨(Level 0, 1, 2...)로 나누고, 한 레벨이 꽉 차면 다음 레벨의 파일들과 병합하여 밀어내는 방식이다. (RocksDB 기본 방식)
- 디스크 공간 소모가 적고 읽기 속도가 아주 빠르며 예측 가능하지만, 콤팩션 I/O가 잦아 Read-Heavy 작업에 유리하다.
📢 섹션 요약 비유: 빨래(파일)를 모아서 합칠 때, 바구니에 일정량 찰 때마다 한 번에 다 때려 넣고 돌릴 것인지(Size-Tiered), 아니면 서랍장을 층별로 나눠서 꽉 찰 때마다 바로 아랫칸으로 조금씩 밀어내며 정리할 것인지(Leveled)의 전략적 차이입니다.