CAP 정리의 AP 시스템 비교 분석
결론
CAP 정리에서 가용성(Availability)과 분할 내성(Partition tolerance)을 우선하는 주요 AP 시스템은 다음과 같습니다:
- Apache Cassandra - 오픈소스, 가장 널리 사용되는 AP 데이터베이스 ScyllaDB Glossary (opens in a new tab)
- Amazon DynamoDB - AWS 관리형 서비스, 튜닝 가능한 일관성 CAP Theorem Database Selection Guide (opens in a new tab)
- Riak - Dynamo 스타일 구현, 유연한 스토리지 백엔드 Riak vs Cassandra (opens in a new tab)
- ScyllaDB - Cassandra 호환 C++ 구현, 뛰어난 성능 ScyllaDB vs Cassandra (opens in a new tab)
ScyllaDB 문서에서 "Cassandra is an AP database—it delivers availability and partition tolerance but can't deliver consistency all the time"라고 명시되어 있습니다.
CAP 정리 가이드에서 "DynamoDB and Riak furnish users with control over certain consistency parameters, catering to varying application needs"라고 설명합니다.
1. Apache Cassandra
데이터 저장 구조
Cassandra는 LSM Tree (Log-Structured Merge Tree) 기반 아키텍처를 사용합니다 Apache Cassandra Storage Engine (opens in a new tab).
구성 요소:
- Memtable (메모리)
- Red-Black Tree와 같은 자기 균형 이진 검색 트리로 구현 Baeldung - Cassandra Storage Engine (opens in a new tab)
- 쓰기 작업을 정렬된 순서로 메모리에 저장
- 설정된 임계값에 도달하면 디스크로 플러시
Baeldung 문서에서 "MemTable is a memory-resident data structure such as a Red-black tree with self-balancing binary search tree properties"라고 설명합니다.
- SSTable (Sorted String Table, 디스크)
- Memtable이 플러시되어 생성된 불변(immutable) 파일 ScyllaDB SSTable Glossary (opens in a new tab)
- Partition은 토큰 순서로 정렬 (기본 파티셔너인 Murmur3Partition 사용 시 파티션 키의 해시 순서)
- Partition 내에서는 Clustering Key 순서로 행이 저장됨
Apache Cassandra 문서에서 "Within the Data.db file, rows are organized by partition. These partitions are sorted in token order (i.e. by a hash of the partition key when the default partitioner, Murmur3Partition, is used)"라고 명시되어 있습니다.
- Compaction (압축)
- 여러 SSTable을 병합하여 하나로 만드는 백그라운드 프로세스 Apache Cassandra Compaction (opens in a new tab)
- 중복 제거, 만료된 Tombstone 삭제, 인덱스 재구축
- 주요 전략:
- STCS (Size-Tiered Compaction Strategy): 쓰기 처리량에 최적화
- LCS (Leveled Compaction Strategy): 읽기 처리량에 최적화
Apache Cassandra 문서에서 "Compaction is a necessary background activity required by the 'merge' phase of Log Structured Merge trees"라고 설명합니다.
인덱스 메커니즘
Cassandra는 세 가지 인덱스 유형을 제공합니다:
-
Secondary Index (2i) - 기본 보조 인덱스 Baeldung - Secondary Indexes (opens in a new tab)
-
SASI (SSTable Attached Secondary Index) - SSTable에 붙은 인덱스
-
SAI (Storage-Attached Indexing) - Cassandra 5.0의 새로운 인덱스 구현 Apache Cassandra SAI Concepts (opens in a new tab)
- Secondary Index 대비 40% 더 나은 처리량, 230% 더 나은 지연시간 제공
- Memtable과 SSTable이 쓰여질 때 인덱싱하여 읽기 시점에 차이를 해결
- SASI보다 적은 디스크 공간 사용 (모든 용어에 대해 ngram을 생성하지 않음)
Instaclustr 블로그에서 "Users should expect to achieve about 40% better throughput when using SAI compared to Secondary Indexes and about 230% better latency"라고 명시되어 있습니다.
Apache Cassandra 문서에서 "SAI is deeply integrated with the storage engine, indexing Memtables and Sorted String Tables (SSTables) as they are written"라고 설명합니다.
분산 방식
Partitioning:
- Consistent Hashing 사용 Apache Cassandra Dynamo (opens in a new tab)
- 토큰 범위: -2^63 ~ +2^63-1
- 파티션 키를 해싱하여 토큰 링에 배치
DataStax 문서에서 "Cassandra's ring relies on consistent hashing – a technique that maps both nodes and data to positions on a token ring (ranging from -2^63 to +2^63-1)"라고 명시되어 있습니다.
Virtual Nodes (Vnodes):
- Cassandra 1.2 이후 도입 DataStax - Virtual Nodes (opens in a new tab)
- 각 노드가 여러 개의 작은 토큰 범위를 소유
- 권장 설정: 8개의 vnodes
- 노드 추가/제거 시 여러 노드에 분산되어 데이터 이동
DataStax 문서에서 "DataStax recommends using 8 vnodes (tokens). Using 8 vnodes distributes the workload between systems with a ~10% variance"라고 권장합니다.
Replication:
- Replication Factor (RF)로 복제본 수 지정 Baeldung - Replication Strategies (opens in a new tab)
- 복제 전략:
- SimpleStrategy: 단일 데이터센터용
- NetworkTopologyStrategy: 다중 데이터센터용
- 데이터는 토큰 위치에서 시계방향으로 N개의 연속된 노드에 복제
Cassandra 문서에서 "Data is replicated to N consecutive nodes clockwise from its token position, creating what's called a 'replication chain'"이라고 설명합니다.
장점
- 높은 쓰기 성능: LSM Tree 구조로 순차 쓰기에 최적화
- 선형적 확장성: 노드 추가로 성능이 비례하여 증가
- 고가용성: 단일 장애 지점 없음
- 유연한 일관성 튜닝: Read/Write 일관성 레벨 조정 가능
- 성숙한 에코시스템: 널리 사용되고 검증됨
단점
- JVM 기반: Garbage Collection으로 인한 지연 변동 가능성
- 읽기 성능: 여러 SSTable을 읽어야 할 수 있음
- 운영 복잡성: 튜닝과 유지보수에 전문 지식 필요
- 최종 일관성: 기본적으로 즉각적인 일관성을 보장하지 않음
ScyllaDB 문서에서 "Cassandra provides eventual consistency by allowing clients to write to any nodes at any time and reconciling inconsistencies as quickly as possible"라고 명시되어 있습니다.
주요 사용 사례
- 시계열 데이터 (센서 데이터, IoT)
- 사용자 활동 로그
- 메시징 시스템
- 실시간 분석
- Netflix, Apple 등에서 사용
2. Amazon DynamoDB
데이터 저장 구조
DynamoDB는 Partition 기반 저장 구조를 사용합니다 DynamoDB Indexes Explained (opens in a new tab).
- 데이터는 물리적 파티션에 저장
- Partition Key가 아이템이 저장될 파티션 결정
- 동일한 Partition Key를 가진 아이템들은 함께 그룹화되어 빠른 쿼리 가능
Dynomate 블로그에서 "DynamoDB uses partitions as the physical storage where items are stored, with the partition key deciding which partition an item goes to"라고 설명합니다.
인덱스 메커니즘
DynamoDB는 두 가지 보조 인덱스를 제공합니다:
1. Local Secondary Index (LSI) AWS DynamoDB Documentation (opens in a new tab)
- 기본 테이블과 동일한 Partition Key, 다른 Sort Key 사용
- 테이블 생성 시에만 정의 가능 (나중에 추가 불가)
- Partition당 10GB 크기 제한
- 기본 테이블과 처리량 설정 공유
- 강한 일관성 읽기 지원 가능
AWS 문서에서 "Local Secondary Indexes (LSI) use the same partition key as the main table but a different sort key"라고 명시되어 있습니다.
Dynomate 블로그에서 "LSIs must be declared when the table is created; they cannot be added later"라고 설명합니다.
2. Global Secondary Index (GSI) AWS DynamoDB GSI (opens in a new tab)
- 기본 테이블과 다른 Partition Key와 Sort Key 사용 가능
- 전체 테이블의 모든 파티션에 걸쳐 쿼리 가능
- 언제든지 추가/삭제 가능
- 크기 제한 없음
- 독립적인 처리량 설정 (기본 테이블과 분리)
- 비동기 업데이트 (잠깐 동안 stale할 수 있음)
AWS 문서에서 "A GSI has a partition key and a sort key that can be different from those on the base table, and queries on the index can span all of the data in the base table, across all partitions"라고 설명합니다.
제한사항:
- 테이블당 GSI 최대 20개, LSI 최대 5개 KodeKloud Notes (opens in a new tab)
분산 방식
- Partition Key 해싱으로 데이터 분산
- AWS가 자동으로 파티션 관리
- 사용자는 파티션 관리에 대해 신경 쓸 필요 없음 (완전 관리형)
장점
- 완전 관리형: 인프라 관리 불필요
- 자동 확장: 트래픽에 따라 자동으로 확장/축소
- 예측 가능한 성능: 프로비저닝된 처리량 또는 온디맨드 모드
- 강력한 보안: AWS IAM, 암호화 통합
- 유연한 인덱싱: GSI로 다양한 쿼리 패턴 지원
단점
- 비용: 처리량과 스토리지에 따라 비용이 높을 수 있음
- 벤더 종속성: AWS에 종속
- 쿼리 제한: 복잡한 쿼리나 조인 불가
- GSI 비동기 업데이트: 일시적인 불일치 발생 가능
Dynomate 블로그에서 "GSI updates are propagated asynchronously, so the index can be briefly stale"이라고 명시되어 있습니다.
주요 사용 사례
- 서버리스 애플리케이션
- 모바일/웹 애플리케이션 백엔드
- 게임 리더보드
- 세션 관리
- Amazon, Lyft 등에서 사용
3. Riak
데이터 저장 구조
Riak는 플러그인 가능한 스토리지 백엔드 아키텍처를 제공합니다 Riak Choosing Backend (opens in a new tab).
1. Bitcask (기본 백엔드) Riak Bitcask (opens in a new tab)
- Riak에서 자체 개발한 스토리지 엔진
- 메모리 내 해시 테이블 + 디스크 저장소
- 모든 키를 메모리에 유지하여 디스크 위치를 직접 가리킴
- 단 한 번의 디스크 시크로 데이터 읽기 가능
- 매우 빠른 읽기/쓰기 성능과 높은 처리량
Riak 문서에서 "Bitcask uses an in-memory hash-table of all keys you write to Riak, which points directly to the on-disk location of the value"라고 설명합니다.
"The direct lookup from memory means Bitcask never uses more than one disk seek to read data"라고 명시되어 있습니다.
제한사항:
- 시스템이 전체 키 공간을 메모리에 담을 수 있어야 함
2. LevelDB Riak LevelDB (opens in a new tab)
- Google에서 개발한 오픈소스 키-값 저장소 (Riak에서 튜닝)
- Bitcask의 메모리 제약이 없음
- 매우 많은 수의 키를 가진 환경에 이상적
- 영구적 정렬 맵 (Bitcask는 영구적 해시 테이블)
- 순서 있는 반복 지원
Riak 문서에서 "LevelDB doesn't have Bitcask's memory constraints around keyspace size, and thus is ideal for deployments with a very large number of keys"라고 설명합니다.
분산 방식
Consistent Hashing:
- Amazon Dynamo와 유사한 일관된 해싱 사용 Riak Dynamo (opens in a new tab)
- SHA1 해시 알고리즘 사용
- 데이터를 링 주위에 파티션하고 복제
Riak 문서에서 "Like Dynamo, Riak KV employs consistent hashing to partition and replicate data around the ring, and for the consistent hashing that takes place in riak_core, Basho chose the SHA1 hash"라고 명시되어 있습니다.
자동 재분산:
- 노드 추가 시 데이터가 자동으로 재분산
- 핫스팟 방지 및 수동 리샤딩 불필요
Riak 문서에서 "Riak's operational profile and use of consistent hashing means data is automatically redistributed as you add machines"라고 설명합니다.
장점
- 유연한 스토리지 옵션: 워크로드에 맞게 백엔드 선택
- 매우 빠른 읽기/쓰기: Bitcask 사용 시
- 확장 가능한 키 수: LevelDB 사용 시
- 높은 가용성: Dynamo 스타일 복제
- 운영 단순성: 자동 재분산
단점
- 커뮤니티 규모: Cassandra나 DynamoDB보다 작은 생태계
- 메모리 요구사항: Bitcask는 전체 키를 메모리에 유지
- 쿼리 기능 제한: 복잡한 쿼리 지원 부족
주요 사용 사례
- 세션 저장소
- 사용자 프로필 데이터
- 로그 데이터
- 콘텐츠 관리 시스템
- Airbnb에서 사용
4. ScyllaDB
데이터 저장 구조
ScyllaDB는 Cassandra와 동일한 LSM Tree 아키텍처를 사용하지만 구현이 크게 다릅니다 ScyllaDB vs Cassandra (opens in a new tab).
핵심 차이점:
- 프로그래밍 언어: C++ 기반 (Cassandra는 Java)
- Seastar 프레임워크 활용
- Garbage Collection 없음 - 지연 변동성 제거
ScyllaDB 문서에서 "ScyllaDB is written in C++ and leverages the high-performance Seastar framework, while Cassandra is in Java"라고 설명합니다.
"The use of C++ allows ScyllaDB to perform highly asynchronous operations and avoid Garbage Collection (GC) stalls"이라고 명시되어 있습니다.
- Shard-per-Core 아키텍처 RisingWave Blog (opens in a new tab)
- 각 CPU 코어가 독립적인 샤드로 작동
- CPU 코어, RAM, 영구 저장소, 네트워크 I/O를 공유하지 않는 단위로 분할
- 진정한 병렬 처리 가능
- 100코어든 1000코어든 서버 크기에 관계없이 완전히 활용 가능
ScyllaDB 문서에서 "ScyllaDB's innovative shard-per-core design divides a server's resources into shared-nothing units of CPU-core, RAM, persistent storage and network I/O"라고 설명합니다.
- 성능
- Cassandra 대비 2-5배 더 나은 처리량
- 일관되게 더 낮은 지연시간
- 훨씬 적은 노드 수로 동일한 작업 수행
- 최대 100% CPU 활용률 달성
ScyllaDB 문서에서 "ScyllaDB to deliver 2-5x better throughput with consistently lower latencies while using far fewer nodes than Cassandra"라고 명시되어 있습니다.
- 호환성
- Cassandra와 API 호환
- 동일한 CQL 인터페이스 및 쿼리
- 동일한 드라이버
- 동일한 SSTable 디스크 포맷
ScyllaDB 문서에서 "ScyllaDB is API-compatible with Apache Cassandra; it provides the same Cassandra Query Language (CQL) interface and queries, the same drivers, even the same on-disk SSTable format"라고 설명합니다.
Compaction 전략
Incremental Compaction Strategy (ICS) ScyllaDB Blog (opens in a new tab)
- 스케일 아웃 전에 스토리지의 최대 90% 활용 가능
- Hybrid compaction 전략 지원
분산 방식
Cassandra와 동일:
- Consistent Hashing
- Virtual Nodes
- 동일한 복제 전략
장점
- 뛰어난 성능: GC 없음, shard-per-core 아키텍처
- 비용 효율적: 더 적은 노드로 동일한 처리량
- Cassandra 호환: 기존 Cassandra 애플리케이션 마이그레이션 용이
- 높은 하드웨어 활용률: 현대적인 멀티코어 서버 완전 활용
- 예측 가능한 지연시간: GC pause 없음
단점
- 상대적으로 새로운 기술: Cassandra보다 짧은 운영 이력
- 커뮤니티 규모: Cassandra보다 작은 생태계
- 학습 곡선: 최적의 성능을 위한 튜닝 필요
주요 사용 사례
- Cassandra의 성능 문제가 있는 경우
- 고성능이 중요한 시계열 데이터
- 실시간 분석
- IoT 데이터 처리
- Discord, Comcast 등에서 사용
비교 요약
저장 구조 비교
| 시스템 | 저장 엔진 | 메모리 구조 | 디스크 구조 | Compaction |
|---|---|---|---|---|
| Cassandra | LSM Tree | Memtable (Red-Black Tree) | SSTable | STCS, LCS |
| DynamoDB | Proprietary | AWS 관리 | AWS 관리 | 자동 |
| Riak | Pluggable | Bitcask: 해시 테이블<br>LevelDB: LSM | Bitcask: 로그 구조<br>LevelDB: SSTable | 자동 |
| ScyllaDB | LSM Tree (C++) | Memtable (최적화된 구조) | SSTable | STCS, LCS, ICS |
인덱스 비교
| 시스템 | 인덱스 유형 | 특징 |
|---|---|---|
| Cassandra | Secondary Index, SASI, SAI | SAI: 40% 더 나은 처리량, 230% 더 나은 지연시간 |
| DynamoDB | LSI, GSI | LSI: 생성 시 정의, 10GB 제한<br>GSI: 언제든지 추가, 비동기 업데이트 |
| Riak | Secondary Index (2i) | 제한적인 인덱싱 기능 |
| ScyllaDB | Cassandra와 동일 | SAI 지원 예정 |
분산 방식 비교
| 시스템 | Partitioning | Replication | 특징 |
|---|---|---|---|
| Cassandra | Consistent Hashing | RF 기반, 시계방향 복제 | Vnodes (권장 8개) |
| DynamoDB | Partition Key 해싱 | AWS 자동 관리 | 사용자 투명 |
| Riak | Consistent Hashing (SHA1) | Dynamo 스타일 | 자동 재분산 |
| ScyllaDB | Cassandra와 동일 | Cassandra와 동일 | Shard-per-core |
성능 비교
| 시스템 | 쓰기 성능 | 읽기 성능 | 지연시간 | 확장성 |
|---|---|---|---|---|
| Cassandra | 매우 높음 | 높음 | GC로 인한 변동 | 선형 확장 |
| DynamoDB | 높음 (프로비저닝 기준) | 높음 | 예측 가능 | 자동 확장 |
| Riak | 매우 높음 (Bitcask) | 매우 높음 (Bitcask) | 낮음 | 선형 확장 |
| ScyllaDB | 최고 (Cassandra 대비 2-5배) | 최고 | 가장 낮음 (GC 없음) | 선형 확장 |
사용 시나리오 비교
| 시나리오 | 추천 시스템 | 이유 |
|---|---|---|
| 높은 쓰기 처리량 | ScyllaDB, Cassandra | LSM Tree, 순차 쓰기 최적화 |
| 낮은 지연시간 | ScyllaDB, Riak (Bitcask) | GC 없음, 메모리 기반 조회 |
| 완전 관리형 필요 | DynamoDB | 인프라 관리 불필요 |
| AWS 환경 | DynamoDB | AWS 서비스 통합 |
| 오픈소스 선호 | Cassandra, Riak | 커뮤니티 지원, 벤더 종속성 없음 |
| Cassandra 마이그레이션 | ScyllaDB | API 호환, 성능 향상 |
| 매우 많은 키 | Riak (LevelDB), DynamoDB | 메모리 제약 없음 |
| 복잡한 쿼리 | 모두 제한적 | AP 시스템은 간단한 쿼리에 최적화 |
AP 시스템 일반적인 장단점
장점 IBM CAP Theorem (opens in a new tab):
- 높은 가용성: 네트워크 파티션 중에도 계속 작동
- 빠른 응답: 쓰기 작업이 모든 노드의 동기화를 기다리지 않음
- 수평 확장: 노드 추가로 성능 증가
- 분할 내성: 네트워크 장애 시에도 서비스 지속
IBM 문서에서 "Data availability and responsiveness are paramount, and the system continues to operate despite network partitions"라고 설명합니다.
단점 Analytics Vidhya - CAP Theorem (opens in a new tab):
- 최종 일관성: 즉각적인 일관성 보장 안 됨
- 읽기 시 오래된 데이터: 파티션 발생 시 stale 데이터 반환 가능
- 충돌 해결 필요: 서로 다른 노드가 다른 데이터 버전을 가질 수 있음
문서에서 "AP databases sacrifice some consistency; a read operation may return an outdated value if the database is partitioned at the time of the read"라고 명시되어 있습니다.
선택 가이드
Cassandra를 선택해야 할 때
- 오픈소스 솔루션이 필요한 경우
- 성숙하고 검증된 기술을 원하는 경우
- 대규모 쓰기 워크로드 (시계열, 로그, 이벤트)
- 멀티 데이터센터 복제 필요
- 활발한 커뮤니티 지원이 중요한 경우
DynamoDB를 선택해야 할 때
- 완전 관리형 서비스를 원하는 경우
- AWS 생태계 내에서 작업하는 경우
- 운영 오버헤드를 최소화하려는 경우
- 예측 가능한 성능이 필요한 경우
- 서버리스 아키텍처와 통합
Riak을 선택해야 할 때
- 매우 빠른 읽기/쓰기가 필요한 경우 (키 수가 적으면 Bitcask)
- 매우 많은 키를 저장해야 하는 경우 (LevelDB)
- 유연한 스토리지 백엔드 선택이 필요한 경우
- 운영 단순성이 중요한 경우
ScyllaDB를 선택해야 할 때
- 최고의 성능이 필요한 경우
- Cassandra의 성능 문제를 겪고 있는 경우
- 비용 효율성이 중요한 경우 (더 적은 노드로 동일한 처리량)
- 예측 가능한 낮은 지연시간이 필요한 경우
- 현대적인 멀티코어 하드웨어를 완전히 활용하고 싶은 경우
참고 자료
CAP Theorem & AP Systems
- CAP Theorem Database Selection Guide - Talent500 (opens in a new tab)
- CAP Theorem Explained - ScyllaDB (opens in a new tab)
- IBM CAP Theorem (opens in a new tab)
- Analytics Vidhya - CAP Theorem Guide (opens in a new tab)
- Riak vs Cassandra Comparison (opens in a new tab)
Apache Cassandra
- Apache Cassandra Storage Engine (opens in a new tab)
- Baeldung - Cassandra Storage Engine (opens in a new tab)
- ScyllaDB - SSTable Glossary (opens in a new tab)
- Apache Cassandra Compaction (opens in a new tab)
- Apache Cassandra Dynamo Architecture (opens in a new tab)
- DataStax - Virtual Nodes (opens in a new tab)
- Baeldung - Replication Strategies (opens in a new tab)
- Apache Cassandra SAI Concepts (opens in a new tab)
- Instaclustr - Storage Attached Indexing (opens in a new tab)
- Baeldung - Secondary Indexes (opens in a new tab)
Amazon DynamoDB
- AWS - Using Global Secondary Indexes (opens in a new tab)
- AWS - General Guidelines for Secondary Indexes (opens in a new tab)
- Dynomate - DynamoDB Indexes Explained (opens in a new tab)
- KodeKloud - DynamoDB Indexes GSI LSI (opens in a new tab)
Riak
- Riak - Choosing a Backend (opens in a new tab)
- Riak - Bitcask (opens in a new tab)
- Riak - LevelDB (opens in a new tab)
- Riak - Dynamo (opens in a new tab)