왜 지금 봐야 하나
Apache Cassandra에서 "repair"는 선택이 아니라 의무다. 노드 간 데이터 불일치를 방치하면 읽기 일관성이 깨지고, 결국 데이터 손실로 이어질 수 있다. 문제는 repair 운영이 쉽지 않다는 점이다.
전통적인 nodetool repair는 수동으로 스케줄링해야 하고, 중단됐다 재시작하면 어디까지 됐는지 알기 어려우며, 대규모 클러스터에서는 수일씩 걸리기도 한다. 이 때문에 많은 팀이 Reaper(Spotify가 개발, Netflix Priam 등) 같은 외부 수리 도구를 별도로 운영해 왔다.
2026년 4월, Cassandra 5.0.8이 배포되면서 상황이 달라졌다. Cassandra 6.0에서 도입된 CEP-37 Auto Repair가 5.0.8에 백포트됐다. 이 기능의 핵심은 하나다.
수리 스케줄러가 Cassandra 내부에 내장됐다. 외부 도구 없이, JVM 플래그 하나와 설정 파일 몇 줄로 클러스터 전체의 자동 수리가 시작된다.
Auto Repair와 기존 방식 비교
| 항목 | 기존 (외부 도구) | CEP-37 Auto Repair |
|---|---|---|
| 스케줄러 위치 | 외부 (Reaper, 사용자 스크립트 등) | Cassandra 내부 |
| 상태 저장소 | 외부 DB 또는 별도 관리 | system_distributed.auto_repair_history |
| 실패 후 재시작 | 어디까지 됐는지 불명확 | 테이블에서 진행 상황 복원 |
| 토큰 범위 분할 | 도구별로 다름 | 내장 알고리즘 (두 가지 선택) |
| 테이블별 우선순위 | 도구별로 다름 | 지원 (table-level 설정) |
| 수리 유형 | Full 위주 | Full, Incremental, Preview |
| 제어 방법 | 외부 UI / CLI | JMX + cassandra.yaml |
| 별도 의존성 | 있음 (외부 서비스 유지·운영 필요) | 없음 |
어떻게 켜는가
1단계: JVM 플래그
Auto Repair는 기본 비활성화 상태다. 첫 번째 단계는 JVM 속성을 활성화하는 것이다.
# jvm11-server.options 또는 jvm-server.options에 추가
-Dcassandra.autorepair.enable=true이 플래그를 설정하고 노드를 재시작하면, Cassandra가 수리 상태 추적을 위한 스키마 요소를 자동으로 생성한다.
system_schema.tables에auto_repair컬럼 추가system_schema.views에auto_repair컬럼 추가system_distributed.auto_repair_history테이블 생성system_distributed.auto_repair_priority테이블 생성
2단계: cassandra.yaml 설정
JVM 플래그만으로는 수리가 시작되지 않는다. cassandra.yaml의 auto_repair 섹션에서 수리 유형별로 활성화해야 한다.
auto_repair:
full_repair:
enabled: true
# 동일 테이블의 수리 최소 간격 (기본: 10일)
min_repair_interval: 10d
# 토큰 범위 분할 방식
token_range_splitter: RepairTokenRangeSplitter
# 한 번 수리할 때 처리할 최대 데이터 크기 (bytes)
bytes_per_assignment: 1073741824 # 1 GiB
incremental_repair:
enabled: false
preview_repair:
enabled: false3단계: JMX로 동적 제어
재시작 없이 Auto Repair를 껐다 켤 수 있다. JMX 또는 nodetool 확장 명령을 통해 런타임에 제어한다.
# nodetool를 통한 Auto Repair 상태 확인 (CEP-37 지원 명령)
nodetool autorepair status
# 특정 수리 유형 비활성화
nodetool autorepair disable --type full
# 다시 활성화
nodetool autorepair enable --type full내부 동작: 어떻게 클러스터 전체를 수리하는가
스케줄러 선택 알고리즘
스케줄러는 auto_repair_history 테이블을 참조해 어떤 노드와 토큰 범위를 먼저 수리할지 결정한다. 핵심 기준은 마지막 수리 시각이다. min_repair_interval이 지난 테이블과 범위부터 우선 처리하며, 우선순위가 높게 설정된 테이블은 간격을 무시하고 먼저 처리할 수 있다.
클러스터 재시작 후에도 이 테이블에서 진행 상황을 복원하기 때문에, 중단됐다가 다시 시작한 수리가 처음부터 다시 시작되는 문제가 없다.
토큰 범위 분할 알고리즘 선택
RepairTokenRangeSplitter (기본 권장)
full_repair:
token_range_splitter: RepairTokenRangeSplitter
bytes_per_assignment: 1073741824 # 1 GiBSSTable 인덱스 데이터를 사용해 각 토큰 범위의 압축 데이터 크기를 추정한다. 지정한 bytes_per_assignment 한도까지 토큰 범위를 묶어 하나의 수리 세션으로 만든다.
- 장점: 수리 세션당 처리량이 일정해 I/O 부하를 예측할 수 있다.
- 단점: SSTable 인덱스 통계가 부정확하면 실제 크기가 달라질 수 있다.
- 적합한 경우: 대부분의 운영 환경. Cassandra가 공식 기본값으로 지정.
FixedSplitTokenRangeSplitter
full_repair:
token_range_splitter: FixedSplitTokenRangeSplitter
num_splits: 100 # 전체 토큰 링을 100등분토큰 링 전체를 N개로 균등 분할한다. 데이터 크기와 무관하게 항상 같은 수의 세션이 생성된다.
- 장점: 세션 수가 고정되어 예측 가능.
- 단점: 핫 파티션이 있으면 일부 세션이 불균형하게 클 수 있다.
- 적합한 경우: 데이터 분포가 비교적 균일한 클러스터.
Incremental Repair와 Full Repair
Auto Repair는 세 가지 수리 유형을 지원한다.
| 수리 유형 | 방식 | 언제 쓰나 |
|---|---|---|
| Full Repair | 토큰 범위 전체를 Merkle Tree로 비교 후 동기화 | 첫 활성화, 장기 미수리 이후, 신뢰도 필요 시 |
| Incremental Repair | 마지막 수리 이후 변경된 SSTable만 처리 | Full Repair 이후 주기적 운영 수리 |
| Preview | 실제 동기화 없이 불일치 정도만 측정 | 수리 필요성 진단, 부하 없이 상태 확인 |
운영 권장 패턴:
- 클러스터 구성 후 Full Repair를 한 번 완료한다.
- 이후 Incremental Repair를 주기적으로 활성화한다.
- 정기적(분기 등)으로 Full Repair를 다시 실행해 누적 불일치를 청소한다.
운영 체크리스트
도입 전 판단
- 현재 외부 repair 도구(Reaper 등)를 운영 중인가?
- Cassandra 5.0.8 이상으로 업그레이드됐는가?
min_repair_interval을 데이터 특성에 맞게 계획했는가?
초기 활성화 절차
- 스테이징 클러스터에서 먼저 테스트한다.
jvm-server.options에-Dcassandra.autorepair.enable=true추가.cassandra.yaml에auto_repair.full_repair.enabled: true설정.- 한 노드씩 순차 재시작(rolling restart).
system_distributed.auto_repair_history에서 수리 기록이 쌓이는지 확인.nodetool autorepair status로 상태 주기적 확인.
모니터링
-- 최근 수리 이력 확인
SELECT * FROM system_distributed.auto_repair_history
WHERE repair_type = 'full'
LIMIT 100;
-- 우선순위 설정 확인
SELECT * FROM system_distributed.auto_repair_priority;Cassandra JMX 메트릭에서 Auto Repair 관련 지표가 노출된다. 기존 Prometheus + Grafana 스택과 연동해 수리 완료율, 대기 중인 세션 수, 실패 횟수를 모니터링하도록 구성한다.
외부 도구와의 공존
CEP-37 Auto Repair와 Reaper 같은 외부 도구를 동시에 실행하면 수리가 중첩될 수 있다. 초기에는 둘을 병행하되 CEP-37의 동작을 충분히 확인한 후 외부 도구를 단계적으로 비활성화하는 것이 안전하다.
5.0.8의 다른 변화
CEP-37 외에 5.0.8에 포함된 주요 변경:
- TLS 1.3 자동 협상:
cassandra-stress에서 TLS 1.3을 명시하지 않아도 서버와 협상해 자동으로 사용. - SnapshotLoader 경화(hardening): 스냅샷 복원 과정에서 간헐적으로 발생하던 문제 수정.
- 데이터 부활 시작 체크: 노드 시작 시 데이터 부활(data resurrection) 가능성을 감지하는 추가 검사 포함.
한 줄 결론
Cassandra 5.0.8의 CEP-37 Auto Repair는 수리 스케줄러를 클러스터 내부로 가져와 외부 도구 의존성을 제거하되, 첫 활성화는 JVM 플래그부터 순서대로 밟고 Full Repair 한 번 완료한 뒤 Incremental로 전환하는 순서가 안전하다.
References
- Apache Cassandra Auto Repair 공식 문서: https://cassandra.apache.org/doc/latest/cassandra/managing/operating/auto_repair.html
- CEP-37 제안서 (Confluence): https://cwiki.apache.org/confluence/display/CASSANDRA/CEP-37:+Apache+Cassandra+Unified+Repair+Solution
- CASSANDRA-19918 JIRA (자동화 수리 구현): https://issues.apache.org/jira/browse/CASSANDRA-19918
- Cassandra 2025 연간 보고 (AxonOps, 2026): https://axonops.com/blog/cassandra-in-2025-a-year-in-review/
- CASSANDRA-20421 (RepairTokenRangeSplitter 문서 개선, 보수적 기본값): https://issues.apache.org/jira/browse/CASSANDRA-20421
- Apache Cassandra 릴리스 노트: https://cassandra.apache.org/doc/latest/cassandra/new/index.html