Apache Cassandra
1. 아파치 카산드라
아파치 카산드라(Apache Cassandra)는 대규모의 데이터를 효율적으로 처리하도록 설계된 오픈소스 분산형 NoSQL 데이터베이스이다.1 관계형 데이터베이스(RDBMS)가 직면한 성능과 확장성의 한계를 극복하기 위해 탄생했으며, 높은 확장성(Scalability), 고가용성(High Availability), 내결함성(Fault Tolerance), 그리고 조정 가능한 일관성(Tunable Consistency)을 핵심 특징으로 한다.1 이러한 특성 덕분에 카산드라는 구조적이거나 비구조적인 데이터를 막론하고 페타바이트(PB) 규모의 데이터셋을 처리해야 하는 미션 크리티컬 애플리케이션에 최적화된 솔루션으로 자리 잡았다.1
1.1 NoSQL 분산 데이터베이스로서의 카산드라 정의 및 핵심 특성
카산드라는 데이터를 전통적인 행과 열의 테이블 구조가 아닌, 와이드 컬럼 스토어(Wide Column Store) 모델로 저장한다.3 이는 고정된 스키마 없이 각 행이 동적으로 다른 수의 컬럼을 가질 수 있음을 의미하며, 애플리케이션의 변화에 유연하게 대응할 수 있는 기반을 제공한다.1
카산드라의 가장 두드러진 아키텍처적 특징은 중앙 제어 지점이 없는 완전한 분산 시스템이라는 점이다.3 모든 노드가 동등한 역할을 수행하는 ‘마스터 없는(Masterless)’ 또는 ‘P2P(Peer-to-Peer)’ 구조를 채택하여 단일 장애 지점(Single Point of Failure, SPOF)을 원천적으로 제거했다.1 데이터는 클러스터 내 여러 노드에 자동으로 복제되어 일부 노드에 장애가 발생하더라도 서비스 중단 없이 운영이 가능하다.3 또한, 클러스터에 노드를 추가하는 것만으로 읽기 및 쓰기 처리량이 선형적으로 증가하는 수평적 확장성(Horizontal Scalability)을 제공하여, 예측 불가능한 대규모 트래픽 증가에도 탄력적으로 대응할 수 있다.2
1.2 개발 역사와 설계 철학: Dynamo와 Bigtable의 융합
카산드라의 탄생은 2008년, 급격하게 성장하던 페이스북의 기술적 난제를 해결하기 위한 내부 프로젝트에서 시작되었다.1 당시 페이스북은 기존 RDBMS의 수직적 확장 방식으로는 늘어나는 데이터를 감당할 수 없는 한계에 직면했고, 이를 해결하기 위해 엔지니어 Avinash Lakshman과 Prashant Malik이 새로운 분산 데이터베이스 개발에 착수했다.1 흥미롭게도 Avinash Lakshman은 Amazon Dynamo의 설계자 중 한 명으로, 그의 경험은 카산드라의 핵심 설계 철학에 지대한 영향을 미쳤다.1
카산드라의 아키텍처는 당대 가장 성공적인 두 분산 시스템 모델인 Amazon Dynamo와 Google Bigtable의 장점을 실용적으로 융합한 결과물이다. 이는 특정 이론에 얽매이기보다, 실제 하이퍼스케일 환경의 문제를 해결하기 위한 최적의 엔지니어링적 선택이었다.1
- Amazon Dynamo의 영향: Dynamo로부터 ’상시 가용성(Always-On Availability)’을 위한 핵심 아키텍처를 계승했다. SPOF가 없는 P2P 아키텍처, 데이터 복제를 통한 고가용성, 분산 해시 테이블(DHT) 개념에 기반한 일관된 해싱(Consistent Hashing)을 통한 데이터 분산, 그리고 결과적 일관성(Eventual Consistency) 모델이 그것이다.1 이는 시스템의 일부에 장애가 발생하더라도 전체 서비스가 중단되지 않도록 하는 데 초점을 맞춘 설계이다.
- Google Bigtable의 영향: Bigtable로부터는 유연하고 효율적인 데이터 저장 구조를 채택했다. 고정된 스키마 없이 동적으로 열을 추가할 수 있는 열 기반 저장소(Columnar Storage) 모델은 빠르게 변화하는 애플리케이션 요구사항에 민첩하게 대응하고, 대규모 데이터셋을 효율적으로 저장 및 검색하는 데 유리하다.1
이처럼 카산드라는 Dynamo의 강력한 분산 및 복제 기술과 Bigtable의 유연한 데이터 모델을 결합하여, 확장성, 가용성, 성능이라는 세 마리 토끼를 모두 잡으려는 야심 찬 목표를 가지고 설계되었다. 2009년 아파치 소프트웨어 재단의 인큐베이터 프로젝트로 기증된 이후, 2010년에는 최상위 프로젝트(Top-Level Project, TLP)로 승격되며 전 세계적인 오픈소스 커뮤니티의 기여를 통해 빠르게 발전해왔다.1
2. 분산 아키텍처 심층 분석
카산드라의 아키텍처는 ’완전한 분산화’와 ’장애 감내’라는 철학을 구현하기 위한 유기적인 시스템이다. 마스터 없는 구조는 가십 프로토콜을 필수로 만들고, 가십 프로토콜은 스니치와 결합하여 단순한 멤버십 관리를 넘어 ’성능 인식 라우팅’이라는 고차원적인 기능을 수행한다. 이 구성 요소들은 각각 독립적으로 동작하는 것이 아니라, 중앙 제어 없이도 안정적이고 효율적으로 시스템을 운영하기 위한 연쇄적인 해법으로 긴밀하게 연결되어 있다.
2.1 마스터 없는 P2P 모델과 링(Ring) 구조의 원리
카산드라 아키텍처의 가장 근본적인 특징은 특정 노드가 전체 클러스터를 제어하는 마스터(Master) 역할을 하지 않는다는 점이다. 대신, 클러스터를 구성하는 모든 노드가 동등한 지위와 역할을 갖는 ‘마스터 없는(Masterless)’ 또는 ‘P2P(Peer-to-Peer)’ 모델을 채택했다.1
이러한 설계는 중앙 제어 지점의 부재를 의미하며, 이는 곧 시스템 전체를 마비시킬 수 있는 단일 장애 지점(SPOF)이 원천적으로 존재하지 않음을 보장한다.1 클라이언트의 읽기 또는 쓰기 요청은 클러스터 내 어떤 노드에든 전달될 수 있으며, 요청을 받은 노드는 해당 요청의 코디네이터(Coordinator) 역할을 수행하여 데이터를 담당하는 실제 노드들과 통신한다.2
클러스터에 속한 노드들은 물리적으로 분산되어 있지만, 논리적으로는 하나의 ‘링(Ring)’ 구조를 형성한다.7 이는 분산 해시 테이블(DHT) 구현체인 Chord 알고리즘과 유사한 개념으로, 데이터가 클러스터 전체에 어떻게 분산될지를 결정하는 기준이 된다.7 데이터는 각 행(row)을 식별하는 고유 키인 파티션 키(Partition Key)를 해시 함수에 통과시켜 얻은 숫자 값, 즉 ’토큰(Token)’을 기준으로 링 상의 특정 위치에 매핑된다. 각 노드는 이 링의 특정 토큰 범위를 담당하게 되며, 자신의 범위에 해당하는 토큰을 가진 데이터를 저장하고 관리할 책임을 진다.2 이 방식을 통해 데이터는 클러스터 전체에 자동으로 분산된다.
2.2 가십 프로토콜(Gossip Protocol)을 통한 멤버십 및 장애 감지
마스터 노드가 없는 P2P 환경에서는 “누가 클러스터의 멤버이며, 각 노드의 현재 상태는 어떠한가?“라는 정보를 모든 노드가 공유해야 한다. 카산드라는 이 문제를 해결하기 위해 ’가십 프로토콜(Gossip Protocol)’이라는 P2P 통신 메커니즘을 사용한다.8
’전염병 프로토콜(Epidemic Protocol)’이라고도 불리는 이 방식은, 각 노드가 주기적으로(보통 1초마다) 클러스터 내의 다른 임의의 노드 몇 개와 자신이 알고 있는 상태 정보를 교환하는 방식으로 동작한다.15 이 정보에는 노드의 가용성(UP/DOWN), 부하 상태, 스키마 버전 등 클러스터 운영에 필수적인 메타데이터가 포함된다.10 정보는 마치 소문이나 전염병처럼 노드에서 노드로 빠르게 전파되어, 결국 모든 노드가 짧은 시간 내에 클러스터 전체의 상태에 대한 거의 일관된 그림을 갖게 된다.15
가십 프로토콜은 단순한 멤버십 관리를 넘어 장애 감지에도 핵심적인 역할을 한다. 카산드라는 Phi Accrual Failure Detector라는 정교한 알고리즘을 사용하여 노드 간 가십 메시지의 도착 간격을 통계적으로 분석하고, 특정 노드가 다운되었을 확률을 계산한다.10 이를 통해 일시적인 네트워크 지연과 실제 노드 장애를 구분하여 불필요한 장애 조치를 방지하고 시스템의 안정성을 높인다.
또한, 교환되는 가십 메시지에는 버전 정보가 포함되어 있어, 노드들은 항상 가장 최신의 상태 정보만을 신뢰하게 된다. 이는 벡터 클록(Vector Clock)과 유사한 메커니즘을 통해 구현되며, 네트워크 분할과 같은 상황에서 발생할 수 있는 정보의 충돌을 방지한다.13
2.2.1 시드 노드 (Seed Nodes)
완전한 P2P 환경에서 새로운 노드가 클러스터에 참여하려면, 기존 멤버 중 누구에게라도 말을 걸어 클러스터 정보를 얻어야 한다. ’시드 노드(Seed Node)’는 바로 이 진입점 역할을 하는 노드들이다.10 시드 노드는 클러스터를 부트스트랩하고, 새로운 노드가 클러스터의 멤버십 정보를 얻기 위해 가장 먼저 접촉하는 공식적인 연락 지점이다. 또한, 모든 노드가 시드 노드와 주기적으로 가십 통신을 시도함으로써, 일시적인 네트워크 문제로 클러스터가 여러 개로 분리되는 ‘분할뇌(Split-brain)’ 현상을 방지하는 데 도움을 준다.10 시드 노드는 특별한 역할을 하지만 마스터 노드는 아니며, 일단 클러스터 상태 정보가 전파되고 나면 다른 노드와 동등한 지위를 갖는다.
2.3 스니치(Snitch)를 이용한 네트워크 토폴로지 인식 및 요청 라우팅 최적화
카산드라 클러스터는 종종 여러 데이터센터와 랙(Rack)에 걸쳐 지리적으로 분산되어 운영된다. 고가용성을 위해서는 데이터의 복제본을 서로 다른 물리적 위치(예: 다른 랙, 다른 데이터센터)에 저장하여 랙 전원이나 네트워크 스위치 고장과 같은 공통 장애 지점의 영향을 피해야 한다.18 또한, 요청을 처리할 때 네트워크적으로 가장 가까운 노드에서 데이터를 읽어오는 것이 지연 시간을 줄이는 데 유리하다.
’스니치(Snitch)’는 이러한 요구사항을 충족시키기 위해 클러스터의 네트워크 토폴로지 정보를 카산드라에 제공하는 핵심 구성 요소이다.19 스니치는 각 노드의 IP 주소를 기반으로 해당 노드가 어떤 데이터센터와 랙에 속하는지를 판단하고, 이 정보를 다른 노드들과 공유한다.19 복제 전략(NetworkTopologyStrategy)은 스니치가 제공하는 토폴로지 정보를 활용하여 데이터 복제본을 의도적으로 다른 랙과 데이터센터에 분산 배치한다.13
2.3.1 SimpleSnitch와 GossipingPropertyFileSnitch의 차이점
카산드라는 다양한 환경에 맞는 여러 종류의 스니치를 제공한다.19
-
SimpleSnitch: 가장 기본적인 스니치로, 네트워크 토폴로지를 전혀 인식하지 못한다. 모든 노드를 단일 데이터센터의 단일 랙에 있는 것으로 간주한다.21 따라서 이 스니치는 개발 및 테스트 환경과 같이 단일 노드 또는 단일 랙으로 구성된 클러스터에서만 사용해야 하며, 프로덕션 환경에는 절대적으로 부적합하다.19
-
GossipingPropertyFileSnitch: 프로덕션 환경에서 가장 널리 권장되는 스니치이다.19 이 방식은 각 노드의
cassandra-rackdc.properties라는 설정 파일에 해당 노드가 속한 데이터센터와 랙 정보를 명시적으로 기입하는 방식이다.19 각 노드는 이 정보를 가십 프로토콜을 통해 클러스터 내 다른 모든 노드에게 전파한다. 이를 통해 모든 노드가 중앙의 설정 파일 동기화 없이도 전체 클러스터의 토폴로지 정보를 최신 상태로 유지할 수 있다.19
이 외에도 AWS, Google Cloud 등 특정 클라우드 환경의 토폴로지 정보를 자동으로 감지하는 Ec2Snitch, GoogleCloudSnitch 등이 있어 인프라 환경에 맞춰 최적의 스니치를 선택할 수 있다.19
2.3.2 동적 스니칭 (Dynamic Snitching)
정적인 토폴로지 정보만으로는 노드의 일시적인 과부하, 네트워크 혼잡 등 실시간 성능 변화에 대응하기 어렵다. ’동적 스니칭(Dynamic Snitching)’은 이러한 한계를 극복하기 위한 기능이다.19 기본적으로 카산드라는 사용자가 설정한 기본 스니치(예: GossipingPropertyFileSnitch)를 DynamicEndpointSnitch로 감싸서 동작시킨다.19
동적 스니치는 실제 읽기 요청들의 성능(지연 시간)을 지속적으로 추적하고 점수를 매긴다. 그리고 읽기 요청을 보낼 때, 토폴로지상 가깝더라도 현재 성능이 저하된 노드는 피하고 가장 응답이 빠른 노드를 우선적으로 선택한다.19 이는 정적인 네트워크 토폴로지 정보 위에 동적인 성능 데이터를 덧씌워, 클러스터가 실시간 부하 변화에 지능적으로 적응하고 최적의 성능을 유지하도록 돕는 고도화된 라우팅 메커니즘이다.
3. 데이터 분산, 복제, 그리고 일관성
카산드라는 대규모 데이터를 안정적으로 관리하기 위해 정교한 데이터 분산, 복제, 그리고 일관성 유지 메커니즘을 갖추고 있다. 이 메커니즘들은 시스템의 확장성, 고가용성, 그리고 데이터의 신뢰성을 보장하는 핵심 요소로 작용한다. 특히, CAP 이론의 제약을 정적인 한계로 받아들이지 않고, ’조정 가능한 일관성’이라는 유연한 해법을 통해 애플리케이션의 다양한 요구사항에 동적으로 대응하는 실용적인 접근법을 취한다.
3.1 파티셔닝: 일관된 해싱(Consistent Hashing)과 가상 노드(vnodes)
카산드라의 수평적 확장성은 데이터를 여러 노드에 효과적으로 분산시키는 파티셔닝(Partitioning) 기술에 기반한다. 이를 위해 ’일관된 해싱(Consistent Hashing)’이라는 알고리즘을 사용한다.13
전통적인 해싱 방식은 해시 값을 서버의 수로 나눈 나머지를 사용하여 데이터를 분배한다. 이 방식의 문제점은 서버(노드) 수가 변경될 때 거의 모든 데이터가 재배치되어야 한다는 것이다. 이는 대규모 데이터 이동을 유발하여 시스템에 막대한 부하를 준다.24
일관된 해싱은 이러한 문제를 해결한다. 먼저, 매우 큰 범위의 숫자 값(예: −263 에서 263−1)으로 구성된 논리적인 ’토큰 링(Token Ring)’을 상상한다.2 데이터의 파티션 키는 해시 함수를 통해 이 링 위의 특정 위치를 나타내는 ‘토큰’ 값으로 변환된다. 동시에, 클러스터의 각 노드에도 하나 이상의 토큰 값이 할당되어 링 위에 배치된다.2 데이터는 자신의 토큰 값으로부터 링을 시계 방향으로 따라가다 처음 만나는 노드에 저장된다. 이 방식의 가장 큰 장점은 노드가 추가되거나 제거될 때, 영향을 받는 데이터가 해당 노드의 이웃 노드들에 국한된다는 점이다. 즉, 전체 데이터의 극히 일부만 재배치하면 되므로 클러스터의 확장이 매우 효율적이다.13
3.1.1 가상 노드 (vnodes)
초기 카산드라 버전에서는 각 물리 노드가 링에서 단 하나의 큰 토큰 범위를 담당했다. 이 방식은 노드 추가 시 특정 노드에서만 대량의 데이터를 이동시켜야 하는 부담과 데이터 분포의 불균형을 야기할 수 있었다.13
이 문제를 해결하기 위해 도입된 것이 ‘가상 노드(virtual nodes, vnodes)’ 개념이다.13 vnodes는 하나의 물리 노드가 링 상에서 여러 개의 작은 토큰 범위를 담당하도록 하는 기술이다. 예를 들어, 256개의 vnode를 사용하도록 설정하면, 각 물리 노드는 링 전체에 흩어져 있는 256개의 작은 데이터 조각들을 책임지게 된다.
vnodes의 도입은 다음과 같은 중요한 이점을 가져왔다 13:
- 탄력적 확장성: 새로운 노드가 클러스터에 추가될 때, 이 노드는 링 전체에 흩어져 있는 여러 기존 노드들로부터 조금씩 데이터를 가져온다. 데이터 이동의 부담이 특정 노드에 집중되지 않고 클러스터 전체에 분산되므로, 노드 추가 및 제거 작업이 훨씬 원활하고 빨라진다.
- 균등한 데이터 분배: 데이터와 부하가 클러스터 전체에 더 균등하게 분산되어 ‘핫스팟(hotspot)’ 발생 가능성을 줄인다.
- 장애 복구 향상: 특정 노드에 장애가 발생했을 때, 해당 노드가 담당하던 데이터에 대한 요청 부하가 여러 다른 노드들로 자연스럽게 분산된다.
3.2 복제 전략과 고가용성 달성 메커니즘
카산드라는 노드 장애나 데이터센터 전체의 재해 상황에서도 데이터를 안전하게 보존하고 서비스를 지속하기 위해 데이터를 여러 노드에 복제한다.13 복제본의 개수는 키스페이스를 생성할 때 ’복제 계수(Replication Factor, RF)’를 통해 지정한다.13 예를 들어, RF=3이라면 원본 데이터를 포함하여 총 3개의 복제본이 클러스터 내 서로 다른 노드에 저장된다. 중요한 점은 카산드라에는 프라이머리(Primary)나 마스터(Master) 복제본이라는 개념이 없으며, 모든 복제본은 동등한 지위를 갖는다는 것이다.26
데이터 복제본을 어떤 노드에 배치할지는 ’복제 전략(Replication Strategy)’에 따라 결정된다.
-
SimpleStrategy: 이 전략은 주로 단일 데이터센터로 구성된 개발 환경이나 테스트 환경에서 사용된다.13 파티션 키의 토큰이 속한 노드를 첫 번째 복제본으로 삼고, 링을 시계 방향으로 따라가면서 만나는 다음 노드들에 순차적으로 나머지 복제본을 배치한다.18 이 방식은 네트워크 토폴로지(랙 구성 등)를 고려하지 않는다.
-
NetworkTopologyStrategy: 프로덕션 환경 및 다중 데이터센터 환경에서 반드시 사용해야 하는 전략이다.13 이 전략은 각 데이터센터별로 복제 계수를 독립적으로 설정할 수 있게 해준다. 예를 들어, 미국 데이터센터에는 3개의 복제본을, 유럽 데이터센터에는 2개의 복제본을 두는 것이 가능하다. 더 중요한 것은, 이 전략이 스니치(Snitch)가 제공하는 네트워크 토폴로지 정보를 활용한다는 점이다.
NetworkTopologyStrategy는 복제본을 가능한 한 서로 다른 랙(rack)에 분산시키려고 시도한다. 이를 통해 랙 단위의 장애(예: 랙 스위치 고장, 랙 전원 문제)가 발생하더라도 데이터의 가용성을 잃지 않도록 보장한다.13
3.3 CAP 이론 관점에서의 분석: AP 시스템과 조정 가능한 일관성(Tunable Consistency)
분산 시스템 설계를 논할 때 빠질 수 없는 것이 CAP 이론이다. 이 이론에 따르면, 분산 시스템은 세 가지 속성, 즉 일관성(Consistency), 가용성(Availability), 분할 허용성(Partition Tolerance) 중에서 최대 두 가지만을 동시에 보장할 수 있다.28 네트워크 장애는 분산 시스템에서 피할 수 없는 현실이므로, 모든 실용적인 분산 시스템은 분할 허용성(P)을 기본적으로 선택해야 한다. 따라서 실제 선택은 일관성(C)과 가용성(A) 사이에서 이루어진다.31
카산드라는 설계 철학상, 네트워크 분할(P) 상황에서 데이터의 정합성(C)을 일부 희생하더라도 모든 요청에 응답하는 것(A)을 우선시하는 AP 시스템으로 분류된다.28 이는 일부 노드가 다운되거나 네트워크적으로 고립되더라도, 살아있는 노드들이 계속해서 읽기 및 쓰기 요청을 처리하여 서비스 중단을 최소화하는 것을 목표로 함을 의미한다.
이러한 선택의 결과로 카산드라는 기본적으로 ‘결과적 일관성(Eventual Consistency)’ 모델을 따른다.1 이는 쓰기 작업이 성공한 직후 모든 복제본이 즉시 동일한 데이터를 보장하지는 않지만, 충분한 시간이 지나면(보통 수 밀리초 내에) 모든 복제본이 결국에는 일관된 상태에 도달함을 보장하는 모델이다.
하지만 카산드라는 AP 시스템이라는 정적인 분류에 갇히지 않는다. ’조정 가능한 일관성(Tunable Consistency)’이라는 매우 강력하고 유연한 기능을 제공함으로써, CAP 이론의 트레이드오프를 개발자가 직접 제어할 수 있게 한다.4 이는 시스템 전체에 고정된 일관성 모델을 강요하는 대신, 애플리케이션의 각 읽기/쓰기 요청마다 ’일관성 수준(Consistency Level, CL)’을 명시하여 가용성과 일관성 사이의 균형을 동적으로 조절할 수 있게 하는 것이다.
주요 일관성 수준은 다음과 같다.28
ONE: 복제본 중 하나라도 응답하면 성공으로 간주한다. 가장 빠르지만 일관성은 가장 낮다.QUORUM: 전체 복제본 중 과반수(⌊RF/2⌋+1)가 응답해야 성공으로 간주한다. 일관성과 가용성 사이의 일반적인 균형점이다.LOCAL_QUORUM: 요청을 받은 코디네이터 노드가 속한 데이터센터 내에서 과반수의 복제본이 응답해야 성공으로 간주한다. 데이터센터 간의 네트워크 지연을 피하면서 일관성을 유지하는 데 사용된다.ALL: 모든 복제본이 응답해야 성공으로 간주한다. 가장 강력한 일관성을 보장하지만, 단 하나의 복제본 노드라도 장애가 발생하면 요청이 실패하므로 가용성은 가장 낮다.
이러한 일관성 수준을 조합하여 강력한 일관성을 달성할 수도 있다. 읽기 요청의 일관성 수준(R)과 쓰기 요청의 일관성 수준(W)의 합이 복제 계수(N)보다 크도록 설정하면 (R+W>N), 읽기 작업과 쓰기 작업에 참여하는 노드 집합이 반드시 하나 이상 겹치게 되어 항상 최신 데이터를 읽는 것을 보장할 수 있다.13 예를 들어,
RF=3인 환경에서 쓰기와 읽기 요청 모두에 CL=QUORUM(노드 2개의 응답 필요)을 사용하면, 2+2>3 이므로 강력한 일관성이 보장된다.
이처럼 ’조정 가능한 일관성’은 CAP 이론을 정적인 제약이 아닌 동적인 설계의 축으로 활용하는 고도의 아키텍처적 유연성을 보여준다. 개발자는 비즈니스 요구사항의 중요도에 따라, 빠른 응답이 중요한 기능에는 낮은 일관성 수준을, 데이터 정합성이 중요한 기능에는 높은 일관성 수준을 선택적으로 적용하여 시스템 전체의 성능과 신뢰성을 최적화할 수 있다.
4. 쿼리 중심의 데이터 모델링과 CQL
카산드라의 성능과 확장성을 최대한 활용하기 위해서는 그 데이터 모델링 패러다임을 깊이 이해하는 것이 필수적이다. 카산드라의 데이터 모델링은 관계형 데이터베이스(RDBMS)의 ‘데이터 중심’ 접근법과 근본적으로 다르다. 이는 ‘애플리케이션 중심’, 즉 ’쿼리 기반 설계’라는 패러다임 전환을 요구한다. ’JOIN 미지원’은 이러한 철학의 가장 명백한 발현이며, 이는 단순한 제약이 아니라 분산 시스템에서 예측 가능한 저지연(low-latency) 성능을 보장하기 위한 의도적인 설계 결정이다.
4.1 카산드라 데이터 모델의 구성 요소
카산드라의 데이터는 계층적인 구조로 구성된다.10
- 키스페이스 (Keyspace): 가장 상위의 데이터 컨테이너로, RDBMS의 데이터베이스나 스키마와 유사한 개념이다.10 키스페이스는 하나 이상의 테이블을 포함하며, 가장 중요한 역할은 해당 키스페이스에 속한 데이터의 복제 전략(Replication Strategy)과 복제 계수(Replication Factor)를 정의하는 것이다.32
- 테이블 (Table): 과거 ’컬럼 패밀리(Column Family)’로 불렸던 개념으로, 행(Row)과 열(Column)로 구성된 데이터의 집합이다.8 각 테이블은 데이터를 고유하게 식별하는 기본 키(Primary Key)를 반드시 가져야 한다.
- 파티션 키 (Partition Key): 기본 키의 첫 번째 부분을 구성하며, 카산드라 데이터 모델링의 가장 핵심적인 요소이다.14 파티션 키의 값은 해싱되어 토큰(Token)으로 변환되고, 이 토큰 값에 따라 데이터가 클러스터 내의 어떤 물리적 노드(파티션)에 저장될지가 결정된다.2 따라서 모든 읽기 및 쓰기 성능은 파티션 키를 어떻게 설계하느냐에 따라 극명하게 달라진다. 파티션 키는 단일 컬럼(Simple Partition Key)으로 구성될 수도 있고, 여러 컬럼을 괄호로 묶어 복합 파티션 키(Composite Partition Key)로 구성할 수도 있다 (
PRIMARY KEY ((col_a, col_b),...)).36 - 클러스터링 키 (Clustering Key): 기본 키에서 파티션 키를 제외한 나머지 부분을 의미한다.35 클러스터링 키의 역할은 동일한 파티션 키를 가진 데이터(행)들을 물리적으로 어떻게 정렬하여 저장할지를 결정하는 것이다. 데이터는 클러스터링 키의 순서에 따라 디스크에 정렬되어 저장되므로, 특정 범위의 데이터를 조회하는 범위 쿼리(range query)나 정렬된 결과를 얻는 쿼리를 매우 효율적으로 수행할 수 있게 해준다.37
4.2 핵심 원칙: 쿼리 기반 설계(Query-Driven Design)와 비정규화(Denormalization)
RDBMS 데이터 모델링의 제1원칙은 정규화(Normalization)를 통해 데이터 중복을 최소화하고 데이터 무결성을 유지하는 것이다. 그리고 필요한 데이터는 쿼리 시점에 JOIN 연산을 통해 조합한다. 카산드라는 이와 정반대의 접근법을 취한다.
쿼리 기반 설계 (Query-Driven Design): 카산드라에서는 데이터의 관계를 중심으로 테이블을 설계하는 것이 아니라, 애플리케이션이 데이터를 어떻게 조회할 것인지, 즉 ’쿼리 패턴’을 가장 먼저 분석하고 정의해야 한다.39 그리고 각각의 쿼리 패턴을 가장 효율적으로 만족시킬 수 있도록 테이블을 설계한다. 이는 “하나의 쿼리에는 하나의 테이블“이라는 원칙으로 요약될 수 있다.
비정규화 (Denormalization): 쿼리 기반 설계를 따르다 보면, 자연스럽게 비정규화가 핵심 전략이 된다. RDBMS에서는 JOIN을 통해 여러 테이블의 정보를 결합하지만, 카산드라는 JOIN을 지원하지 않는다. 따라서 특정 쿼리가 여러 엔티티의 정보를 필요로 한다면, 해당 정보를 모두 포함하는 하나의 ‘비정규화된’ 테이블을 만드는 것이 일반적이다.39 예를 들어, ’사용자 정보’와 ‘사용자가 작성한 게시물’ 정보를 함께 보여줘야 하는 쿼리가 있다면, 게시물 테이블에 사용자 이름과 같은 중복 데이터를 함께 저장하는 것이다. 이는 쓰기 시점에 약간의 오버헤드와 추가적인 저장 공간을 감수하는 대신, 읽기 시점에는 단일 테이블 조회만으로 매우 빠른 성능을 얻기 위한 전략적 트레이드오프이다.
이러한 모델링의 핵심 목표는 두 가지로 요약된다: 1) 파티션 키를 신중하게 선택하여 데이터와 부하를 클러스터 전체에 균등하게 분산시키는 것, 그리고 2) 각 쿼리가 가능한 한 적은 수의 파티션(이상적으로는 단 하나)을 읽도록 설계하는 것이다.36
4.3 JOIN 미지원에 따른 대안적 접근법
카산드라가 JOIN을 지원하지 않는 이유는 그 아키텍처적 목표와 직결된다. 분산 환경에서 JOIN 연산은 서로 다른 노드에 흩어져 있는 데이터를 네트워크를 통해 실시간으로 집계해야 하는 매우 비용이 많이 드는 작업이다. 이는 네트워크 병목을 유발하고 응답 시간을 예측 불가능하게 만들어, 카산드라가 추구하는 선형적 확장성과 예측 가능한 저지연 성능이라는 목표를 근본적으로 훼손한다.43
따라서 JOIN이 필요한 RDBMS의 데이터 모델을 카산드라로 이전할 때는 다음과 같은 대안적인 접근법을 사용해야 한다.
- 비정규화를 통한 테이블 생성 (권장): 가장 일반적이고 권장되는 방법이다. 앞서 설명한 바와 같이, 쿼리 패턴에 맞춰 필요한 모든 데이터를 포함하는 새로운 테이블을 생성한다. 예를 들어,
사용자별 주문 목록을 조회하는 쿼리가 있다면, 주문 테이블에 사용자 ID를 파티션 키로 두고, 주문 정보와 함께 필요한 제품명, 가격 등의 정보를 중복해서 저장하는orders_by_user테이블을 만든다.43 - 클라이언트 측 조인 (제한적 사용): 애플리케이션 코드 레벨에서 여러 테이블에 개별적으로 쿼리를 실행한 후, 그 결과를 메모리에서 직접 조합하는 방식이다.43 예를 들어, 주문 ID로 주문 정보를 조회하고, 그 결과에 포함된 사용자 ID로 다시 사용자 테이블을 조회하여 두 정보를 합치는 것이다. 이 방법은 여러 번의 네트워크 왕복을 유발하므로 지연 시간이 길어지고 애플리케이션의 복잡도가 증가한다. 따라서 데이터 모델을 변경하기 어려운 예외적인 상황에서만 제한적으로 사용해야 한다.
- 구체화된 뷰 (Materialized Views): 카산드라가 서버 측에서 비정규화를 자동으로 관리해주는 기능이다.32 기본 테이블(base table)을 기반으로, 다른 파티션 키와 클러스터링 키를 갖는 새로운 뷰 테이블을 생성할 수 있다. 기본 테이블의 데이터가 변경되면 카산드라가 자동으로 뷰 테이블을 업데이트해준다.24 이는 개발 편의성을 높여주지만, 백그라운드 업데이트로 인한 성능 오버헤드가 발생할 수 있고, 여전히 실험적인 기능으로 간주되어 몇 가지 제약사항이 존재하므로 신중하게 사용해야 한다.32
4.4 Cassandra Query Language (CQL) 활용법
카산드라는 데이터베이스와 상호작용하기 위해 CQL(Cassandra Query Language)이라는 쿼리 언어를 제공한다. CQL은 의도적으로 SQL과 매우 유사한 구문을 채택하여, RDBMS에 익숙한 개발자들이 쉽게 적응할 수 있도록 설계되었다.9
CQL은 데이터 정의 언어(DDL)와 데이터 조작 언어(DML)를 모두 포함한다.35
- DDL:
CREATE KEYSPACE,CREATE TABLE,ALTER TABLE,DROP TABLE등 스키마를 정의하고 변경하는 명령어. - DML:
INSERT,UPDATE,DELETE,SELECT등 데이터를 조작하고 조회하는 명령어.
SQL과의 주요 차이점은 카산드라의 데이터 모델 제약을 반영한다는 점이다. JOIN 연산은 지원되지 않으며, GROUP BY와 같은 집계 기능도 매우 제한적이다.34
SELECT 문의 WHERE 절에서 필터링 조건으로 사용할 수 있는 컬럼은 주로 기본 키(파티션 키 및 클러스터링 키)로 한정된다. 이는 카산드라가 전체 데이터를 스캔하는 비효율적인 쿼리를 방지하고, 항상 파티션 키를 통해 특정 노드의 특정 위치를 직접 찾아가는 고성능 쿼리를 유도하기 위함이다.
기본 CQL 사용 예시:
-- 1. 키스페이스 생성 (데이터센터 dc1에 복제본 3개)
CREATE KEYSPACE my_app WITH replication = {
'class': 'NetworkTopologyStrategy',
'dc1': '3'
};
-- 2. 생성한 키스페이스 사용
USE my_app;
-- 3. 사용자별 비디오 목록을 저장할 테이블 생성
-- userid가 파티션 키, uploaded_at이 클러스터링 키
CREATE TABLE videos_by_user (
userid UUID,
uploaded_at TIMESTAMP,
video_id UUID,
title TEXT,
PRIMARY KEY (userid, uploaded_at)
) WITH CLUSTERING ORDER BY (uploaded_at DESC);
-- 4. 데이터 삽입
INSERT INTO videos_by_user (userid, uploaded_at, video_id, title)
VALUES (uuid(), toTimestamp(now()), uuid(), 'My First Video');
-- 5. 데이터 조회 (파티션 키는 반드시 지정해야 함)
SELECT video_id, title FROM videos_by_user
WHERE userid = 123e4567-e89b-12d3-a456-426614174000;
34
4.4.1 표 1: 관계형 데이터베이스(RDBMS)와 카산드라의 데이터 모델링 패러다임 비교
| 특성 | RDBMS (정규화 모델) | Cassandra (비정규화/쿼리 기반 모델) |
|---|---|---|
| 설계 중심 | 데이터 관계 (엔티티) 중심 | 애플리케이션 쿼리 중심 |
| 데이터 중복 | 최소화 (정규화) | 허용 및 권장 (비정규화) |
| 데이터 조합 | 읽기 시점 (JOIN) | 쓰기 시점 (비정규화 테이블) |
| 스키마 변경 | 어려움 (Migration 필요) | 유연함 (동적 컬럼 추가) |
| 주요 최적화 목표 | 저장 공간 효율성, 데이터 무결성 | 읽기 성능, 확장성 |
이 표는 두 시스템 간의 근본적인 철학적 차이를 명확하게 보여준다. 카산드라를 성공적으로 도입하기 위해서는 RDBMS적 사고방식에서 벗어나, 애플리케이션의 데이터 접근 패턴을 최우선으로 고려하는 ’쿼리 기반 설계’라는 새로운 패러다임을 받아들이는 것이 왜 중요한지를 함축적으로 전달한다.
5. 스토리지 엔진 내부 동작 원리
카산드라의 고성능은 ’쓰기 최적화’라는 명확한 목표를 위해 설계된 정교한 스토리지 엔진에 기인한다. 이 엔진의 핵심은 LSM-Tree(Log-Structured Merge-Tree) 아키텍처로, 이 선택에서 비롯된 인과관계의 사슬이 카산드라의 쓰기, 읽기, 삭제, 그리고 데이터 유지보수 방식 전체를 규정한다. 빠른 쓰기를 얻는 대가로 발생하는 읽기 및 삭제의 복잡성을 해결하기 위해 블룸 필터, 툼스톤, 컴팩션과 같은 보완적인 메커니즘들이 유기적으로 작동한다.
5.1 쓰기 경로(Write Path): LSM-Tree 기반의 고성능 쓰기 메커니즘
카산드라는 전통적인 데이터베이스가 사용하는 B-Tree 구조 대신 LSM-Tree를 채택하여 쓰기 성능을 극대화했다.53 B-Tree는 데이터를 정렬된 상태로 유지하기 위해 새로운 데이터가 삽입될 때 디스크의 특정 위치를 찾아 데이터를 수정하는 ‘제자리 업데이트(in-place update)’ 방식을 사용한다. 이는 디스크 탐색(seek)과 랜덤 I/O를 유발하여 쓰기 작업에 병목을 일으킬 수 있다.
반면, LSM-Tree는 모든 쓰기 작업을 디스크에 순차적으로 추가(append-only)하는 방식으로 처리하여 랜덤 I/O를 제거하고 쓰기 처리량을 획기적으로 향상시킨다.56 카산드라의 쓰기 경로는 다음과 같은 단계로 이루어진다.56
- 커밋 로그(Commit Log)에 추가: 클라이언트로부터 쓰기 요청이 들어오면, 카산드라는 먼저 해당 데이터를 디스크 상의 커밋 로그 파일에 순차적으로 기록한다.10 이는 쓰기 전 로그(Write-Ahead Log, WAL)의 일종으로, 노드에 예기치 않은 장애가 발생하더라도 기록된 데이터를 복구하여 내구성(Durability)을 보장하는 역할을 한다. 커밋 로그에 대한 쓰기는 순차 I/O이므로 매우 빠르다.
- 멤테이블(Memtable)에 쓰기: 커밋 로그에 기록하는 동시에, 데이터는 메모리 내의 정렬된 자료 구조인 멤테이블에 쓰여진다.10 멤테이블은 파티션 키와 클러스터링 키를 기준으로 데이터를 정렬된 상태로 유지한다.
- 클라이언트에 응답: 이 두 단계가 완료되면, 즉 데이터가 디스크(커밋 로그)와 메모리(멤테이블)에 모두 안전하게 기록되면, 카산드라는 클라이언트에게 쓰기 작업이 성공했음을 알린다. 이 과정에서 디스크에 대한 랜덤 I/O가 전혀 발생하지 않기 때문에 쓰기 지연 시간이 극도로 짧다.
- SSTable로 플러시(Flush): 멤테이블이 설정된 크기 임계값에 도달하거나 일정 시간이 지나면, 멤테이블의 내용은 디스크에 새로운 파일 형태로 순차적으로 기록된다. 이 파일을 SSTable(Sorted String Table)이라고 부른다.10 SSTable은 한번 기록되면 절대 수정되지 않는 불변(immutable)의 속성을 가진다. 플러시 작업이 완료되면, 해당 멤테이블에 있던 데이터에 대한 커밋 로그는 더 이상 필요 없으므로 삭제된다.
5.2 읽기 경로(Read Path): 블룸 필터(Bloom Filter)를 통한 I/O 최적화
쓰기 최적화의 대가로 카산드라의 읽기 경로는 다소 복잡하다. 특정 파티션 키에 해당하는 데이터가 메모리의 멤테이블과 디스크의 여러 SSTable 파일에 흩어져 있을 수 있기 때문이다. 따라서 읽기 요청을 처리하기 위해서는 이 모든 소스로부터 데이터를 읽어와 병합한 후, 가장 최신 타임스탬프를 가진 데이터를 반환해야 한다 (Last Write Wins 원칙).10
만약 모든 SSTable 파일을 매번 디스크에서 읽어야 한다면 읽기 성능은 심각하게 저하될 것이다. 카산드라는 이러한 비효율을 줄이기 위해 여러 캐싱 및 최적화 기법을 사용하며, 그중 가장 핵심적인 것이 ’블룸 필터(Bloom Filter)’이다.58
블룸 필터(Bloom Filter)의 원리: 블룸 필터는 특정 원소가 집합에 속해 있는지를 매우 빠르고 메모리 효율적으로 검사할 수 있는 확률적 자료 구조이다.59 각 SSTable은 자신만의 블룸 필터를 가지며, 이 블룸 필터들은 메모리(오프힙)에 상주한다.58
블룸 필터는 두 가지 답변만 할 수 있다.59
- “찾는 데이터는 이 SSTable에 절대 존재하지 않는다.” (거짓 음성, False Negative 없음)
- “찾는 데이터가 이 SSTable에 존재할 가능성이 있다.” (거짓 양성, False Positive 가능)
읽기 요청이 들어오면, 카산드라는 디스크의 SSTable 파일에 접근하기 전에 먼저 메모리에 있는 블룸 필터를 확인한다. 만약 블룸 필터가 “절대 존재하지 않는다“고 응답하면, 해당 SSTable에 대한 비싼 디스크 I/O 작업을 완전히 건너뛸 수 있다.60 “존재할 가능성이 있다“고 응답할 경우에만 실제 SSTable 파일을 읽어 데이터의 존재 여부를 최종 확인한다. 이 메커니즘을 통해 카산드라는 불필요한 디스크 접근을 획기적으로 줄여 읽기 성능을 크게 향상시킨다.59
카산드라의 전체 읽기 경로는 다음과 같은 순서로 진행된다.58
- 활성 멤테이블 확인
- (활성화 시) 행 캐시(Row Cache) 확인
- 블룸 필터 확인
- 블룸 필터가 통과하면, (활성화 시) 파티션 키 캐시(Partition Key Cache)를 확인하여 SSTable 내 데이터의 오프셋을 찾음
- 캐시에 오프셋이 없으면, 파티션 요약(Partition Summary)과 파티션 인덱스(Partition Index)를 통해 오프셋을 찾음
- 찾아낸 오프셋을 이용해 SSTable 파일에서 데이터를 읽어옴
- 멤테이블과 여러 SSTable에서 읽어온 결과를 병합하여 최종 결과를 반환
5.3 삭제 메커니즘: 툼스톤(Tombstone)의 역할과 성능 영향
LSM-Tree 아키텍처에서 SSTable은 불변(immutable)이기 때문에, 기존 데이터를 직접 찾아가 삭제하는 작업이 불가능하다. 대신 카산드라는 논리적인 삭제 방식을 사용하는데, 이것이 바로 ’툼스톤(Tombstone)’이다.10
데이터 삭제 요청이 오면, 카산드라는 데이터를 물리적으로 지우는 대신, 해당 데이터가 삭제되었음을 알리는 타임스탬프가 찍힌 특수한 마커, 즉 툼스톤을 새로 기록한다.62 툼스톤 역시 일반 데이터와 마찬가지로 쓰기 경로를 통해 멤테이블에 기록된 후 SSTable로 플러시된다. 읽기 요청이 들어오면, 카산드라는 데이터와 툼스톤을 함께 읽고, 툼스톤의 타임스탬프가 데이터의 타임스탬프보다 최신이면 해당 데이터를 없는 것으로 간주하고 결과에서 제외한다.
툼스톤의 역할: 툼스톤은 분산 환경에서 삭제 정보가 모든 복제본에 안정적으로 전파되도록 보장하는 핵심적인 역할을 한다. 만약 어떤 노드가 다운된 상태에서 데이터가 삭제되었다고 가정해보자. 툼스톤이 없다면, 나중에 이 노드가 다시 온라인 상태가 되었을 때, 다른 노드들은 이미 삭제된 데이터를 가지고 있는 이 노드로부터 오래된 데이터를 복제하여 삭제된 데이터가 되살아나는 ‘좀비 데이터(zombie data)’ 현상이 발생할 수 있다. 툼스톤은 이러한 데이터 부활을 방지한다.64
성능 영향: 툼스톤은 필수적인 기능이지만, 과도하게 많아지면 심각한 성능 저하를 유발한다.62
- 읽기 성능 저하: 읽기 쿼리는 유효한 데이터뿐만 아니라 툼스톤도 함께 스캔해야 하므로, 툼스톤이 많을수록 처리할 데이터가 늘어나 지연 시간이 증가한다. 특히 범위 쿼리에서 수많은 툼스톤을 건너뛰어야 할 경우 성능 저하가 극심하다.
- 메모리 및 GC 압박: 스캔된 툼스톤은 힙 메모리에 로드되어야 하므로, 메모리 사용량을 증가시키고 가비지 컬렉션(GC)에 부담을 준다.
- 디스크 사용량: 툼스톤 자체도 디스크 공간을 차지한다.
gc_grace_seconds: 툼스톤은 영원히 남아있지 않는다. 각 테이블에는 gc_grace_seconds라는 설정값이 있으며, 기본값은 10일(864,000초)이다.62 이 시간은 삭제 정보가 다운된 노드에까지 전파될 수 있는 유예 기간을 의미한다. 툼스톤이 생성된 후 gc_grace_seconds가 지나면, 해당 툼스톤은 컴팩션(Compaction) 과정에서 관련된 데이터와 함께 영구적으로 제거될 수 있다.62 따라서 클러스터의 모든 노드는 gc_grace_seconds 주기 내에 최소 한 번 이상 nodetool repair를 실행하여 데이터 일관성을 맞춰야 한다.
5.4 압축(Compaction) 전략 비교 분석: STCS, LCS, TWCS
시간이 지남에 따라 플러시 작업으로 인해 수많은 SSTable이 디스크에 쌓이게 된다. 또한, 업데이트(새로운 버전의 데이터를 씀)와 삭제(툼스톤을 씀)로 인해 오래된 데이터와 툼스톤이 디스크 공간을 차지하게 된다. ’컴팩션(Compaction)’은 이렇게 흩어져 있는 여러 SSTable과 불필요한 데이터(오래된 버전, 툼스톤)를 병합하여 더 적은 수의 새로운 SSTable로 만드는 백그라운드 유지보수 작업이다.10 컴팩션은 디스크 공간을 효율적으로 재사용하고, 읽기 시 스캔해야 할 SSTable의 수를 줄여 읽기 성능을 최적화하는 데 필수적이다.
카산드라는 워크로드의 특성에 따라 선택할 수 있는 여러 컴팩션 전략을 제공한다.
- SizeTieredCompactionStrategy (STCS): 기본 전략으로, 비슷한 크기의 SSTable이 4개 이상(기본 설정) 모이면 이들을 하나의 큰 SSTable로 병합한다.68 이 과정은 쓰기 작업 중에 발생하는 I/O 오버헤드(쓰기 증폭)가 상대적으로 적어 쓰기 중심의 워크로드에 적합하다. 하지만 데이터가 여러 크기의 SSTable에 흩어져 있을 수 있어 읽기 시 여러 파일을 스캔해야 할 수 있고(읽기 증폭 높음), 오래된 데이터가 오랫동안 남아있을 수 있으며, 컴팩션 시 임시적으로 원본 데이터 크기만큼의 추가 디스크 공간이 필요하다(공간 증폭 높음).69
- LeveledCompactionStrategy (LCS): 읽기 중심의 워크로드에 최적화된 전략이다.67 SSTable을 여러 개의 ’레벨(Level)’로 나누어 관리한다. 가장 낮은 레벨(L0)을 제외한 각 레벨(L1, L2,…) 내의 SSTable들은 서로 데이터(파티션 키) 범위가 겹치지 않도록 유지된다. 이 덕분에 특정 데이터를 찾기 위해 각 레벨에서 최대 하나의 SSTable만 읽으면 되므로 읽기 성능이 매우 뛰어나다(읽기 증폭 낮음). 그러나 데이터를 상위 레벨로 올리기 위해 더 작고 빈번한 컴팩션이 계속해서 발생하므로, 쓰기 I/O 오버헤드(쓰기 증폭)가 STCS보다 훨씬 크다.70
- TimeWindowCompactionStrategy (TWCS): 로그나 센서 데이터와 같은 시계열 데이터에 특화된 전략이다.67 데이터를 시간 단위(예: 1일)의 ’윈도우’로 그룹화한다. 각 윈도우 내에서는 STCS 방식으로 컴팩션이 진행된다. 윈도우가 닫히면(즉, 해당 시간 구간이 지나면), 그 윈도우에 속한 SSTable들은 더 이상 다른 윈도우의 SSTable과 병합되지 않는다. 이는 오래된 데이터와 최신 데이터가 섞이는 것을 방지한다. 특히 데이터에 TTL(Time-To-Live)을 설정한 경우, 특정 윈도우의 모든 데이터가 만료되면 카산드라는 해당 윈도우에 속한 SSTable 파일 전체를 간단히 삭제할 수 있어, 툼스톤을 생성하지 않고도 매우 효율적으로 오래된 데이터를 제거할 수 있다.70
- UnifiedCompactionStrategy (UCS): Cassandra 5.0에 도입된 최신 전략으로, STCS와 LCS의 장점을 결합한 하이브리드 방식이다.68 단일 전략 내에서 파라미터 조정을 통해 STCS처럼 동작하게 하거나 LCS처럼 동작하게 할 수 있어, 다양한 워크로드에 유연하게 대응하고 운영의 복잡성을 줄여준다.72
5.4.1 표 2: 카산드라 압축(Compaction) 전략 비교
| 전략 | 최적 워크로드 | 읽기 증폭 | 쓰기 증폭 | 공간 증폭 | 핵심 동작 원리 |
|---|---|---|---|---|---|
| STCS | 쓰기 중심 | 높음 | 낮음 | 높음 | 비슷한 크기의 SSTable들을 하나의 큰 SSTable로 병합 |
| LCS | 읽기 중심 | 낮음 | 높음 | 낮음 | SSTable을 레벨별로 관리하며, 각 레벨 내 데이터가 겹치지 않게 유지 |
| TWCS | 시계열/TTL | 낮음 (윈도우 내) | 낮음 (윈도우 내) | 낮음 (TTL 만료 시) | 시간 윈도우 단위로 SSTable을 그룹화하여 독립적으로 관리 |
| UCS (5.0+) | 혼합/적응형 | 가변/조정 가능 | 가변/조정 가능 | 가변/조정 가능 | STCS와 LCS를 결합한 하이브리드 알고리즘 |
이 표는 운영자가 자신의 애플리케이션 워크로드 특성에 맞는 최적의 컴팩션 전략을 선택하는 데 필요한 핵심 정보를 일목요연하게 제공한다. 각 전략의 근본적인 트레이드오프 관계를 이해하는 것은 카산드라 클러스터의 장기적인 성능과 안정성을 유지하는 데 매우 중요하다.
6. 운영, 관리 및 성능 튜닝
카산드라의 분산 아키텍처는 뛰어난 확장성과 가용성을 제공하지만, 그 성능을 최적으로 유지하고 안정적으로 운영하기 위해서는 지속적인 관리와 튜닝이 필수적이다. 카산드라 운영은 ’균형’의 예술이라 할 수 있다. 쓰기 성능, 읽기 성능, 디스크 사용량, GC 효율 등 서로 상충하는 요소들 사이에서 현재 워크로드에 맞는 최적의 지점을 찾는 과정이며, 이는 nodetool을 통한 관리 작업, cassandra.yaml 및 JVM 설정을 통한 미세 조정, 그리고 모니터링을 통한 지속적인 관찰을 통해 이루어진다.
6.1 nodetool을 활용한 클러스터 관리
nodetool은 JMX(Java Management Extensions)를 통해 실행 중인 카산드라 노드와 상호작용하여 클러스터를 관리하고 모니터링하는 가장 기본적인 커맨드라인 유틸리티이다.10 운영자는 nodetool을 사용하여 클러스터의 상태를 확인하고, 데이터 일관성을 유지하며, 백업과 같은 필수적인 유지보수 작업을 수행할 수 있다.
6.1.1 Repair: 데이터 일관성 복구
카산드라는 결과적 일관성 모델을 따르기 때문에, 노드 장애나 네트워크 문제로 인해 복제본 간에 일시적인 데이터 불일치가 발생할 수 있다. ’Repair’는 이러한 불일치를 감지하고 동기화하여 데이터의 최종적인 일관성을 보장하는 안티-엔트로피(anti-entropy) 프로세스이다.76
Repair 과정에서 노드들은 자신이 담당하는 데이터 범위에 대해 머클 트리(Merkle Tree)라는 해시 트리를 생성한다. 이 트리를 서로 비교하여 데이터가 다른 부분을 효율적으로 찾아내고, 다른 부분만 네트워크를 통해 스트리밍하여 동기화한다.76
- Full Repair (
nodetool repair --full): 노드가 담당하는 모든 데이터에 대해 머클 트리를 생성하고 비교한다. 리소스 소모가 크지만, 전체 데이터의 정합성을 완벽하게 보장한다. 클러스터에 노드를 새로 추가했거나 복제 계수를 변경한 후에 실행하는 것이 좋다.76 - Incremental Repair (
nodetool repair): Cassandra 2.2부터 기본값으로, 마지막 repair 이후 새로 추가되거나 변경된 데이터(SSTable)만을 대상으로 repair를 수행한다.76 전체 데이터를 매번 비교하는 full repair보다 훨씬 효율적이므로, 정기적으로(예: 매일) 실행하는 것이 권장된다.
gc_grace_seconds(기본 10일) 주기 내에 반드시 repair를 수행하는 것은 매우 중요하다. 만약 이 기간 내에 repair가 실행되지 않으면, 삭제된 데이터의 정보(툼스톤)가 일부 노드에 전달되지 않은 상태에서 툼스톤이 먼저 삭제될 수 있다. 이 경우, 오래된 데이터를 가진 노드가 나중에 이 데이터를 다른 노드에 전파하여 삭제된 데이터가 되살아나는 ‘좀비 데이터’ 현상이 발생할 수 있다.76
6.1.2 Backup and Restore: 데이터 백업 및 복구
카산드라는 데이터 손실에 대비한 백업 및 복구 메커니즘을 제공한다.
-
백업 (Snapshot): 가장 일반적인 백업 방법은
nodetool snapshot명령어를 사용하는 것이다.32 이 명령어는 특정 시점의 모든 SSTable 파일에 대한 하드 링크(hard link)를 생성한다. 하드 링크는 실제 데이터 파일을 복사하는 것이 아니라 파일 시스템의 포인터만 생성하므로 매우 빠르고 디스크 공간을 거의 차지하지 않는다. 스냅샷 생성 후, 생성된 하드 링크 파일들을 외부 스토리지(예: S3, NAS)로 복사하여 안전하게 보관한다. 이 과정은 데이터베이스를 중단하지 않고 온라인 상태에서 수행할 수 있다. -
복구 (Restore): 데이터를 복구하려면 먼저 테이블의 데이터를 비우고(
TRUNCATE), 외부 스토리지에 백업해 둔 스냅샷 파일들을 원래의 카산드라 데이터 디렉토리로 복사한다.78 그 후,
nodetool refresh 명령어를 실행하여 카산드라가 새로 복사된 SSTable 파일들을 인식하고 로드하도록 한다. 복구가 완료된 후에는 클러스터 전체에 nodetool repair를 실행하여 노드 간 데이터 일관성을 반드시 맞춰주어야 한다.
이 외에도 nodetool status (클러스터 노드 상태 확인), nodetool info (특정 노드 정보), nodetool cfstats (테이블 통계), nodetool compactionstats (컴팩션 진행 상태), nodetool flush, nodetool drain (노드 재시작 전 메모리의 데이터를 디스크로 안전하게 내리는 작업) 등 다양한 명령어가 클러스터 운영에 필수적으로 사용된다.32
6.2 cassandra.yaml 핵심 파라미터 및 JVM 튜닝을 통한 성능 최적화
카산드라의 성능은 cassandra.yaml 설정 파일과 JVM(Java Virtual Machine) 옵션을 어떻게 조정하느냐에 따라 크게 달라진다. 워크로드의 특성을 정확히 파악하고 그에 맞는 튜닝을 적용하는 것이 중요하다.80
6.2.1 cassandra.yaml 핵심 파라미터
- 네트워킹 및 토폴로지:
listen_address,rpc_address: 노드가 다른 노드 및 클라이언트와 통신하기 위해 사용하는 IP 주소.seeds: 클러스터의 시드 노드 목록.endpoint_snitch: 클러스터의 네트워크 토폴로지(데이터센터, 랙)를 인식하는 전략을 설정. 프로덕션 환경에서는GossipingPropertyFileSnitch가 권장된다.80- 디스크 I/O 최적화:
commitlog_directory,data_file_directories: 커밋 로그와 데이터 파일(SSTable)의 저장 위치. 최상의 성능을 위해서는 이 두 디렉토리를 서로 다른 물리적 디스크에 배치해야 한다. 특히, 쓰기 성능에 지대한 영향을 미치는 커밋 로그는 SSD와 같은 빠른 디스크에 위치시키는 것이 매우 효과적이다.80commitlog_sync: 커밋 로그를 디스크에 동기화하는 방식.periodic(주기적) 방식은 성능이 좋지만 장애 시 일부 데이터 유실 가능성이 있고,batch방식은 내구성이 높지만 쓰기 지연 시간이 약간 증가한다.80- 메모리 및 압축:
memtable_allocation_type: 멤테이블을 JVM 힙 메모리(on-heap)에 할당할지, 아니면 네이티브 메모리(off-heap)에 할당할지를 결정. 오프힙을 사용하면 대용량 멤테이블을 사용하면서도 JVM의 GC 부담을 크게 줄일 수 있다.82concurrent_compactors,compaction_throughput_mb_per_sec: 컴팩션을 수행하는 스레드 수와 초당 최대 처리량을 제한하는 설정. 컴팩션이 다른 작업에 미치는 영향을 제어하는 데 사용된다.83
6.2.2 JVM 튜닝 (cassandra-env.sh 또는 jvm.options 파일)
카산드라는 JVM 위에서 동작하므로, JVM 튜닝, 특히 힙 메모리(Heap Memory)와 가비지 컬렉터(Garbage Collector, GC) 설정이 전체 성능에 결정적인 영향을 미친다.
- 힙 크기 (Heap Size):
MAX_HEAP_SIZE옵션으로 설정한다. 일반적으로 시스템 전체 RAM의 1/4에서 1/2 사이로 설정하는 것이 권장되지만, 절대적인 규칙은 아니다.84 OS가 파일 시스템 캐시로 사용할 메모리를 충분히 남겨두는 것이 매우 중요하다. 힙 크기가 너무 크면 Full GC 발생 시 ‘Stop-the-world’ 정지 시간이 길어져 노드가 응답 불능 상태에 빠질 수 있다. 반대로 너무 작으면 잦은 GC로 성능이 저하되거나 OutOfMemoryError가 발생할 수 있다.82 - 가비지 컬렉터 (GC) 설정:
- G1GC (Garbage-First): Java 9부터 기본 GC로, 대용량 힙(예: 16GB ~ 64GB) 환경에서 CMS보다 예측 가능한 정지 시간을 제공하도록 설계되었다.85 힙을 여러 개의 작은 영역(region)으로 나누고, 가비지가 가장 많이 쌓인 영역부터 우선적으로 정리하여 전체적인 GC 효율을 높인다.
- ZGC (Z Garbage Collector): Java 11에서 실험적으로 도입되어 Java 15부터 프로덕션용으로 사용 가능한 최신 저지연 GC이다.86 수백 GB 이상의 대용량 힙에서도 GC로 인한 정지 시간을 수 밀리초(sub-millisecond) 이내로 유지하는 것을 목표로 한다. Cassandra 5.0부터 JDK 17을 공식 지원하게 되면서, ZGC를 활용하여 매우 일관된 저지연 성능을 달성하는 것이 가능해졌다.72
6.3 Prometheus와 Grafana를 활용한 모니터링 핵심 지표
안정적인 클러스터 운영과 선제적인 성능 문제 해결을 위해서는 지속적인 모니터링이 필수적이다. 카산드라는 JMX를 통해 수백 개의 내부 성능 지표(metrics)를 노출한다. 오픈소스 모니터링 솔루션인 Prometheus와 Grafana는 이러한 지표를 수집, 저장, 시각화하는 사실상의 표준 조합이다. Prometheus는 jmx_exporter나 MCAC(Metrics Collector for Apache Cassandra) 같은 에이전트를 통해 카산드라의 JMX 메트릭을 주기적으로 수집(scrape)하고, Grafana는 수집된 데이터를 사용하여 시각적으로 이해하기 쉬운 대시보드를 구성한다.81
반드시 추적해야 할 핵심 성능 지표는 다음과 같다.
- 요청 지연 시간 (Request Latency): 읽기 및 쓰기 요청의 평균, 95, 99, 99.9 퍼센타일 지연 시간. 특히 99 퍼센타일 이상의 ’꼬리 지연 시간(tail latency)’은 시스템의 실제 사용자 경험과 안정성을 파악하는 데 매우 중요한 지표이다.90
- 요청 처리량 (Request Throughput): 초당 처리되는 읽기 및 쓰기 요청의 수. 클러스터가 현재 받고 있는 부하의 양을 나타낸다.90
- 대기 중인 작업 (Pending/Blocked Tasks): 컴팩션, 멤테이블 플러시 등 내부 스테이지에서 처리되지 못하고 대기 중인 작업의 수. 이 수치가 지속적으로 증가한다면 해당 스테이지에 병목이 발생했음을 의미한다.81
- 가비지 컬렉션 (Garbage Collection): GC 발생 횟수와 총 소요 시간, 특히 긴 ‘Stop-the-world’ 정지 시간. 긴 GC 정지는 노드 타임아웃을 유발하여 클러스터 전체의 안정성을 해칠 수 있다.90
- SSTable 및 컴팩션 관련 지표: 총 SSTable 개수, 디스크 사용량, 예상되는 컴팩션 작업의 양. SSTable 개수가 과도하게 많으면 읽기 성능 저하의 직접적인 원인이 된다.81
- 툼스톤 (Tombstone) 관련 지표: 읽기 쿼리에서 스캔된 툼스톤의 수. 이 지표가 높게 나타나면, 불필요한 데이터 스캔으로 인해 읽기 지연 시간이 길어지고 있음을 시사한다.66
- OS 수준 지표: CPU 사용률, 디스크 I/O 대기 시간, 네트워크 대역폭, 가용 메모리 등 노드 자체의 리소스 상태. 데이터베이스 내부 지표와 함께 분석하여 문제의 근본 원인을 파악하는 데 사용된다.81
7. 주요 데이터베이스 시스템과의 비교 분석
카산드라의 아키텍처와 특성을 깊이 이해하기 위해서는 다른 데이터베이스 시스템과의 비교를 통해 그 상대적인 위치와 설계 철학의 차이를 파악하는 것이 효과적이다. 데이터베이스 선택은 단순히 기술 스택을 고르는 행위가 아니라, 해결하고자 하는 비즈니스 문제의 특성과 가장 잘 맞는 ‘설계 철학’ 및 ’트레이드오프’를 선택하는 전략적 결정이다. 각 데이터베이스는 특정 목표를 달성하기 위해 다른 가치를 의도적으로 희생한 결과물이기 때문이다.
7.1 vs. RDBMS, MongoDB, HBase: 아키텍처 및 데이터 모델의 근본적 차이
7.1.1 vs. 관계형 데이터베이스 (RDBMS)
RDBMS(예: MySQL, PostgreSQL)와의 비교는 카산드라가 왜 등장했는지를 가장 잘 보여준다.
- 아키텍처 및 확장성: RDBMS는 전통적으로 단일 서버의 성능을 높이는 수직적 확장(Scale-up)에 의존하는 중앙 집중형 Master-Slave 구조를 가진다. 반면, 카산드라는 여러 대의 범용 서버를 추가하여 시스템 전체의 성능을 높이는 수평적 확장(Scale-out)에 최적화된 분산형 Masterless 구조를 채택했다.3
- 데이터 모델 및 스키마: RDBMS는 정규화를 통해 데이터 중복을 최소화하고, 고정된 스키마와 관계(JOIN)를 통해 데이터 무결성을 강제한다. 카산드라는 읽기 성능을 위해 비정규화를 적극 권장하며, 스키마 변경이 자유로운 유연한 와이드 컬럼 모델을 사용한다.10
- 일관성 및 트랜잭션: RDBMS는 ACID(원자성, 일관성, 고립성, 지속성) 트랜잭션을 통해 강력한 일관성을 보장한다. 카산드라는 BASE(Basically Available, Soft state, Eventually consistent) 철학에 기반한 결과적 일관성을 기본으로 하며, 필요에 따라 일관성 수준을 조정할 수 있다.31
7.1.2 vs. MongoDB
MongoDB는 문서 지향(Document-Oriented) NoSQL 데이터베이스의 대표 주자로, 카산드라와는 다른 접근 방식을 취한다.
- 아키텍처: MongoDB는 복제본 세트(Replica Set)라는 Master-Slave 구조를 기본으로 한다. 하나의 프라이머리 노드가 쓰기 작업을 처리하고, 이를 세컨더리 노드들이 비동기적으로 복제한다. 이는 카산드라의 모든 노드가 쓰기 작업을 처리할 수 있는 Masterless 구조와 대조된다.42
- 데이터 모델: MongoDB는 데이터를 유연한 JSON과 유사한 BSON(Binary JSON) 문서 형태로 저장한다. 중첩된 문서와 배열을 지원하여 복잡한 계층 구조의 데이터를 직관적으로 표현할 수 있다. 이는 카산드라의 테이블 기반 와이드 컬럼 모델과 구별된다.6
- 쿼리 유연성: MongoDB는 풍부한 쿼리 언어, 강력한 집계 파이프라인(Aggregation Framework), 그리고 다양한 종류의 보조 인덱스를 지원하여 개발자에게 높은 유연성을 제공한다. 반면, 카산드라는 파티션 키 기반의 단순 조회에 최적화되어 있으며, 쿼리 유연성은 상대적으로 낮다.42
7.1.3 vs. HBase
HBase 역시 Google Bigtable의 영향을 받은 와이드 컬럼 스토어이지만, 아키텍처적으로 카산드라와 중요한 차이점을 보인다.
- 아키텍처 및 의존성: HBase는 독립적으로 동작하는 카산드라와 달리, Hadoop 생태계에 깊이 의존한다. 데이터 저장을 위해 HDFS(Hadoop Distributed File System)를, 클러스터 코디네이션을 위해 Zookeeper를, 리소스 관리를 위해 YARN을 필요로 하는 Master-Slave 구조를 가진다.93 이는 HBase의 설치와 운영을 더 복잡하게 만드는 요인이다.
- 일관성 (CAP 이론): HBase는 Zookeeper를 통해 강력한 일관성을 보장하는 CP(Consistency, Partition Tolerance) 시스템으로 분류된다. 반면, 카산드라는 가용성을 우선시하는 AP 시스템이다.93
- 성능 특성: 일반적으로 HBase는 대규모 데이터셋에 대한 랜덤 읽기 성능에 강점을 보이며, 카산드라는 극단적인 쓰기 처리량에 더 최적화되어 있다.93
- 사용 편의성: 카산드라는 SQL과 유사한 CQL을 제공하여 상대적으로 배우기 쉬운 반면, HBase는 자체 Java API를 사용하거나 SQL 인터페이스를 위해 Apache Phoenix와 같은 추가적인 계층을 필요로 한다.6
7.1.4 표 3: 주요 NoSQL 및 분산 SQL 데이터베이스 아키텍처 비교
| 구분 | Cassandra | MongoDB | HBase | CockroachDB | ScyllaDB |
|---|---|---|---|---|---|
| 패러다임 | Wide-Column | Document | Wide-Column | Distributed SQL | Wide-Column (C++) |
| 아키텍처 | Masterless (P2P) | Master-Slave | Master-Slave (Hadoop) | Symmetric (P2P) | Masterless (Shard-per-core) |
| CAP 분류 | AP (Tunable) | CP (Default) | CP | CP | AP (Tunable) |
| 일관성 모델 | 결과적/조정 가능 | 강력함 (기본) | 강력함 | 직렬화 가능 ACID | 결과적/조정 가능 |
| 트랜잭션 | LWT (제한적) | Multi-document ACID | 제한적 | 분산 ACID | LWT (개선됨) |
| 주요 강점 | 쓰기 처리량/가용성 | 개발 유연성/쿼리 | 대용량 랜덤 읽기 | 분산 트랜잭션 | 극한의 성능 |
이 표는 복잡한 분산 데이터베이스 시장의 지형도를 한눈에 보여준다. 각 시스템의 핵심적인 아키텍처 철학과 그로 인해 발생하는 특성들을 명확하게 대비시켜, 독자가 자신의 요구사항에 맞는 기술을 전략적으로 평가하고 선택하는 데 필요한 핵심 정보를 제공한다.
7.2 vs. ScyllaDB, CockroachDB: 성능, 트랜잭션, 일관성 모델 비교
7.2.1 vs. ScyllaDB
ScyllaDB는 ’더 빠른 카산드라’를 목표로 등장한 데이터베이스로, 카산드라와 API 수준에서 호환되지만 내부 구현은 완전히 다르다.
- 아키텍처 및 언어: 가장 큰 차이점은 ScyllaDB가 JVM 기반의 Java 대신 C++로 완전히 새로 작성되었다는 점이다.4 이를 통해 JVM의 가비지 컬렉션(GC)으로 인한 예측 불가능한 성능 저하 문제를 원천적으로 제거했다. 또한, ’Shard-per-core’라는 독자적인 아키텍처를 채택하여, 각 CPU 코어가 독립적인 스레드, 메모리, 디스크 I/O 큐를 가지고 데이터를 처리한다. 이는 하드웨어의 성능을 거의 100% 활용하여 멀티코어 환경에서 최고의 성능을 이끌어내기 위한 설계이다.4
- 성능: 이러한 아키텍처 차이로 인해, 동일한 하드웨어에서 ScyllaDB는 일반적으로 카산드라보다 훨씬 낮은 지연 시간과 수 배에서 수십 배 높은 처리량을 보인다.96
- 기능 및 발전: ScyllaDB는 카산드라와의 호환성을 유지하면서도, 자동 튜닝, 워크로드 우선순위 지정, 향상된 컴팩션 전략(ICS) 등 운영 편의성과 성능을 높이는 독자적인 기능들을 더 빠르게 도입하고 있다.4
7.2.2 vs. CockroachDB
CockroachDB는 카산드라와 같은 NoSQL이 아닌, 분산 환경에서 RDBMS의 장점을 제공하려는 ‘분산 SQL(Distributed SQL)’ 또는 ‘NewSQL’ 데이터베이스이다.
- 패러다임 및 일관성: CockroachDB의 핵심 설계 목표는 지리적으로 분산된 환경에서도 강력한 일관성과 ACID 트랜잭션을 보장하는 것이다.99 이를 위해 Paxos/Raft와 같은 합의 알고리즘을 기반으로 동작하며, CAP 이론상 CP 시스템에 해당한다. 이는 가용성을 최우선으로 하는 카산드라의 AP 철학과 정면으로 배치된다.
- 트랜잭션: CockroachDB는 여러 행과 테이블에 걸친 분산 ACID 트랜잭션을 완벽하게 지원한다. 반면, 카산드라의 트랜잭션 지원은 단일 파티션 내에서의 조건부 업데이트를 위한 ’경량 트랜잭션(Lightweight Transactions, LWT)’으로 매우 제한적이다.32
- 쿼리 언어: CockroachDB는 PostgreSQL과 와이어 프로토콜 수준에서 호환되는 표준 SQL을 지원한다. 이는 JOIN, 서브쿼리, 외래 키 등 RDBMS 개발자에게 익숙한 모든 기능을 사용할 수 있음을 의미한다.99 카산드라의 CQL은 이와 비교해 기능이 매우 제한적이다.
8. 최신 동향 및 미래 전망
아파치 카산드라는 지난 10여 년간 대규모 분산 데이터베이스의 대명사로 자리매김해왔지만, 기술 생태계의 빠른 변화에 발맞춰 끊임없이 진화하고 있다. 현재 카산드라의 발전 방향은 크게 ’운영 자동화’와 ’AI 워크로드 지원’이라는 두 가지 축을 중심으로 전개되고 있다. 이는 클라우드 네이티브 환경으로의 전환과 인공지능 시대의 새로운 데이터 패러다임이라는 거대한 기술 트렌드에 적극적으로 부응하려는 전략적 움직임으로 해석된다.
8.1 쿠버네티스 환경에서의 카산드라 운영: K8ssandra Operator
과거 카산드라는 강력한 성능에도 불구하고 복잡한 설치, 구성, 그리고 수동적인 관리(repair 등)로 인해 운영이 어렵다는 인식이 있었다. 그러나 애플리케이션 배포 및 운영의 중심이 쿠버네티스로 이동하면서, 카산드라와 같은 상태 저장(stateful) 애플리케이션도 쿠버네티스 위에서 ‘선언적으로’ 관리하려는 요구가 커졌다.
K8ssandra는 이러한 요구에 대한 카산드라 커뮤니티의 공식적인 답변이다. K8ssandra는 쿠버네티스에서 카산드라를 프로덕션 수준으로 운영하기 위한 모든 구성 요소를 통합한 오픈소스 플랫폼이다.100
K8ssandra의 핵심은 Cass Operator라는 쿠버네티스 오퍼레이터이다.100 오퍼레이터는 쿠버네티스의 커스텀 리소스(Custom Resource)를 통해 특정 애플리케이션(이 경우 카산드라)의 배포, 스케일링, 장애 복구, 업그레이드와 같은 복잡한 운영 작업을 자동화하는 소프트웨어이다. 개발자나 운영자는 복잡한 절차를 직접 수행하는 대신, “3개의 노드로 구성된 데이터센터를 만들어줘“와 같은 원하는 상태를 YAML 파일에 선언하기만 하면, Cass Operator가 나머지 모든 작업을 자동으로 처리해준다.100
K8ssandra는 Cass Operator를 기반으로, 다음과 같은 필수 운영 도구들을 하나의 패키지로 통합하여 제공한다 100:
- 모니터링: Prometheus 및 Grafana를 통한 지표 수집 및 시각화
- 복구(Repair): Reaper를 이용한 자동화된 안티-엔트로피 복구 스케줄링
- 백업/복원: Medusa를 이용한 클라우드 스토리지(S3 등) 기반의 스냅샷 백업 및 복원
- API 게이트웨이: Stargate를 통해 CQL 외에 REST, GraphQL 등 다양한 API 인터페이스 제공
K8ssandra의 등장은 카산드라 운영의 패러다임을 바꾸고 있다. 복잡한 수동 작업을 자동화하고 클라우드 네이티브 환경에 완벽하게 통합함으로써, 개발자들이 인프라 관리의 부담에서 벗어나 애플리케이션 개발에 더 집중할 수 있도록 돕는다.
8.2 카산드라 5.0의 신기능과 AI/ML 워크로드 지원
2024년 9월에 공식 릴리즈된 Cassandra 5.0은 AI 및 머신러닝 시대의 새로운 데이터 요구사항에 대응하기 위한 혁신적인 기능들을 대거 탑재한 중요한 이정표이다.10
- Vector Search: Cassandra 5.0의 가장 핵심적인 신기능으로, AI 모델이 생성하는 고차원 벡터 임베딩(vector embedding)을 저장하고, 그 유사도를 기반으로 데이터를 검색하는 ’벡터 검색’을 네이티브로 지원한다.72 이는 근사 최근접 이웃(Approximate Nearest Neighbor, ANN) 알고리즘을 기반으로 하며, Storage Attached Index(SAI)를 통해 구현된다.106 이 기능 덕분에 카산드라는 이제 단순한 데이터 저장소를 넘어, 추천 시스템, 이미지/음성/텍스트 검색, 이상 탐지 등 다양한 AI 애플리케이션의 핵심 백엔드 데이터베이스로 직접 활용될 수 있다.
- Storage Attached Indexes (SAI): 기존의 보조 인덱스(Secondary Index)가 가진 성능 및 확장성 문제를 해결하기 위해 설계된 새로운 인덱싱 메커니즘이다.72 SAI는 인덱스 데이터를 SSTable에 직접 첨부하여 디스크 공간 효율성을 높이고, 다양한 유형의 쿼리(정확한 일치, 범위, 전문 검색 등)를 높은 성능으로 지원한다.
- Unified Compaction Strategy (UCS): 기존의 STCS와 LCS 컴팩션 전략의 장점을 결합한 새로운 하이브리드 전략이다.72 운영자는 단일 전략 내에서 파라미터 조정을 통해 워크로드 특성에 맞게 컴팩션 동작을 미세 조정할 수 있어, 운영의 복잡성을 크게 줄여준다.
- Trie Memtables and SSTables: 스토리지 엔진의 핵심 자료 구조인 멤테이블과 SSTable의 인덱스를 B-Tree에서 Trie 구조로 변경하여, 메모리 사용량을 줄이고, 쓰기 처리량을 향상시키며, 특히 넓은 파티션(wide partition)에 대한 지원을 강화했다.72
- JDK 17 지원: 최신 LTS(Long-Term Support) 버전인 Java 17을 지원하게 됨으로써, ZGC(Z Garbage Collector)와 같은 최신 저지연 GC를 활용할 수 있게 되었다. 이는 대용량 힙 환경에서도 예측 가능하고 안정적인 성능을 제공하는 데 기여한다.72
이러한 기능들은 카산드라가 과거의 명성에 안주하지 않고, 미래 기술 스택의 핵심 구성 요소로 남기 위한 능동적인 변화를 추구하고 있음을 명확히 보여준다.
8.3 CEP(Cassandra Enhancement Proposals)를 통해 본 미래 방향성
CEP는 카산드라 커뮤니티가 새로운 주요 기능을 제안, 토론하고, 개발 방향을 결정하는 공식적인 프로세스이다.107 현재 논의되거나 최근에 구현된 CEP들을 살펴보면 카산드라의 미래를 엿볼 수 있다.
- Auto Repair (CEP-37): 운영자의 가장 큰 부담 중 하나였던 repair 작업을 컴팩션처럼 시스템이 자동으로, 지능적으로 수행하도록 만드는 기능이다.108 클러스터의 부하 상태를 감지하여 repair 강도를 조절하고, 디스크 공간과 같은 가드레일을 통해 안정성을 확보하는 등, 운영 자동화의 정점을 목표로 한다.
- ACID 트랜잭션 및 일관성 강화: 2024년 사용자 설문조사에서 ACID 트랜잭션에 대한 요구가 높게 나타난 만큼, 커뮤니티 내에서도 일관성 모델을 강화하려는 논의가 지속되고 있다.109 과거에 제안되었던 범용 트랜잭션 지원이나 Pluggable Storage Engine(다양한 스토리지 엔진을 교체 가능하게 하는 기능)과 같은 CEP들은 카산드라가 전통적인 NoSQL의 한계를 넘어 더 넓은 영역의 워크로드를 포용하려는 장기적인 비전을 가지고 있음을 시사한다.110
결론적으로, 카산드라의 미래 방향성은 명확하다. K8ssandra를 통해 ’어디서든 쉽게 운영’할 수 있는 클라우드 네이티브 데이터베이스로 거듭나고 있으며, Vector Search와 같은 AI 지원 기능을 통해 ’무엇이든 저장하고 지능적으로 검색’할 수 있는 차세대 데이터 플랫폼으로 진화하고 있다.
9. 결론: 카산드라의 전략적 활용 방안
아파치 카산드라는 지난 십수 년간 대규모 분산 데이터 처리 분야에서 그 가치를 입증해 온 강력하고 성숙한 데이터베이스이다. 그 설계 철학은 명확하다: 극단적인 수준의 확장성과 상시 가용성을 확보하기 위해 전통적인 데이터베이스의 제약(강력한 일관성, JOIN, 정규화)을 과감히 포기하는 것이다. 이러한 명확한 트레이드오프는 카산드라를 모든 문제에 대한 만병통치약이 아닌, 특정 유형의 문제에 대한 최적의 해법으로 만든다.
9.1 핵심 강점과 약점 요약
강점:
- 선형적 확장성: 클러스터에 노드를 추가하는 것만으로 읽기/쓰기 처리량이 예측 가능하게 증가하여, 페타바이트 규모의 데이터와 초당 수백만 건의 요청을 처리할 수 있다.4
- 고가용성 및 내결함성: 마스터 없는 P2P 아키텍처와 데이터 복제 메커니즘을 통해 단일 장애 지점이 없으며, 개별 노드, 랙, 심지어 데이터센터 전체의 장애에도 서비스 중단 없이 동작한다.3
- 뛰어난 쓰기 성능: LSM-Tree 기반 스토리지 엔진은 모든 쓰기 작업을 순차 I/O로 처리하여 매우 높은 쓰기 처리량을 제공한다.90
- 지리적 분산: 다중 데이터센터 복제를 네이티브로 지원하여, 전 세계 사용자를 대상으로 하는 글로벌 서비스에서 데이터를 사용자 가까이에 배치함으로써 낮은 지연 시간을 실현할 수 있다.5
- 유연성: 조정 가능한 일관성 모델을 통해 애플리케이션의 요구사항에 따라 성능과 데이터 정합성 사이의 균형을 쿼리 단위로 선택할 수 있으며, 스키마 변경이 자유롭다.4
약점:
- 제한된 쿼리 능력: JOIN, 복잡한 집계(aggregation), 서브쿼리 등을 지원하지 않아 분석적인 쿼리에는 부적합하다.3
- 데이터 모델링의 복잡성: ’쿼리 기반 설계’와 ’비정규화’라는, RDBMS와는 다른 패러다임에 대한 깊은 이해가 필요하다. 잘못된 데이터 모델링은 심각한 성능 문제로 이어진다.39
- 결과적 일관성: 강력한 일관성을 기본으로 요구하는 금융 거래나 재고 관리 시스템과 같은 일부 애플리케이션에는 부적합할 수 있다.
- 운영의 복잡성: 툼스톤, 대용량 파티션, 컴팩션 튜닝 등 성능 유지를 위해 고려해야 할 내부적인 요소들이 많아 운영에 전문성이 요구된다 (단, K8ssandra와 같은 도구들이 이를 완화하고 있다).62
9.2 적합한 사용 사례 제시
이러한 강점과 약점을 고려할 때, 카산드라는 다음과 같은 특성을 가진 사용 사례에서 그 진가를 발휘한다.
- 대규모 쓰기 중심 워크로드: 초당 수많은 데이터가 지속적으로 유입되는 시나리오에 이상적이다.
- 사례: IoT 센서 데이터 수집, 실시간 로그 데이터 저장, 사용자 활동 추적, 메시징 시스템.113 Discord는 수조 개의 메시지를 저장하고 관리하기 위해 카산드라를 사용한다.1
- 지리적으로 분산된 글로벌 서비스: 전 세계에 분산된 데이터센터를 통해 모든 사용자에게 빠르고 안정적인 서비스를 제공해야 하는 경우.
- 사례: 소셜 미디어 피드, 스트리밍 서비스의 사용자 프로필 및 시청 기록 관리, 글로벌 전자상거래 플랫폼.5 Instagram은 전 세계 사용자의 데이터를 각 지역 데이터센터에 복제하여 빠른 서비스를 제공한다.115
- 제로 다운타임이 필수적인 ‘Always-On’ 시스템: 단 한 순간의 서비스 중단도 허용되지 않는 미션 크리티컬 애플리케이션.
- 사례: 사기 탐지 시스템, 실시간 개인화 및 추천 엔진, 규정 준수를 위한 감사 로깅.3 Netflix는 스트리밍 데이터 처리와 감사 로깅에 카산드라를 활용하여 제로 다운타임을 달성한다.115
- 시계열 데이터 관리: TimeWindowCompactionStrategy(TWCS)와 Time-To-Live(TTL) 기능을 결합하여 대규모 시계열 데이터를 효율적으로 저장하고, 오래된 데이터를 자동으로 폐기하는 데 매우 효과적이다.113
- AI/ML 애플리케이션 백엔드: Cassandra 5.0부터 네이티브로 지원되는 Vector Search 기능을 활용하여, 대규모 벡터 임베딩을 저장하고 유사성 기반 검색을 수행하는 AI 기반 추천 시스템, 이미지 검색, 자연어 처리 애플리케이션의 백엔드로 활용될 수 있다.106
결론적으로, 아파치 카산드라는 RDBMS를 대체하는 범용 데이터베이스가 아니다. 대신, 데이터의 규모가 기존 시스템의 한계를 넘어서고, 중단 없는 서비스와 빠른 쓰기 성능이 비즈니스의 성패를 좌우하는 특정 영역에서 타의 추종을 불허하는 강력한 솔루션이다. 카산드라를 성공적으로 도입하기 위해서는 그 아키텍처적 트레이드오프를 명확히 이해하고, ’쿼리 기반 설계’라는 원칙에 따라 데이터 모델을 신중하게 설계하는 것이 무엇보다 중요하다.아파치 카산드라: 분산 아키텍처, 데이터 모델링, 그리고 운영 심층 분석
10. 서론: 아파치 카산드라 개요
아파치 카산드라(Apache Cassandra)는 대규모의 데이터를 효율적으로 처리하도록 설계된 오픈소스 분산형 NoSQL 데이터베이스이다.1 관계형 데이터베이스(RDBMS)가 직면한 성능과 확장성의 한계를 극복하기 위해 탄생했으며, 높은 확장성(Scalability), 고가용성(High Availability), 내결함성(Fault Tolerance), 그리고 조정 가능한 일관성(Tunable Consistency)을 핵심 특징으로 한다.1 이러한 특성 덕분에 카산드라는 구조적이거나 비구조적인 데이터를 막론하고 페타바이트(PB) 규모의 데이터셋을 처리해야 하는 미션 크리티컬 애플리케이션에 최적화된 솔루션으로 자리 잡았다.1
10.1 NoSQL 분산 데이터베이스로서의 카산드라 정의 및 핵심 특성
카산드라는 데이터를 전통적인 행과 열의 테이블 구조가 아닌, 와이드 컬럼 스토어(Wide Column Store) 모델로 저장한다.3 이는 고정된 스키마 없이 각 행이 동적으로 다른 수의 컬럼을 가질 수 있음을 의미하며, 애플리케이션의 변화에 유연하게 대응할 수 있는 기반을 제공한다.1
카산드라의 가장 두드러진 아키텍처적 특징은 중앙 제어 지점이 없는 완전한 분산 시스템이라는 점이다.3 모든 노드가 동등한 역할을 수행하는 ‘마스터 없는(Masterless)’ 또는 ‘P2P(Peer-to-Peer)’ 구조를 채택하여 단일 장애 지점(Single Point of Failure, SPOF)을 원천적으로 제거했다.1 데이터는 클러스터 내 여러 노드에 자동으로 복제되어 일부 노드에 장애가 발생하더라도 서비스 중단 없이 운영이 가능하다.3 또한, 클러스터에 노드를 추가하는 것만으로 읽기 및 쓰기 처리량이 선형적으로 증가하는 수평적 확장성(Horizontal Scalability)을 제공하여, 예측 불가능한 대규모 트래픽 증가에도 탄력적으로 대응할 수 있다.2
10.2 개발 역사와 설계 철학: Dynamo와 Bigtable의 융합
카산드라의 탄생은 2008년, 급격하게 성장하던 페이스북의 기술적 난제를 해결하기 위한 내부 프로젝트에서 시작되었다.1 당시 페이스북은 기존 RDBMS의 수직적 확장 방식으로는 늘어나는 데이터를 감당할 수 없는 한계에 직면했고, 이를 해결하기 위해 엔지니어 Avinash Lakshman과 Prashant Malik이 새로운 분산 데이터베이스 개발에 착수했다.1 흥미롭게도 Avinash Lakshman은 Amazon Dynamo의 설계자 중 한 명으로, 그의 경험은 카산드라의 핵심 설계 철학에 지대한 영향을 미쳤다.1
카산드라의 아키텍처는 당대 가장 성공적인 두 분산 시스템 모델인 Amazon Dynamo와 Google Bigtable의 장점을 실용적으로 융합한 결과물이다. 이는 특정 이론에 얽매이기보다, 실제 하이퍼스케일 환경의 문제를 해결하기 위한 최적의 엔지니어링적 선택이었다.1
- Amazon Dynamo의 영향: Dynamo로부터 ’상시 가용성(Always-On Availability)’을 위한 핵심 아키텍처를 계승했다. SPOF가 없는 P2P 아키텍처, 데이터 복제를 통한 고가용성, 분산 해시 테이블(DHT) 개념에 기반한 일관된 해싱(Consistent Hashing)을 통한 데이터 분산, 그리고 결과적 일관성(Eventual Consistency) 모델이 그것이다.1 이는 시스템의 일부에 장애가 발생하더라도 전체 서비스가 중단되지 않도록 하는 데 초점을 맞춘 설계이다.
- Google Bigtable의 영향: Bigtable로부터는 유연하고 효율적인 데이터 저장 구조를 채택했다. 고정된 스키마 없이 동적으로 열을 추가할 수 있는 열 기반 저장소(Columnar Storage) 모델은 빠르게 변화하는 애플리케이션 요구사항에 민첩하게 대응하고, 대규모 데이터셋을 효율적으로 저장 및 검색하는 데 유리하다.1
이처럼 카산드라는 Dynamo의 강력한 분산 및 복제 기술과 Bigtable의 유연한 데이터 모델을 결합하여, 확장성, 가용성, 성능이라는 세 마리 토끼를 모두 잡으려는 야심 찬 목표를 가지고 설계되었다. 2009년 아파치 소프트웨어 재단의 인큐베이터 프로젝트로 기증된 이후, 2010년에는 최상위 프로젝트(Top-Level Project, TLP)로 승격되며 전 세계적인 오픈소스 커뮤니티의 기여를 통해 빠르게 발전해왔다.1
11. 분산 아키텍처 심층 분석
카산드라의 아키텍처는 ’완전한 분산화’와 ’장애 감내’라는 철학을 구현하기 위한 유기적인 시스템이다. 마스터 없는 구조는 가십 프로토콜을 필수로 만들고, 가십 프로토콜은 스니치와 결합하여 단순한 멤버십 관리를 넘어 ’성능 인식 라우팅’이라는 고차원적인 기능을 수행한다. 이 구성 요소들은 각각 독립적으로 동작하는 것이 아니라, 중앙 제어 없이도 안정적이고 효율적으로 시스템을 운영하기 위한 연쇄적인 해법으로 긴밀하게 연결되어 있다.
11.1 마스터 없는 P2P 모델과 링(Ring) 구조의 원리
카산드라 아키텍처의 가장 근본적인 특징은 특정 노드가 전체 클러스터를 제어하는 마스터(Master) 역할을 하지 않는다는 점이다. 대신, 클러스터를 구성하는 모든 노드가 동등한 지위와 역할을 갖는 ‘마스터 없는(Masterless)’ 또는 ‘P2P(Peer-to-Peer)’ 모델을 채택했다.1
이러한 설계는 중앙 제어 지점의 부재를 의미하며, 이는 곧 시스템 전체를 마비시킬 수 있는 단일 장애 지점(SPOF)이 원천적으로 존재하지 않음을 보장한다.1 클라이언트의 읽기 또는 쓰기 요청은 클러스터 내 어떤 노드에든 전달될 수 있으며, 요청을 받은 노드는 해당 요청의 코디네이터(Coordinator) 역할을 수행하여 데이터를 담당하는 실제 노드들과 통신한다.2
클러스터에 속한 노드들은 물리적으로 분산되어 있지만, 논리적으로는 하나의 ‘링(Ring)’ 구조를 형성한다.7 이는 분산 해시 테이블(DHT) 구현체인 Chord 알고리즘과 유사한 개념으로, 데이터가 클러스터 전체에 어떻게 분산될지를 결정하는 기준이 된다.7 데이터는 각 행(row)을 식별하는 고유 키인 파티션 키(Partition Key)를 해시 함수에 통과시켜 얻은 숫자 값, 즉 ’토큰(Token)’을 기준으로 링 상의 특정 위치에 매핑된다. 각 노드는 이 링의 특정 토큰 범위를 담당하게 되며, 자신의 범위에 해당하는 토큰을 가진 데이터를 저장하고 관리할 책임을 진다.2 이 방식을 통해 데이터는 클러스터 전체에 자동으로 분산된다.
11.2 가십 프로토콜(Gossip Protocol)을 통한 멤버십 및 장애 감지
마스터 노드가 없는 P2P 환경에서는 “누가 클러스터의 멤버이며, 각 노드의 현재 상태는 어떠한가?“라는 정보를 모든 노드가 공유해야 한다. 카산드라는 이 문제를 해결하기 위해 ’가십 프로토콜(Gossip Protocol)’이라는 P2P 통신 메커니즘을 사용한다.8
’전염병 프로토콜(Epidemic Protocol)’이라고도 불리는 이 방식은, 각 노드가 주기적으로(보통 1초마다) 클러스터 내의 다른 임의의 노드 몇 개와 자신이 알고 있는 상태 정보를 교환하는 방식으로 동작한다.15 이 정보에는 노드의 가용성(UP/DOWN), 부하 상태, 스키마 버전 등 클러스터 운영에 필수적인 메타데이터가 포함된다.10 정보는 마치 소문이나 전염병처럼 노드에서 노드로 빠르게 전파되어, 결국 모든 노드가 짧은 시간 내에 클러스터 전체의 상태에 대한 거의 일관된 그림을 갖게 된다.15
가십 프로토콜은 단순한 멤버십 관리를 넘어 장애 감지에도 핵심적인 역할을 한다. 카산드라는 Phi Accrual Failure Detector라는 정교한 알고리즘을 사용하여 노드 간 가십 메시지의 도착 간격을 통계적으로 분석하고, 특정 노드가 다운되었을 확률을 계산한다.10 이를 통해 일시적인 네트워크 지연과 실제 노드 장애를 구분하여 불필요한 장애 조치를 방지하고 시스템의 안정성을 높인다.
또한, 교환되는 가십 메시지에는 버전 정보가 포함되어 있어, 노드들은 항상 가장 최신의 상태 정보만을 신뢰하게 된다. 이는 벡터 클록(Vector Clock)과 유사한 메커니즘을 통해 구현되며, 네트워크 분할과 같은 상황에서 발생할 수 있는 정보의 충돌을 방지한다.13
11.2.1 시드 노드 (Seed Nodes)
완전한 P2P 환경에서 새로운 노드가 클러스터에 참여하려면, 기존 멤버 중 누구에게라도 말을 걸어 클러스터 정보를 얻어야 한다. ’시드 노드(Seed Node)’는 바로 이 진입점 역할을 하는 노드들이다.10 시드 노드는 클러스터를 부트스트랩하고, 새로운 노드가 클러스터의 멤버십 정보를 얻기 위해 가장 먼저 접촉하는 공식적인 연락 지점이다. 또한, 모든 노드가 시드 노드와 주기적으로 가십 통신을 시도함으로써, 일시적인 네트워크 문제로 클러스터가 여러 개로 분리되는 ‘분할뇌(Split-brain)’ 현상을 방지하는 데 도움을 준다.10 시드 노드는 특별한 역할을 하지만 마스터 노드는 아니며, 일단 클러스터 상태 정보가 전파되고 나면 다른 노드와 동등한 지위를 갖는다.
11.3 스니치(Snitch)를 이용한 네트워크 토폴로지 인식 및 요청 라우팅 최적화
카산드라 클러스터는 종종 여러 데이터센터와 랙(Rack)에 걸쳐 지리적으로 분산되어 운영된다. 고가용성을 위해서는 데이터의 복제본을 서로 다른 물리적 위치(예: 다른 랙, 다른 데이터센터)에 저장하여 랙 전원이나 네트워크 스위치 고장과 같은 공통 장애 지점의 영향을 피해야 한다.18 또한, 요청을 처리할 때 네트워크적으로 가장 가까운 노드에서 데이터를 읽어오는 것이 지연 시간을 줄이는 데 유리하다.
’스니치(Snitch)’는 이러한 요구사항을 충족시키기 위해 클러스터의 네트워크 토폴로지 정보를 카산드라에 제공하는 핵심 구성 요소이다.19 스니치는 각 노드의 IP 주소를 기반으로 해당 노드가 어떤 데이터센터와 랙에 속하는지를 판단하고, 이 정보를 다른 노드들과 공유한다.19 복제 전략(NetworkTopologyStrategy)은 스니치가 제공하는 토폴로지 정보를 활용하여 데이터 복제본을 의도적으로 다른 랙과 데이터센터에 분산 배치한다.13
11.3.1 SimpleSnitch와 GossipingPropertyFileSnitch의 차이점
카산드라는 다양한 환경에 맞는 여러 종류의 스니치를 제공한다.19
-
SimpleSnitch: 가장 기본적인 스니치로, 네트워크 토폴로지를 전혀 인식하지 못한다. 모든 노드를 단일 데이터센터의 단일 랙에 있는 것으로 간주한다.21 따라서 이 스니치는 개발 및 테스트 환경과 같이 단일 노드 또는 단일 랙으로 구성된 클러스터에서만 사용해야 하며, 프로덕션 환경에는 절대적으로 부적합하다.19
-
GossipingPropertyFileSnitch: 프로덕션 환경에서 가장 널리 권장되는 스니치이다.19 이 방식은 각 노드의
cassandra-rackdc.properties라는 설정 파일에 해당 노드가 속한 데이터센터와 랙 정보를 명시적으로 기입하는 방식이다.19 각 노드는 이 정보를 가십 프로토콜을 통해 클러스터 내 다른 모든 노드에게 전파한다. 이를 통해 모든 노드가 중앙의 설정 파일 동기화 없이도 전체 클러스터의 토폴로지 정보를 최신 상태로 유지할 수 있다.19
이 외에도 AWS, Google Cloud 등 특정 클라우드 환경의 토폴로지 정보를 자동으로 감지하는 Ec2Snitch, GoogleCloudSnitch 등이 있어 인프라 환경에 맞춰 최적의 스니치를 선택할 수 있다.19
11.3.2 동적 스니칭 (Dynamic Snitching)
정적인 토폴로지 정보만으로는 노드의 일시적인 과부하, 네트워크 혼잡 등 실시간 성능 변화에 대응하기 어렵다. ’동적 스니칭(Dynamic Snitching)’은 이러한 한계를 극복하기 위한 기능이다.19 기본적으로 카산드라는 사용자가 설정한 기본 스니치(예: GossipingPropertyFileSnitch)를 DynamicEndpointSnitch로 감싸서 동작시킨다.19
동적 스니치는 실제 읽기 요청들의 성능(지연 시간)을 지속적으로 추적하고 점수를 매긴다. 그리고 읽기 요청을 보낼 때, 토폴로지상 가깝더라도 현재 성능이 저하된 노드는 피하고 가장 응답이 빠른 노드를 우선적으로 선택한다.19 이는 정적인 네트워크 토폴로지 정보 위에 동적인 성능 데이터를 덧씌워, 클러스터가 실시간 부하 변화에 지능적으로 적응하고 최적의 성능을 유지하도록 돕는 고도화된 라우팅 메커니즘이다.
12. 데이터 분산, 복제, 그리고 일관성
카산드라는 대규모 데이터를 안정적으로 관리하기 위해 정교한 데이터 분산, 복제, 그리고 일관성 유지 메커니즘을 갖추고 있다. 이 메커니즘들은 시스템의 확장성, 고가용성, 그리고 데이터의 신뢰성을 보장하는 핵심 요소로 작용한다. 특히, CAP 이론의 제약을 정적인 한계로 받아들이지 않고, ’조정 가능한 일관성’이라는 유연한 해법을 통해 애플리케이션의 다양한 요구사항에 동적으로 대응하는 실용적인 접근법을 취한다.
12.1 파티셔닝: 일관된 해싱(Consistent Hashing)과 가상 노드(vnodes)
카산드라의 수평적 확장성은 데이터를 여러 노드에 효과적으로 분산시키는 파티셔닝(Partitioning) 기술에 기반한다. 이를 위해 ’일관된 해싱(Consistent Hashing)’이라는 알고리즘을 사용한다.13
전통적인 해싱 방식은 해시 값을 서버의 수로 나눈 나머지를 사용하여 데이터를 분배한다. 이 방식의 문제점은 서버(노드) 수가 변경될 때 거의 모든 데이터가 재배치되어야 한다는 것이다. 이는 대규모 데이터 이동을 유발하여 시스템에 막대한 부하를 준다.24
일관된 해싱은 이러한 문제를 해결한다. 먼저, 매우 큰 범위의 숫자 값(예: −263 에서 263−1)으로 구성된 논리적인 ’토큰 링(Token Ring)’을 상상한다.2 데이터의 파티션 키는 해시 함수를 통해 이 링 위의 특정 위치를 나타내는 ‘토큰’ 값으로 변환된다. 동시에, 클러스터의 각 노드에도 하나 이상의 토큰 값이 할당되어 링 위에 배치된다.2 데이터는 자신의 토큰 값으로부터 링을 시계 방향으로 따라가다 처음 만나는 노드에 저장된다. 이 방식의 가장 큰 장점은 노드가 추가되거나 제거될 때, 영향을 받는 데이터가 해당 노드의 이웃 노드들에 국한된다는 점이다. 즉, 전체 데이터의 극히 일부만 재배치하면 되므로 클러스터의 확장이 매우 효율적이다.13
12.1.1 가상 노드 (vnodes)
초기 카산드라 버전에서는 각 물리 노드가 링에서 단 하나의 큰 토큰 범위를 담당했다. 이 방식은 노드 추가 시 특정 노드에서만 대량의 데이터를 이동시켜야 하는 부담과 데이터 분포의 불균형을 야기할 수 있었다.13
이 문제를 해결하기 위해 도입된 것이 ‘가상 노드(virtual nodes, vnodes)’ 개념이다.13 vnodes는 하나의 물리 노드가 링 상에서 여러 개의 작은 토큰 범위를 담당하도록 하는 기술이다. 예를 들어, 256개의 vnode를 사용하도록 설정하면, 각 물리 노드는 링 전체에 흩어져 있는 256개의 작은 데이터 조각들을 책임지게 된다.
vnodes의 도입은 다음과 같은 중요한 이점을 가져왔다 13:
- 탄력적 확장성: 새로운 노드가 클러스터에 추가될 때, 이 노드는 링 전체에 흩어져 있는 여러 기존 노드들로부터 조금씩 데이터를 가져온다. 데이터 이동의 부담이 특정 노드에 집중되지 않고 클러스터 전체에 분산되므로, 노드 추가 및 제거 작업이 훨씬 원활하고 빨라진다.
- 균등한 데이터 분배: 데이터와 부하가 클러스터 전체에 더 균등하게 분산되어 ‘핫스팟(hotspot)’ 발생 가능성을 줄인다.
- 장애 복구 향상: 특정 노드에 장애가 발생했을 때, 해당 노드가 담당하던 데이터에 대한 요청 부하가 여러 다른 노드들로 자연스럽게 분산된다.
12.2 복제 전략과 고가용성 달성 메커니즘
카산드라는 노드 장애나 데이터센터 전체의 재해 상황에서도 데이터를 안전하게 보존하고 서비스를 지속하기 위해 데이터를 여러 노드에 복제한다.13 복제본의 개수는 키스페이스를 생성할 때 ’복제 계수(Replication Factor, RF)’를 통해 지정한다.13 예를 들어, RF=3이라면 원본 데이터를 포함하여 총 3개의 복제본이 클러스터 내 서로 다른 노드에 저장된다. 중요한 점은 카산드라에는 프라이머리(Primary)나 마스터(Master) 복제본이라는 개념이 없으며, 모든 복제본은 동등한 지위를 갖는다는 것이다.26
데이터 복제본을 어떤 노드에 배치할지는 ’복제 전략(Replication Strategy)’에 따라 결정된다.
-
SimpleStrategy: 이 전략은 주로 단일 데이터센터로 구성된 개발 환경이나 테스트 환경에서 사용된다.13 파티션 키의 토큰이 속한 노드를 첫 번째 복제본으로 삼고, 링을 시계 방향으로 따라가면서 만나는 다음 노드들에 순차적으로 나머지 복제본을 배치한다.18 이 방식은 네트워크 토폴로지(랙 구성 등)를 고려하지 않는다.
-
NetworkTopologyStrategy: 프로덕션 환경 및 다중 데이터센터 환경에서 반드시 사용해야 하는 전략이다.13 이 전략은 각 데이터센터별로 복제 계수를 독립적으로 설정할 수 있게 해준다. 예를 들어, 미국 데이터센터에는 3개의 복제본을, 유럽 데이터센터에는 2개의 복제본을 두는 것이 가능하다. 더 중요한 것은, 이 전략이 스니치(Snitch)가 제공하는 네트워크 토폴로지 정보를 활용한다는 점이다.
NetworkTopologyStrategy는 복제본을 가능한 한 서로 다른 랙(rack)에 분산시키려고 시도한다. 이를 통해 랙 단위의 장애(예: 랙 스위치 고장, 랙 전원 문제)가 발생하더라도 데이터의 가용성을 잃지 않도록 보장한다.13
12.3 CAP 이론 관점에서의 분석: AP 시스템과 조정 가능한 일관성(Tunable Consistency)
분산 시스템 설계를 논할 때 빠질 수 없는 것이 CAP 이론이다. 이 이론에 따르면, 분산 시스템은 세 가지 속성, 즉 일관성(Consistency), 가용성(Availability), 분할 허용성(Partition Tolerance) 중에서 최대 두 가지만을 동시에 보장할 수 있다.28 네트워크 장애는 분산 시스템에서 피할 수 없는 현실이므로, 모든 실용적인 분산 시스템은 분할 허용성(P)을 기본적으로 선택해야 한다. 따라서 실제 선택은 일관성(C)과 가용성(A) 사이에서 이루어진다.31
카산드라는 설계 철학상, 네트워크 분할(P) 상황에서 데이터의 정합성(C)을 일부 희생하더라도 모든 요청에 응답하는 것(A)을 우선시하는 AP 시스템으로 분류된다.28 이는 일부 노드가 다운되거나 네트워크적으로 고립되더라도, 살아있는 노드들이 계속해서 읽기 및 쓰기 요청을 처리하여 서비스 중단을 최소화하는 것을 목표로 함을 의미한다.
이러한 선택의 결과로 카산드라는 기본적으로 ‘결과적 일관성(Eventual Consistency)’ 모델을 따른다.1 이는 쓰기 작업이 성공한 직후 모든 복제본이 즉시 동일한 데이터를 보장하지는 않지만, 충분한 시간이 지나면(보통 수 밀리초 내에) 모든 복제본이 결국에는 일관된 상태에 도달함을 보장하는 모델이다.
하지만 카산드라는 AP 시스템이라는 정적인 분류에 갇히지 않는다. ’조정 가능한 일관성(Tunable Consistency)’이라는 매우 강력하고 유연한 기능을 제공함으로써, CAP 이론의 트레이드오프를 개발자가 직접 제어할 수 있게 한다.4 이는 시스템 전체에 고정된 일관성 모델을 강요하는 대신, 애플리케이션의 각 읽기/쓰기 요청마다 ’일관성 수준(Consistency Level, CL)’을 명시하여 가용성과 일관성 사이의 균형을 동적으로 조절할 수 있게 하는 것이다.
주요 일관성 수준은 다음과 같다.28
ONE: 복제본 중 하나라도 응답하면 성공으로 간주한다. 가장 빠르지만 일관성은 가장 낮다.QUORUM: 전체 복제본 중 과반수(⌊RF/2⌋+1)가 응답해야 성공으로 간주한다. 일관성과 가용성 사이의 일반적인 균형점이다.LOCAL_QUORUM: 요청을 받은 코디네이터 노드가 속한 데이터센터 내에서 과반수의 복제본이 응답해야 성공으로 간주한다. 데이터센터 간의 네트워크 지연을 피하면서 일관성을 유지하는 데 사용된다.ALL: 모든 복제본이 응답해야 성공으로 간주한다. 가장 강력한 일관성을 보장하지만, 단 하나의 복제본 노드라도 장애가 발생하면 요청이 실패하므로 가용성은 가장 낮다.
이러한 일관성 수준을 조합하여 강력한 일관성을 달성할 수도 있다. 읽기 요청의 일관성 수준(R)과 쓰기 요청의 일관성 수준(W)의 합이 복제 계수(N)보다 크도록 설정하면 (R+W>N), 읽기 작업과 쓰기 작업에 참여하는 노드 집합이 반드시 하나 이상 겹치게 되어 항상 최신 데이터를 읽는 것을 보장할 수 있다.13 예를 들어, RF=3인 환경에서 쓰기와 읽기 요청 모두에 CL=QUORUM(노드 2개의 응답 필요)을 사용하면, 2+2>3 이므로 강력한 일관성이 보장된다.
이처럼 ’조정 가능한 일관성’은 CAP 이론을 정적인 제약이 아닌 동적인 설계의 축으로 활용하는 고도의 아키텍처적 유연성을 보여준다. 개발자는 비즈니스 요구사항의 중요도에 따라, 빠른 응답이 중요한 기능에는 낮은 일관성 수준을, 데이터 정합성이 중요한 기능에는 높은 일관성 수준을 선택적으로 적용하여 시스템 전체의 성능과 신뢰성을 최적화할 수 있다.
13. 쿼리 중심의 데이터 모델링과 CQL
카산드라의 성능과 확장성을 최대한 활용하기 위해서는 그 데이터 모델링 패러다임을 깊이 이해하는 것이 필수적이다. 카산드라의 데이터 모델링은 관계형 데이터베이스(RDBMS)의 ‘데이터 중심’ 접근법과 근본적으로 다르다. 이는 ‘애플리케이션 중심’, 즉 ’쿼리 기반 설계’라는 패러다임 전환을 요구한다. ’JOIN 미지원’은 이러한 철학의 가장 명백한 발현이며, 이는 단순한 제약이 아니라 분산 시스템에서 예측 가능한 저지연(low-latency) 성능을 보장하기 위한 의도적인 설계 결정이다.
13.1 카산드라 데이터 모델의 구성 요소
카산드라의 데이터는 계층적인 구조로 구성된다.10
- 키스페이스 (Keyspace): 가장 상위의 데이터 컨테이너로, RDBMS의 데이터베이스나 스키마와 유사한 개념이다.10 키스페이스는 하나 이상의 테이블을 포함하며, 가장 중요한 역할은 해당 키스페이스에 속한 데이터의 복제 전략(Replication Strategy)과 복제 계수(Replication Factor)를 정의하는 것이다.32
- 테이블 (Table): 과거 ’컬럼 패밀리(Column Family)’로 불렸던 개념으로, 행(Row)과 열(Column)로 구성된 데이터의 집합이다.8 각 테이블은 데이터를 고유하게 식별하는 기본 키(Primary Key)를 반드시 가져야 한다.
- 파티션 키 (Partition Key): 기본 키의 첫 번째 부분을 구성하며, 카산드라 데이터 모델링의 가장 핵심적인 요소이다.14 파티션 키의 값은 해싱되어 토큰(Token)으로 변환되고, 이 토큰 값에 따라 데이터가 클러스터 내의 어떤 물리적 노드(파티션)에 저장될지가 결정된다.2 따라서 모든 읽기 및 쓰기 성능은 파티션 키를 어떻게 설계하느냐에 따라 극명하게 달라진다. 파티션 키는 단일 컬럼(Simple Partition Key)으로 구성될 수도 있고, 여러 컬럼을 괄호로 묶어 복합 파티션 키(Composite Partition Key)로 구성할 수도 있다 (
PRIMARY KEY ((col_a, col_b),...)).36 - 클러스터링 키 (Clustering Key): 기본 키에서 파티션 키를 제외한 나머지 부분을 의미한다.35 클러스터링 키의 역할은 동일한 파티션 키를 가진 데이터(행)들을 물리적으로 어떻게 정렬하여 저장할지를 결정하는 것이다. 데이터는 클러스터링 키의 순서에 따라 디스크에 정렬되어 저장되므로, 특정 범위의 데이터를 조회하는 범위 쿼리(range query)나 정렬된 결과를 얻는 쿼리를 매우 효율적으로 수행할 수 있게 해준다.37
13.2 핵심 원칙: 쿼리 기반 설계(Query-Driven Design)와 비정규화(Denormalization)
RDBMS 데이터 모델링의 제1원칙은 정규화(Normalization)를 통해 데이터 중복을 최소화하고 데이터 무결성을 유지하는 것이다. 그리고 필요한 데이터는 쿼리 시점에 JOIN 연산을 통해 조합한다. 카산드라는 이와 정반대의 접근법을 취한다.
쿼리 기반 설계 (Query-Driven Design): 카산드라에서는 데이터의 관계를 중심으로 테이블을 설계하는 것이 아니라, 애플리케이션이 데이터를 어떻게 조회할 것인지, 즉 ’쿼리 패턴’을 가장 먼저 분석하고 정의해야 한다.39 그리고 각각의 쿼리 패턴을 가장 효율적으로 만족시킬 수 있도록 테이블을 설계한다. 이는 “하나의 쿼리에는 하나의 테이블“이라는 원칙으로 요약될 수 있다.
비정규화 (Denormalization): 쿼리 기반 설계를 따르다 보면, 자연스럽게 비정규화가 핵심 전략이 된다. RDBMS에서는 JOIN을 통해 여러 테이블의 정보를 결합하지만, 카산드라는 JOIN을 지원하지 않는다. 따라서 특정 쿼리가 여러 엔티티의 정보를 필요로 한다면, 해당 정보를 모두 포함하는 하나의 ‘비정규화된’ 테이블을 만드는 것이 일반적이다.39 예를 들어, ’사용자 정보’와 ‘사용자가 작성한 게시물’ 정보를 함께 보여줘야 하는 쿼리가 있다면, 게시물 테이블에 사용자 이름과 같은 중복 데이터를 함께 저장하는 것이다. 이는 쓰기 시점에 약간의 오버헤드와 추가적인 저장 공간을 감수하는 대신, 읽기 시점에는 단일 테이블 조회만으로 매우 빠른 성능을 얻기 위한 전략적 트레이드오프이다.
이러한 모델링의 핵심 목표는 두 가지로 요약된다: 1) 파티션 키를 신중하게 선택하여 데이터와 부하를 클러스터 전체에 균등하게 분산시키는 것, 그리고 2) 각 쿼리가 가능한 한 적은 수의 파티션(이상적으로는 단 하나)을 읽도록 설계하는 것이다.36
13.3 JOIN 미지원에 따른 대안적 접근법
카산드라가 JOIN을 지원하지 않는 이유는 그 아키텍처적 목표와 직결된다. 분산 환경에서 JOIN 연산은 서로 다른 노드에 흩어져 있는 데이터를 네트워크를 통해 실시간으로 집계해야 하는 매우 비용이 많이 드는 작업이다. 이는 네트워크 병목을 유발하고 응답 시간을 예측 불가능하게 만들어, 카산드라가 추구하는 선형적 확장성과 예측 가능한 저지연 성능이라는 목표를 근본적으로 훼손한다.43
따라서 JOIN이 필요한 RDBMS의 데이터 모델을 카산드라로 이전할 때는 다음과 같은 대안적인 접근법을 사용해야 한다.
- 비정규화를 통한 테이블 생성 (권장): 가장 일반적이고 권장되는 방법이다. 앞서 설명한 바와 같이, 쿼리 패턴에 맞춰 필요한 모든 데이터를 포함하는 새로운 테이블을 생성한다. 예를 들어,
사용자별 주문 목록을 조회하는 쿼리가 있다면, 주문 테이블에 사용자 ID를 파티션 키로 두고, 주문 정보와 함께 필요한 제품명, 가격 등의 정보를 중복해서 저장하는orders_by_user테이블을 만든다.43 - 클라이언트 측 조인 (제한적 사용): 애플리케이션 코드 레벨에서 여러 테이블에 개별적으로 쿼리를 실행한 후, 그 결과를 메모리에서 직접 조합하는 방식이다.43 예를 들어, 주문 ID로 주문 정보를 조회하고, 그 결과에 포함된 사용자 ID로 다시 사용자 테이블을 조회하여 두 정보를 합치는 것이다. 이 방법은 여러 번의 네트워크 왕복을 유발하므로 지연 시간이 길어지고 애플리케이션의 복잡도가 증가한다. 따라서 데이터 모델을 변경하기 어려운 예외적인 상황에서만 제한적으로 사용해야 한다.
- 구체화된 뷰 (Materialized Views): 카산드라가 서버 측에서 비정규화를 자동으로 관리해주는 기능이다.32 기본 테이블(base table)을 기반으로, 다른 파티션 키와 클러스터링 키를 갖는 새로운 뷰 테이블을 생성할 수 있다. 기본 테이블의 데이터가 변경되면 카산드라가 자동으로 뷰 테이블을 업데이트해준다.24 이는 개발 편의성을 높여주지만, 백그라운드 업데이트로 인한 성능 오버헤드가 발생할 수 있고, 여전히 실험적인 기능으로 간주되어 몇 가지 제약사항이 존재하므로 신중하게 사용해야 한다.32
13.4 Cassandra Query Language (CQL) 활용법
카산드라는 데이터베이스와 상호작용하기 위해 CQL(Cassandra Query Language)이라는 쿼리 언어를 제공한다. CQL은 의도적으로 SQL과 매우 유사한 구문을 채택하여, RDBMS에 익숙한 개발자들이 쉽게 적응할 수 있도록 설계되었다.9
CQL은 데이터 정의 언어(DDL)와 데이터 조작 언어(DML)를 모두 포함한다.35
- DDL:
CREATE KEYSPACE,CREATE TABLE,ALTER TABLE,DROP TABLE등 스키마를 정의하고 변경하는 명령어. - DML:
INSERT,UPDATE,DELETE,SELECT등 데이터를 조작하고 조회하는 명령어.
SQL과의 주요 차이점은 카산드라의 데이터 모델 제약을 반영한다는 점이다. JOIN 연산은 지원되지 않으며, GROUP BY와 같은 집계 기능도 매우 제한적이다.34
SELECT 문의 WHERE 절에서 필터링 조건으로 사용할 수 있는 컬럼은 주로 기본 키(파티션 키 및 클러스터링 키)로 한정된다. 이는 카산드라가 전체 데이터를 스캔하는 비효율적인 쿼리를 방지하고, 항상 파티션 키를 통해 특정 노드의 특정 위치를 직접 찾아가는 고성능 쿼리를 유도하기 위함이다.
기본 CQL 사용 예시:
-- 1. 키스페이스 생성 (데이터센터 dc1에 복제본 3개)
CREATE KEYSPACE my_app WITH replication = {
'class': 'NetworkTopologyStrategy',
'dc1': '3'
};
-- 2. 생성한 키스페이스 사용
USE my_app;
-- 3. 사용자별 비디오 목록을 저장할 테이블 생성
-- userid가 파티션 키, uploaded_at이 클러스터링 키
CREATE TABLE videos_by_user (
userid UUID,
uploaded_at TIMESTAMP,
video_id UUID,
title TEXT,
PRIMARY KEY (userid, uploaded_at)
) WITH CLUSTERING ORDER BY (uploaded_at DESC);
-- 4. 데이터 삽입
INSERT INTO videos_by_user (userid, uploaded_at, video_id, title)
VALUES (uuid(), toTimestamp(now()), uuid(), 'My First Video');
-- 5. 데이터 조회 (파티션 키는 반드시 지정해야 함)
SELECT video_id, title FROM videos_by_user
WHERE userid = 123e4567-e89b-12d3-a456-426614174000;
34
13.4.1 표 1: 관계형 데이터베이스(RDBMS)와 카산드라의 데이터 모델링 패러다임 비교
| 특성 | RDBMS (정규화 모델) | Cassandra (비정규화/쿼리 기반 모델) |
|---|---|---|
| 설계 중심 | 데이터 관계 (엔티티) 중심 | 애플리케이션 쿼리 중심 |
| 데이터 중복 | 최소화 (정규화) | 허용 및 권장 (비정규화) |
| 데이터 조합 | 읽기 시점 (JOIN) | 쓰기 시점 (비정규화 테이블) |
| 스키마 변경 | 어려움 (Migration 필요) | 유연함 (동적 컬럼 추가) |
| 주요 최적화 목표 | 저장 공간 효율성, 데이터 무결성 | 읽기 성능, 확장성 |
이 표는 두 시스템 간의 근본적인 철학적 차이를 명확하게 보여준다. 카산드라를 성공적으로 도입하기 위해서는 RDBMS적 사고방식에서 벗어나, 애플리케이션의 데이터 접근 패턴을 최우선으로 고려하는 ’쿼리 기반 설계’라는 새로운 패러다임을 받아들이는 것이 왜 중요한지를 함축적으로 전달한다.
14. 스토리지 엔진 내부 동작 원리
카산드라의 고성능은 ’쓰기 최적화’라는 명확한 목표를 위해 설계된 정교한 스토리지 엔진에 기인한다. 이 엔진의 핵심은 LSM-Tree(Log-Structured Merge-Tree) 아키텍처로, 이 선택에서 비롯된 인과관계의 사슬이 카산드라의 쓰기, 읽기, 삭제, 그리고 데이터 유지보수 방식 전체를 규정한다. 빠른 쓰기를 얻는 대가로 발생하는 읽기 및 삭제의 복잡성을 해결하기 위해 블룸 필터, 툼스톤, 컴팩션과 같은 보완적인 메커니즘들이 유기적으로 작동한다.
14.1 쓰기 경로(Write Path): LSM-Tree 기반의 고성능 쓰기 메커니즘
카산드라는 전통적인 데이터베이스가 사용하는 B-Tree 구조 대신 LSM-Tree를 채택하여 쓰기 성능을 극대화했다.53 B-Tree는 데이터를 정렬된 상태로 유지하기 위해 새로운 데이터가 삽입될 때 디스크의 특정 위치를 찾아 데이터를 수정하는 ‘제자리 업데이트(in-place update)’ 방식을 사용한다. 이는 디스크 탐색(seek)과 랜덤 I/O를 유발하여 쓰기 작업에 병목을 일으킬 수 있다.
반면, LSM-Tree는 모든 쓰기 작업을 디스크에 순차적으로 추가(append-only)하는 방식으로 처리하여 랜덤 I/O를 제거하고 쓰기 처리량을 획기적으로 향상시킨다.56 카산드라의 쓰기 경로는 다음과 같은 단계로 이루어진다.56
- 커밋 로그(Commit Log)에 추가: 클라이언트로부터 쓰기 요청이 들어오면, 카산드라는 먼저 해당 데이터를 디스크 상의 커밋 로그 파일에 순차적으로 기록한다.10 이는 쓰기 전 로그(Write-Ahead Log, WAL)의 일종으로, 노드에 예기치 않은 장애가 발생하더라도 기록된 데이터를 복구하여 내구성(Durability)을 보장하는 역할을 한다. 커밋 로그에 대한 쓰기는 순차 I/O이므로 매우 빠르다.
- 멤테이블(Memtable)에 쓰기: 커밋 로그에 기록하는 동시에, 데이터는 메모리 내의 정렬된 자료 구조인 멤테이블에 쓰여진다.10 멤테이블은 파티션 키와 클러스터링 키를 기준으로 데이터를 정렬된 상태로 유지한다.
- 클라이언트에 응답: 이 두 단계가 완료되면, 즉 데이터가 디스크(커밋 로그)와 메모리(멤테이블)에 모두 안전하게 기록되면, 카산드라는 클라이언트에게 쓰기 작업이 성공했음을 알린다. 이 과정에서 디스크에 대한 랜덤 I/O가 전혀 발생하지 않기 때문에 쓰기 지연 시간이 극도로 짧다.
- SSTable로 플러시(Flush): 멤테이블이 설정된 크기 임계값에 도달하거나 일정 시간이 지나면, 멤테이블의 내용은 디스크에 새로운 파일 형태로 순차적으로 기록된다. 이 파일을 SSTable(Sorted String Table)이라고 부른다.10 SSTable은 한번 기록되면 절대 수정되지 않는 불변(immutable)의 속성을 가진다. 플러시 작업이 완료되면, 해당 멤테이블에 있던 데이터에 대한 커밋 로그는 더 이상 필요 없으므로 삭제된다.
14.2 읽기 경로(Read Path): 블룸 필터(Bloom Filter)를 통한 I/O 최적화
쓰기 최적화의 대가로 카산드라의 읽기 경로는 다소 복잡하다. 특정 파티션 키에 해당하는 데이터가 메모리의 멤테이블과 디스크의 여러 SSTable 파일에 흩어져 있을 수 있기 때문이다. 따라서 읽기 요청을 처리하기 위해서는 이 모든 소스로부터 데이터를 읽어와 병합한 후, 가장 최신 타임스탬프를 가진 데이터를 반환해야 한다 (Last Write Wins 원칙).10
만약 모든 SSTable 파일을 매번 디스크에서 읽어야 한다면 읽기 성능은 심각하게 저하될 것이다. 카산드라는 이러한 비효율을 줄이기 위해 여러 캐싱 및 최적화 기법을 사용하며, 그중 가장 핵심적인 것이 ’블룸 필터(Bloom Filter)’이다.58
블룸 필터(Bloom Filter)의 원리: 블룸 필터는 특정 원소가 집합에 속해 있는지를 매우 빠르고 메모리 효율적으로 검사할 수 있는 확률적 자료 구조이다.59 각 SSTable은 자신만의 블룸 필터를 가지며, 이 블룸 필터들은 메모리(오프힙)에 상주한다.58
블룸 필터는 두 가지 답변만 할 수 있다.59
- “찾는 데이터는 이 SSTable에 절대 존재하지 않는다.” (거짓 음성, False Negative 없음)
- “찾는 데이터가 이 SSTable에 존재할 가능성이 있다.” (거짓 양성, False Positive 가능)
읽기 요청이 들어오면, 카산드라는 디스크의 SSTable 파일에 접근하기 전에 먼저 메모리에 있는 블룸 필터를 확인한다. 만약 블룸 필터가 “절대 존재하지 않는다“고 응답하면, 해당 SSTable에 대한 비싼 디스크 I/O 작업을 완전히 건너뛸 수 있다.60 “존재할 가능성이 있다“고 응답할 경우에만 실제 SSTable 파일을 읽어 데이터의 존재 여부를 최종 확인한다. 이 메커니즘을 통해 카산드라는 불필요한 디스크 접근을 획기적으로 줄여 읽기 성능을 크게 향상시킨다.59
카산드라의 전체 읽기 경로는 다음과 같은 순서로 진행된다.58
- 활성 멤테이블 확인
- (활성화 시) 행 캐시(Row Cache) 확인
- 블룸 필터 확인
- 블룸 필터가 통과하면, (활성화 시) 파티션 키 캐시(Partition Key Cache)를 확인하여 SSTable 내 데이터의 오프셋을 찾음
- 캐시에 오프셋이 없으면, 파티션 요약(Partition Summary)과 파티션 인덱스(Partition Index)를 통해 오프셋을 찾음
- 찾아낸 오프셋을 이용해 SSTable 파일에서 데이터를 읽어옴
- 멤테이블과 여러 SSTable에서 읽어온 결과를 병합하여 최종 결과를 반환
14.3 삭제 메커니즘: 툼스톤(Tombstone)의 역할과 성능 영향
LSM-Tree 아키텍처에서 SSTable은 불변(immutable)이기 때문에, 기존 데이터를 직접 찾아가 삭제하는 작업이 불가능하다. 대신 카산드라는 논리적인 삭제 방식을 사용하는데, 이것이 바로 ’툼스톤(Tombstone)’이다.10
데이터 삭제 요청이 오면, 카산드라는 데이터를 물리적으로 지우는 대신, 해당 데이터가 삭제되었음을 알리는 타임스탬프가 찍힌 특수한 마커, 즉 툼스톤을 새로 기록한다.62 툼스톤 역시 일반 데이터와 마찬가지로 쓰기 경로를 통해 멤테이블에 기록된 후 SSTable로 플러시된다. 읽기 요청이 들어오면, 카산드라는 데이터와 툼스톤을 함께 읽고, 툼스톤의 타임스탬프가 데이터의 타임스탬프보다 최신이면 해당 데이터를 없는 것으로 간주하고 결과에서 제외한다.
툼스톤의 역할: 툼스톤은 분산 환경에서 삭제 정보가 모든 복제본에 안정적으로 전파되도록 보장하는 핵심적인 역할을 한다. 만약 어떤 노드가 다운된 상태에서 데이터가 삭제되었다고 가정해보자. 툼스톤이 없다면, 나중에 이 노드가 다시 온라인 상태가 되었을 때, 다른 노드들은 이미 삭제된 데이터를 가지고 있는 이 노드로부터 오래된 데이터를 복제하여 삭제된 데이터가 되살아나는 ‘좀비 데이터(zombie data)’ 현상이 발생할 수 있다. 툼스톤은 이러한 데이터 부활을 방지한다.64
성능 영향: 툼스톤은 필수적인 기능이지만, 과도하게 많아지면 심각한 성능 저하를 유발한다.62
- 읽기 성능 저하: 읽기 쿼리는 유효한 데이터뿐만 아니라 툼스톤도 함께 스캔해야 하므로, 툼스톤이 많을수록 처리할 데이터가 늘어나 지연 시간이 증가한다. 특히 범위 쿼리에서 수많은 툼스톤을 건너뛰어야 할 경우 성능 저하가 극심하다.
- 메모리 및 GC 압박: 스캔된 툼스톤은 힙 메모리에 로드되어야 하므로, 메모리 사용량을 증가시키고 가비지 컬렉션(GC)에 부담을 준다.
- 디스크 사용량: 툼스톤 자체도 디스크 공간을 차지한다.
gc_grace_seconds: 툼스톤은 영원히 남아있지 않는다. 각 테이블에는 gc_grace_seconds라는 설정값이 있으며, 기본값은 10일(864,000초)이다.62 이 시간은 삭제 정보가 다운된 노드에까지 전파될 수 있는 유예 기간을 의미한다. 툼스톤이 생성된 후 gc_grace_seconds가 지나면, 해당 툼스톤은 컴팩션(Compaction) 과정에서 관련된 데이터와 함께 영구적으로 제거될 수 있다.62 따라서 클러스터의 모든 노드는 gc_grace_seconds 주기 내에 최소 한 번 이상 nodetool repair를 실행하여 데이터 일관성을 맞춰야 한다.
14.4 압축(Compaction) 전략 비교 분석: STCS, LCS, TWCS
시간이 지남에 따라 플러시 작업으로 인해 수많은 SSTable이 디스크에 쌓이게 된다. 또한, 업데이트(새로운 버전의 데이터를 씀)와 삭제(툼스톤을 씀)로 인해 오래된 데이터와 툼스톤이 디스크 공간을 차지하게 된다. ’컴팩션(Compaction)’은 이렇게 흩어져 있는 여러 SSTable과 불필요한 데이터(오래된 버전, 툼스톤)를 병합하여 더 적은 수의 새로운 SSTable로 만드는 백그라운드 유지보수 작업이다.10 컴팩션은 디스크 공간을 효율적으로 재사용하고, 읽기 시 스캔해야 할 SSTable의 수를 줄여 읽기 성능을 최적화하는 데 필수적이다.
카산드라는 워크로드의 특성에 따라 선택할 수 있는 여러 컴팩션 전략을 제공한다.
- SizeTieredCompactionStrategy (STCS): 기본 전략으로, 비슷한 크기의 SSTable이 4개 이상(기본 설정) 모이면 이들을 하나의 큰 SSTable로 병합한다.68 이 과정은 쓰기 작업 중에 발생하는 I/O 오버헤드(쓰기 증폭)가 상대적으로 적어 쓰기 중심의 워크로드에 적합하다. 하지만 데이터가 여러 크기의 SSTable에 흩어져 있을 수 있어 읽기 시 여러 파일을 스캔해야 할 수 있고(읽기 증폭 높음), 오래된 데이터가 오랫동안 남아있을 수 있으며, 컴팩션 시 임시적으로 원본 데이터 크기만큼의 추가 디스크 공간이 필요하다(공간 증폭 높음).69
- LeveledCompactionStrategy (LCS): 읽기 중심의 워크로드에 최적화된 전략이다.67 SSTable을 여러 개의 ’레벨(Level)’로 나누어 관리한다. 가장 낮은 레벨(L0)을 제외한 각 레벨(L1, L2,…) 내의 SSTable들은 서로 데이터(파티션 키) 범위가 겹치지 않도록 유지된다. 이 덕분에 특정 데이터를 찾기 위해 각 레벨에서 최대 하나의 SSTable만 읽으면 되므로 읽기 성능이 매우 뛰어나다(읽기 증폭 낮음). 그러나 데이터를 상위 레벨로 올리기 위해 더 작고 빈번한 컴팩션이 계속해서 발생하므로, 쓰기 I/O 오버헤드(쓰기 증폭)가 STCS보다 훨씬 크다.70
- TimeWindowCompactionStrategy (TWCS): 로그나 센서 데이터와 같은 시계열 데이터에 특화된 전략이다.67 데이터를 시간 단위(예: 1일)의 ’윈도우’로 그룹화한다. 각 윈도우 내에서는 STCS 방식으로 컴팩션이 진행된다. 윈도우가 닫히면(즉, 해당 시간 구간이 지나면), 그 윈도우에 속한 SSTable들은 더 이상 다른 윈도우의 SSTable과 병합되지 않는다. 이는 오래된 데이터와 최신 데이터가 섞이는 것을 방지한다. 특히 데이터에 TTL(Time-To-Live)을 설정한 경우, 특정 윈도우의 모든 데이터가 만료되면 카산드라는 해당 윈도우에 속한 SSTable 파일 전체를 간단히 삭제할 수 있어, 툼스톤을 생성하지 않고도 매우 효율적으로 오래된 데이터를 제거할 수 있다.70
- UnifiedCompactionStrategy (UCS): Cassandra 5.0에 도입된 최신 전략으로, STCS와 LCS의 장점을 결합한 하이브리드 방식이다.68 단일 전략 내에서 파라미터 조정을 통해 STCS처럼 동작하게 하거나 LCS처럼 동작하게 할 수 있어, 다양한 워크로드에 유연하게 대응하고 운영의 복잡성을 줄여준다.72
14.4.1 표 2: 카산드라 압축(Compaction) 전략 비교
| 전략 | 최적 워크로드 | 읽기 증폭 | 쓰기 증폭 | 공간 증폭 | 핵심 동작 원리 |
|---|---|---|---|---|---|
| STCS | 쓰기 중심 | 높음 | 낮음 | 높음 | 비슷한 크기의 SSTable들을 하나의 큰 SSTable로 병합 |
| LCS | 읽기 중심 | 낮음 | 높음 | 낮음 | SSTable을 레벨별로 관리하며, 각 레벨 내 데이터가 겹치지 않게 유지 |
| TWCS | 시계열/TTL | 낮음 (윈도우 내) | 낮음 (윈도우 내) | 낮음 (TTL 만료 시) | 시간 윈도우 단위로 SSTable을 그룹화하여 독립적으로 관리 |
| UCS (5.0+) | 혼합/적응형 | 가변/조정 가능 | 가변/조정 가능 | 가변/조정 가능 | STCS와 LCS를 결합한 하이브리드 알고리즘 |
이 표는 운영자가 자신의 애플리케이션 워크로드 특성에 맞는 최적의 컴팩션 전략을 선택하는 데 필요한 핵심 정보를 일목요연하게 제공한다. 각 전략의 근본적인 트레이드오프 관계를 이해하는 것은 카산드라 클러스터의 장기적인 성능과 안정성을 유지하는 데 매우 중요하다.
15. 운영, 관리 및 성능 튜닝
카산드라의 분산 아키텍처는 뛰어난 확장성과 가용성을 제공하지만, 그 성능을 최적으로 유지하고 안정적으로 운영하기 위해서는 지속적인 관리와 튜닝이 필수적이다. 카산드라 운영은 ’균형’의 예술이라 할 수 있다. 쓰기 성능, 읽기 성능, 디스크 사용량, GC 효율 등 서로 상충하는 요소들 사이에서 현재 워크로드에 맞는 최적의 지점을 찾는 과정이며, 이는 nodetool을 통한 관리 작업, cassandra.yaml 및 JVM 설정을 통한 미세 조정, 그리고 모니터링을 통한 지속적인 관찰을 통해 이루어진다.
15.1 nodetool을 활용한 클러스터 관리
nodetool은 JMX(Java Management Extensions)를 통해 실행 중인 카산드라 노드와 상호작용하여 클러스터를 관리하고 모니터링하는 가장 기본적인 커맨드라인 유틸리티이다.10 운영자는 nodetool을 사용하여 클러스터의 상태를 확인하고, 데이터 일관성을 유지하며, 백업과 같은 필수적인 유지보수 작업을 수행할 수 있다.
15.1.1 Repair: 데이터 일관성 복구
카산드라는 결과적 일관성 모델을 따르기 때문에, 노드 장애나 네트워크 문제로 인해 복제본 간에 일시적인 데이터 불일치가 발생할 수 있다. ’Repair’는 이러한 불일치를 감지하고 동기화하여 데이터의 최종적인 일관성을 보장하는 안티-엔트로피(anti-entropy) 프로세스이다.76
Repair 과정에서 노드들은 자신이 담당하는 데이터 범위에 대해 머클 트리(Merkle Tree)라는 해시 트리를 생성한다. 이 트리를 서로 비교하여 데이터가 다른 부분을 효율적으로 찾아내고, 다른 부분만 네트워크를 통해 스트리밍하여 동기화한다.76
- Full Repair (
nodetool repair --full): 노드가 담당하는 모든 데이터에 대해 머클 트리를 생성하고 비교한다. 리소스 소모가 크지만, 전체 데이터의 정합성을 완벽하게 보장한다. 클러스터에 노드를 새로 추가했거나 복제 계수를 변경한 후에 실행하는 것이 좋다.76 - Incremental Repair (
nodetool repair): Cassandra 2.2부터 기본값으로, 마지막 repair 이후 새로 추가되거나 변경된 데이터(SSTable)만을 대상으로 repair를 수행한다.76 전체 데이터를 매번 비교하는 full repair보다 훨씬 효율적이므로, 정기적으로(예: 매일) 실행하는 것이 권장된다.
gc_grace_seconds(기본 10일) 주기 내에 반드시 repair를 수행하는 것은 매우 중요하다. 만약 이 기간 내에 repair가 실행되지 않으면, 삭제된 데이터의 정보(툼스톤)가 일부 노드에 전달되지 않은 상태에서 툼스톤이 먼저 삭제될 수 있다. 이 경우, 오래된 데이터를 가진 노드가 나중에 이 데이터를 다른 노드에 전파하여 삭제된 데이터가 되살아나는 ‘좀비 데이터’ 현상이 발생할 수 있다.76
15.1.2 Backup and Restore: 데이터 백업 및 복구
카산드라는 데이터 손실에 대비한 백업 및 복구 메커니즘을 제공한다.
- 백업 (Snapshot): 가장 일반적인 백업 방법은
nodetool snapshot명령어를 사용하는 것이다.32 이 명령어는 특정 시점의 모든 SSTable 파일에 대한 하드 링크(hard link)를 생성한다. 하드 링크는 실제 데이터 파일을 복사하는 것이 아니라 파일 시스템의 포인터만 생성하므로 매우 빠르고 디스크 공간을 거의 차지하지 않는다. 스냅샷 생성 후, 생성된 하드 링크 파일들을 외부 스토리지(예: S3, NAS)로 복사하여 안전하게 보관한다. 이 과정은 데이터베이스를 중단하지 않고 온라인 상태에서 수행할 수 있다. - 복구 (Restore): 데이터를 복구하려면 먼저 테이블의 데이터를 비우고(
TRUNCATE), 외부 스토리지에 백업해 둔 스냅샷 파일들을 원래의 카산드라 데이터 디렉토리로 복사한다.78 그 후,nodetool refresh명령어를 실행하여 카산드라가 새로 복사된 SSTable 파일들을 인식하고 로드하도록 한다. 복구가 완료된 후에는 클러스터 전체에nodetool repair를 실행하여 노드 간 데이터 일관성을 반드시 맞춰주어야 한다.
이 외에도 nodetool status (클러스터 노드 상태 확인), nodetool info (특정 노드 정보), nodetool cfstats (테이블 통계), nodetool compactionstats (컴팩션 진행 상태), nodetool flush, nodetool drain (노드 재시작 전 메모리의 데이터를 디스크로 안전하게 내리는 작업) 등 다양한 명령어가 클러스터 운영에 필수적으로 사용된다.32
15.2 cassandra.yaml 핵심 파라미터 및 JVM 튜닝을 통한 성능 최적화
카산드라의 성능은 cassandra.yaml 설정 파일과 JVM(Java Virtual Machine) 옵션을 어떻게 조정하느냐에 따라 크게 달라진다. 워크로드의 특성을 정확히 파악하고 그에 맞는 튜닝을 적용하는 것이 중요하다.80
15.2.1 cassandra.yaml 핵심 파라미터
- 네트워킹 및 토폴로지:
listen_address,rpc_address: 노드가 다른 노드 및 클라이언트와 통신하기 위해 사용하는 IP 주소.seeds: 클러스터의 시드 노드 목록.endpoint_snitch: 클러스터의 네트워크 토폴로지(데이터센터, 랙)를 인식하는 전략을 설정. 프로덕션 환경에서는GossipingPropertyFileSnitch가 권장된다.80- 디스크 I/O 최적화:
commitlog_directory,data_file_directories: 커밋 로그와 데이터 파일(SSTable)의 저장 위치. 최상의 성능을 위해서는 이 두 디렉토리를 서로 다른 물리적 디스크에 배치해야 한다. 특히, 쓰기 성능에 지대한 영향을 미치는 커밋 로그는 SSD와 같은 빠른 디스크에 위치시키는 것이 매우 효과적이다.80commitlog_sync: 커밋 로그를 디스크에 동기화하는 방식.periodic(주기적) 방식은 성능이 좋지만 장애 시 일부 데이터 유실 가능성이 있고,batch방식은 내구성이 높지만 쓰기 지연 시간이 약간 증가한다.80- 메모리 및 압축:
memtable_allocation_type: 멤테이블을 JVM 힙 메모리(on-heap)에 할당할지, 아니면 네이티브 메모리(off-heap)에 할당할지를 결정. 오프힙을 사용하면 대용량 멤테이블을 사용하면서도 JVM의 GC 부담을 크게 줄일 수 있다.82concurrent_compactors,compaction_throughput_mb_per_sec: 컴팩션을 수행하는 스레드 수와 초당 최대 처리량을 제한하는 설정. 컴팩션이 다른 작업에 미치는 영향을 제어하는 데 사용된다.83
15.2.2 JVM 튜닝 (cassandra-env.sh 또는 jvm.options 파일)
카산드라는 JVM 위에서 동작하므로, JVM 튜닝, 특히 힙 메모리(Heap Memory)와 가비지 컬렉터(Garbage Collector, GC) 설정이 전체 성능에 결정적인 영향을 미친다.
- 힙 크기 (Heap Size):
MAX_HEAP_SIZE옵션으로 설정한다. 일반적으로 시스템 전체 RAM의 1/4에서 1/2 사이로 설정하는 것이 권장되지만, 절대적인 규칙은 아니다.84 OS가 파일 시스템 캐시로 사용할 메모리를 충분히 남겨두는 것이 매우 중요하다. 힙 크기가 너무 크면 Full GC 발생 시 ‘Stop-the-world’ 정지 시간이 길어져 노드가 응답 불능 상태에 빠질 수 있다. 반대로 너무 작으면 잦은 GC로 성능이 저하되거나 OutOfMemoryError가 발생할 수 있다.82 - 가비지 컬렉터 (GC) 설정:
- G1GC (Garbage-First): Java 9부터 기본 GC로, 대용량 힙(예: 16GB ~ 64GB) 환경에서 CMS보다 예측 가능한 정지 시간을 제공하도록 설계되었다.85 힙을 여러 개의 작은 영역(region)으로 나누고, 가비지가 가장 많이 쌓인 영역부터 우선적으로 정리하여 전체적인 GC 효율을 높인다.
- ZGC (Z Garbage Collector): Java 11에서 실험적으로 도입되어 Java 15부터 프로덕션용으로 사용 가능한 최신 저지연 GC이다.86 수백 GB 이상의 대용량 힙에서도 GC로 인한 정지 시간을 수 밀리초(sub-millisecond) 이내로 유지하는 것을 목표로 한다. Cassandra 5.0부터 JDK 17을 공식 지원하게 되면서, ZGC를 활용하여 매우 일관된 저지연 성능을 달성하는 것이 가능해졌다.72
15.3 Prometheus와 Grafana를 활용한 모니터링 핵심 지표
안정적인 클러스터 운영과 선제적인 성능 문제 해결을 위해서는 지속적인 모니터링이 필수적이다. 카산드라는 JMX를 통해 수백 개의 내부 성능 지표(metrics)를 노출한다. 오픈소스 모니터링 솔루션인 Prometheus와 Grafana는 이러한 지표를 수집, 저장, 시각화하는 사실상의 표준 조합이다. Prometheus는 jmx_exporter나 MCAC(Metrics Collector for Apache Cassandra) 같은 에이전트를 통해 카산드라의 JMX 메트릭을 주기적으로 수집(scrape)하고, Grafana는 수집된 데이터를 사용하여 시각적으로 이해하기 쉬운 대시보드를 구성한다.81
반드시 추적해야 할 핵심 성능 지표는 다음과 같다.
- 요청 지연 시간 (Request Latency): 읽기 및 쓰기 요청의 평균, 95, 99, 99.9 퍼센타일 지연 시간. 특히 99 퍼센타일 이상의 ’꼬리 지연 시간(tail latency)’은 시스템의 실제 사용자 경험과 안정성을 파악하는 데 매우 중요한 지표이다.90
- 요청 처리량 (Request Throughput): 초당 처리되는 읽기 및 쓰기 요청의 수. 클러스터가 현재 받고 있는 부하의 양을 나타낸다.90
- 대기 중인 작업 (Pending/Blocked Tasks): 컴팩션, 멤테이블 플러시 등 내부 스테이지에서 처리되지 못하고 대기 중인 작업의 수. 이 수치가 지속적으로 증가한다면 해당 스테이지에 병목이 발생했음을 의미한다.81
- 가비지 컬렉션 (Garbage Collection): GC 발생 횟수와 총 소요 시간, 특히 긴 ‘Stop-the-world’ 정지 시간. 긴 GC 정지는 노드 타임아웃을 유발하여 클러스터 전체의 안정성을 해칠 수 있다.90
- SSTable 및 컴팩션 관련 지표: 총 SSTable 개수, 디스크 사용량, 예상되는 컴팩션 작업의 양. SSTable 개수가 과도하게 많으면 읽기 성능 저하의 직접적인 원인이 된다.81
- 툼스톤 (Tombstone) 관련 지표: 읽기 쿼리에서 스캔된 툼스톤의 수. 이 지표가 높게 나타나면, 불필요한 데이터 스캔으로 인해 읽기 지연 시간이 길어지고 있음을 시사한다.66
- OS 수준 지표: CPU 사용률, 디스크 I/O 대기 시간, 네트워크 대역폭, 가용 메모리 등 노드 자체의 리소스 상태. 데이터베이스 내부 지표와 함께 분석하여 문제의 근본 원인을 파악하는 데 사용된다.81
16. 주요 데이터베이스 시스템과의 비교 분석
카산드라의 아키텍처와 특성을 깊이 이해하기 위해서는 다른 데이터베이스 시스템과의 비교를 통해 그 상대적인 위치와 설계 철학의 차이를 파악하는 것이 효과적이다. 데이터베이스 선택은 단순히 기술 스택을 고르는 행위가 아니라, 해결하고자 하는 비즈니스 문제의 특성과 가장 잘 맞는 ‘설계 철학’ 및 ’트레이드오프’를 선택하는 전략적 결정이다. 각 데이터베이스는 특정 목표를 달성하기 위해 다른 가치를 의도적으로 희생한 결과물이기 때문이다.
16.1 vs. RDBMS, MongoDB, HBase: 아키텍처 및 데이터 모델의 근본적 차이
16.1.1 vs. 관계형 데이터베이스 (RDBMS)
RDBMS(예: MySQL, PostgreSQL)와의 비교는 카산드라가 왜 등장했는지를 가장 잘 보여준다.
- 아키텍처 및 확장성: RDBMS는 전통적으로 단일 서버의 성능을 높이는 수직적 확장(Scale-up)에 의존하는 중앙 집중형 Master-Slave 구조를 가진다. 반면, 카산드라는 여러 대의 범용 서버를 추가하여 시스템 전체의 성능을 높이는 수평적 확장(Scale-out)에 최적화된 분산형 Masterless 구조를 채택했다.3
- 데이터 모델 및 스키마: RDBMS는 정규화를 통해 데이터 중복을 최소화하고, 고정된 스키마와 관계(JOIN)를 통해 데이터 무결성을 강제한다. 카산드라는 읽기 성능을 위해 비정규화를 적극 권장하며, 스키마 변경이 자유로운 유연한 와이드 컬럼 모델을 사용한다.10
- 일관성 및 트랜잭션: RDBMS는 ACID(원자성, 일관성, 고립성, 지속성) 트랜잭션을 통해 강력한 일관성을 보장한다. 카산드라는 BASE(Basically Available, Soft state, Eventually consistent) 철학에 기반한 결과적 일관성을 기본으로 하며, 필요에 따라 일관성 수준을 조정할 수 있다.31
16.1.2 vs. MongoDB
MongoDB는 문서 지향(Document-Oriented) NoSQL 데이터베이스의 대표 주자로, 카산드라와는 다른 접근 방식을 취한다.
- 아키텍처: MongoDB는 복제본 세트(Replica Set)라는 Master-Slave 구조를 기본으로 한다. 하나의 프라이머리 노드가 쓰기 작업을 처리하고, 이를 세컨더리 노드들이 비동기적으로 복제한다. 이는 카산드라의 모든 노드가 쓰기 작업을 처리할 수 있는 Masterless 구조와 대조된다.42
- 데이터 모델: MongoDB는 데이터를 유연한 JSON과 유사한 BSON(Binary JSON) 문서 형태로 저장한다. 중첩된 문서와 배열을 지원하여 복잡한 계층 구조의 데이터를 직관적으로 표현할 수 있다. 이는 카산드라의 테이블 기반 와이드 컬럼 모델과 구별된다.6
- 쿼리 유연성: MongoDB는 풍부한 쿼리 언어, 강력한 집계 파이프라인(Aggregation Framework), 그리고 다양한 종류의 보조 인덱스를 지원하여 개발자에게 높은 유연성을 제공한다. 반면, 카산드라는 파티션 키 기반의 단순 조회에 최적화되어 있으며, 쿼리 유연성은 상대적으로 낮다.42
16.1.3 vs. HBase
HBase 역시 Google Bigtable의 영향을 받은 와이드 컬럼 스토어이지만, 아키텍처적으로 카산드라와 중요한 차이점을 보인다.
- 아키텍처 및 의존성: HBase는 독립적으로 동작하는 카산드라와 달리, Hadoop 생태계에 깊이 의존한다. 데이터 저장을 위해 HDFS(Hadoop Distributed File System)를, 클러스터 코디네이션을 위해 Zookeeper를, 리소스 관리를 위해 YARN을 필요로 하는 Master-Slave 구조를 가진다.93 이는 HBase의 설치와 운영을 더 복잡하게 만드는 요인이다.
- 일관성 (CAP 이론): HBase는 Zookeeper를 통해 강력한 일관성을 보장하는 CP(Consistency, Partition Tolerance) 시스템으로 분류된다. 반면, 카산드라는 가용성을 우선시하는 AP 시스템이다.93
- 성능 특성: 일반적으로 HBase는 대규모 데이터셋에 대한 랜덤 읽기 성능에 강점을 보이며, 카산드라는 극단적인 쓰기 처리량에 더 최적화되어 있다.93
- 사용 편의성: 카산드라는 SQL과 유사한 CQL을 제공하여 상대적으로 배우기 쉬운 반면, HBase는 자체 Java API를 사용하거나 SQL 인터페이스를 위해 Apache Phoenix와 같은 추가적인 계층을 필요로 한다.6
16.1.4 표 3: 주요 NoSQL 및 분산 SQL 데이터베이스 아키텍처 비교
| 구분 | Cassandra | MongoDB | HBase | CockroachDB | ScyllaDB |
|---|---|---|---|---|---|
| 패러다임 | Wide-Column | Document | Wide-Column | Distributed SQL | Wide-Column (C++) |
| 아키텍처 | Masterless (P2P) | Master-Slave | Master-Slave (Hadoop) | Symmetric (P2P) | Masterless (Shard-per-core) |
| CAP 분류 | AP (Tunable) | CP (Default) | CP | CP | AP (Tunable) |
| 일관성 모델 | 결과적/조정 가능 | 강력함 (기본) | 강력함 | 직렬화 가능 ACID | 결과적/조정 가능 |
| 트랜잭션 | LWT (제한적) | Multi-document ACID | 제한적 | 분산 ACID | LWT (개선됨) |
| 주요 강점 | 쓰기 처리량/가용성 | 개발 유연성/쿼리 | 대용량 랜덤 읽기 | 분산 트랜잭션 | 극한의 성능 |
이 표는 복잡한 분산 데이터베이스 시장의 지형도를 한눈에 보여준다. 각 시스템의 핵심적인 아키텍처 철학과 그로 인해 발생하는 특성들을 명확하게 대비시켜, 독자가 자신의 요구사항에 맞는 기술을 전략적으로 평가하고 선택하는 데 필요한 핵심 정보를 제공한다.
16.2 vs. ScyllaDB, CockroachDB: 성능, 트랜잭션, 일관성 모델 비교
16.2.1 vs. ScyllaDB
ScyllaDB는 ’더 빠른 카산드라’를 목표로 등장한 데이터베이스로, 카산드라와 API 수준에서 호환되지만 내부 구현은 완전히 다르다.
- 아키텍처 및 언어: 가장 큰 차이점은 ScyllaDB가 JVM 기반의 Java 대신 C++로 완전히 새로 작성되었다는 점이다.4 이를 통해 JVM의 가비지 컬렉션(GC)으로 인한 예측 불가능한 성능 저하 문제를 원천적으로 제거했다. 또한, ’Shard-per-core’라는 독자적인 아키텍처를 채택하여, 각 CPU 코어가 독립적인 스레드, 메모리, 디스크 I/O 큐를 가지고 데이터를 처리한다. 이는 하드웨어의 성능을 거의 100% 활용하여 멀티코어 환경에서 최고의 성능을 이끌어내기 위한 설계이다.4
- 성능: 이러한 아키텍처 차이로 인해, 동일한 하드웨어에서 ScyllaDB는 일반적으로 카산드라보다 훨씬 낮은 지연 시간과 수 배에서 수십 배 높은 처리량을 보인다.96
- 기능 및 발전: ScyllaDB는 카산드라와의 호환성을 유지하면서도, 자동 튜닝, 워크로드 우선순위 지정, 향상된 컴팩션 전략(ICS) 등 운영 편의성과 성능을 높이는 독자적인 기능들을 더 빠르게 도입하고 있다.4
16.2.2 vs. CockroachDB
CockroachDB는 카산드라와 같은 NoSQL이 아닌, 분산 환경에서 RDBMS의 장점을 제공하려는 ‘분산 SQL(Distributed SQL)’ 또는 ‘NewSQL’ 데이터베이스이다.
- 패러다임 및 일관성: CockroachDB의 핵심 설계 목표는 지리적으로 분산된 환경에서도 강력한 일관성과 ACID 트랜잭션을 보장하는 것이다.99 이를 위해 Paxos/Raft와 같은 합의 알고리즘을 기반으로 동작하며, CAP 이론상 CP 시스템에 해당한다. 이는 가용성을 최우선으로 하는 카산드라의 AP 철학과 정면으로 배치된다.
- 트랜잭션: CockroachDB는 여러 행과 테이블에 걸친 분산 ACID 트랜잭션을 완벽하게 지원한다. 반면, 카산드라의 트랜잭션 지원은 단일 파티션 내에서의 조건부 업데이트를 위한 ’경량 트랜잭션(Lightweight Transactions, LWT)’으로 매우 제한적이다.32
- 쿼리 언어: CockroachDB는 PostgreSQL과 와이어 프로토콜 수준에서 호환되는 표준 SQL을 지원한다. 이는 JOIN, 서브쿼리, 외래 키 등 RDBMS 개발자에게 익숙한 모든 기능을 사용할 수 있음을 의미한다.99 카산드라의 CQL은 이와 비교해 기능이 매우 제한적이다.
17. 최신 동향 및 미래 전망
아파치 카산드라는 지난 10여 년간 대규모 분산 데이터베이스의 대명사로 자리매김해왔지만, 기술 생태계의 빠른 변화에 발맞춰 끊임없이 진화하고 있다. 현재 카산드라의 발전 방향은 크게 ’운영 자동화’와 ’AI 워크로드 지원’이라는 두 가지 축을 중심으로 전개되고 있다. 이는 클라우드 네이티브 환경으로의 전환과 인공지능 시대의 새로운 데이터 패러다임이라는 거대한 기술 트렌드에 적극적으로 부응하려는 전략적 움직임으로 해석된다.
17.1 쿠버네티스 환경에서의 카산드라 운영: K8ssandra Operator
과거 카산드라는 강력한 성능에도 불구하고 복잡한 설치, 구성, 그리고 수동적인 관리(repair 등)로 인해 운영이 어렵다는 인식이 있었다. 그러나 애플리케이션 배포 및 운영의 중심이 쿠버네티스로 이동하면서, 카산드라와 같은 상태 저장(stateful) 애플리케이션도 쿠버네티스 위에서 ‘선언적으로’ 관리하려는 요구가 커졌다.
K8ssandra는 이러한 요구에 대한 카산드라 커뮤니티의 공식적인 답변이다. K8ssandra는 쿠버네티스에서 카산드라를 프로덕션 수준으로 운영하기 위한 모든 구성 요소를 통합한 오픈소스 플랫폼이다.100
K8ssandra의 핵심은 Cass Operator라는 쿠버네티스 오퍼레이터이다.100 오퍼레이터는 쿠버네티스의 커스텀 리소스(Custom Resource)를 통해 특정 애플리케이션(이 경우 카산드라)의 배포, 스케일링, 장애 복구, 업그레이드와 같은 복잡한 운영 작업을 자동화하는 소프트웨어이다. 개발자나 운영자는 복잡한 절차를 직접 수행하는 대신, “3개의 노드로 구성된 데이터센터를 만들어줘“와 같은 원하는 상태를 YAML 파일에 선언하기만 하면, Cass Operator가 나머지 모든 작업을 자동으로 처리해준다.100
K8ssandra는 Cass Operator를 기반으로, 다음과 같은 필수 운영 도구들을 하나의 패키지로 통합하여 제공한다 100:
- 모니터링: Prometheus 및 Grafana를 통한 지표 수집 및 시각화
- 복구(Repair): Reaper를 이용한 자동화된 안티-엔트로피 복구 스케줄링
- 백업/복원: Medusa를 이용한 클라우드 스토리지(S3 등) 기반의 스냅샷 백업 및 복원
- API 게이트웨이: Stargate를 통해 CQL 외에 REST, GraphQL 등 다양한 API 인터페이스 제공
K8ssandra의 등장은 카산드라 운영의 패러다임을 바꾸고 있다. 복잡한 수동 작업을 자동화하고 클라우드 네이티브 환경에 완벽하게 통합함으로써, 개발자들이 인프라 관리의 부담에서 벗어나 애플리케이션 개발에 더 집중할 수 있도록 돕는다.
17.2 카산드라 5.0의 신기능과 AI/ML 워크로드 지원
2024년 9월에 공식 릴리즈된 Cassandra 5.0은 AI 및 머신러닝 시대의 새로운 데이터 요구사항에 대응하기 위한 혁신적인 기능들을 대거 탑재한 중요한 이정표이다.10
- Vector Search: Cassandra 5.0의 가장 핵심적인 신기능으로, AI 모델이 생성하는 고차원 벡터 임베딩(vector embedding)을 저장하고, 그 유사도를 기반으로 데이터를 검색하는 ’벡터 검색’을 네이티브로 지원한다.72 이는 근사 최근접 이웃(Approximate Nearest Neighbor, ANN) 알고리즘을 기반으로 하며, Storage Attached Index(SAI)를 통해 구현된다.106 이 기능 덕분에 카산드라는 이제 단순한 데이터 저장소를 넘어, 추천 시스템, 이미지/음성/텍스트 검색, 이상 탐지 등 다양한 AI 애플리케이션의 핵심 백엔드 데이터베이스로 직접 활용될 수 있다.
- Storage Attached Indexes (SAI): 기존의 보조 인덱스(Secondary Index)가 가진 성능 및 확장성 문제를 해결하기 위해 설계된 새로운 인덱싱 메커니즘이다.72 SAI는 인덱스 데이터를 SSTable에 직접 첨부하여 디스크 공간 효율성을 높이고, 다양한 유형의 쿼리(정확한 일치, 범위, 전문 검색 등)를 높은 성능으로 지원한다.
- Unified Compaction Strategy (UCS): 기존의 STCS와 LCS 컴팩션 전략의 장점을 결합한 새로운 하이브리드 전략이다.72 운영자는 단일 전략 내에서 파라미터 조정을 통해 워크로드 특성에 맞게 컴팩션 동작을 미세 조정할 수 있어, 운영의 복잡성을 크게 줄여준다.
- Trie Memtables and SSTables: 스토리지 엔진의 핵심 자료 구조인 멤테이블과 SSTable의 인덱스를 B-Tree에서 Trie 구조로 변경하여, 메모리 사용량을 줄이고, 쓰기 처리량을 향상시키며, 특히 넓은 파티션(wide partition)에 대한 지원을 강화했다.72
- JDK 17 지원: 최신 LTS(Long-Term Support) 버전인 Java 17을 지원하게 됨으로써, ZGC(Z Garbage Collector)와 같은 최신 저지연 GC를 활용할 수 있게 되었다. 이는 대용량 힙 환경에서도 예측 가능하고 안정적인 성능을 제공하는 데 기여한다.72
이러한 기능들은 카산드라가 과거의 명성에 안주하지 않고, 미래 기술 스택의 핵심 구성 요소로 남기 위한 능동적인 변화를 추구하고 있음을 명확히 보여준다.
17.3 CEP(Cassandra Enhancement Proposals)를 통해 본 미래 방향성
CEP는 카산드라 커뮤니티가 새로운 주요 기능을 제안, 토론하고, 개발 방향을 결정하는 공식적인 프로세스이다.107 현재 논의되거나 최근에 구현된 CEP들을 살펴보면 카산드라의 미래를 엿볼 수 있다.
- Auto Repair (CEP-37): 운영자의 가장 큰 부담 중 하나였던 repair 작업을 컴팩션처럼 시스템이 자동으로, 지능적으로 수행하도록 만드는 기능이다.108 클러스터의 부하 상태를 감지하여 repair 강도를 조절하고, 디스크 공간과 같은 가드레일을 통해 안정성을 확보하는 등, 운영 자동화의 정점을 목표로 한다.
- ACID 트랜잭션 및 일관성 강화: 2024년 사용자 설문조사에서 ACID 트랜잭션에 대한 요구가 높게 나타난 만큼, 커뮤니티 내에서도 일관성 모델을 강화하려는 논의가 지속되고 있다.109 과거에 제안되었던 범용 트랜잭션 지원이나 Pluggable Storage Engine(다양한 스토리지 엔진을 교체 가능하게 하는 기능)과 같은 CEP들은 카산드라가 전통적인 NoSQL의 한계를 넘어 더 넓은 영역의 워크로드를 포용하려는 장기적인 비전을 가지고 있음을 시사한다.110
결론적으로, 카산드라의 미래 방향성은 명확하다. K8ssandra를 통해 ’어디서든 쉽게 운영’할 수 있는 클라우드 네이티브 데이터베이스로 거듭나고 있으며, Vector Search와 같은 AI 지원 기능을 통해 ’무엇이든 저장하고 지능적으로 검색’할 수 있는 차세대 데이터 플랫폼으로 진화하고 있다.
18. 결론: 카산드라의 전략적 활용 방안
아파치 카산드라는 지난 십수 년간 대규모 분산 데이터 처리 분야에서 그 가치를 입증해 온 강력하고 성숙한 데이터베이스이다. 그 설계 철학은 명확하다: 극단적인 수준의 확장성과 상시 가용성을 확보하기 위해 전통적인 데이터베이스의 제약(강력한 일관성, JOIN, 정규화)을 과감히 포기하는 것이다. 이러한 명확한 트레이드오프는 카산드라를 모든 문제에 대한 만병통치약이 아닌, 특정 유형의 문제에 대한 최적의 해법으로 만든다.
18.1 핵심 강점과 약점 요약
강점:
- 선형적 확장성: 클러스터에 노드를 추가하는 것만으로 읽기/쓰기 처리량이 예측 가능하게 증가하여, 페타바이트 규모의 데이터와 초당 수백만 건의 요청을 처리할 수 있다.4
- 고가용성 및 내결함성: 마스터 없는 P2P 아키텍처와 데이터 복제 메커니즘을 통해 단일 장애 지점이 없으며, 개별 노드, 랙, 심지어 데이터센터 전체의 장애에도 서비스 중단 없이 동작한다.3
- 뛰어난 쓰기 성능: LSM-Tree 기반 스토리지 엔진은 모든 쓰기 작업을 순차 I/O로 처리하여 매우 높은 쓰기 처리량을 제공한다.90
- 지리적 분산: 다중 데이터센터 복제를 네이티브로 지원하여, 전 세계 사용자를 대상으로 하는 글로벌 서비스에서 데이터를 사용자 가까이에 배치함으로써 낮은 지연 시간을 실현할 수 있다.5
- 유연성: 조정 가능한 일관성 모델을 통해 애플리케이션의 요구사항에 따라 성능과 데이터 정합성 사이의 균형을 쿼리 단위로 선택할 수 있으며, 스키마 변경이 자유롭다.4
약점:
- 제한된 쿼리 능력: JOIN, 복잡한 집계(aggregation), 서브쿼리 등을 지원하지 않아 분석적인 쿼리에는 부적합하다.3
- 데이터 모델링의 복잡성: ’쿼리 기반 설계’와 ’비정규화’라는, RDBMS와는 다른 패러다임에 대한 깊은 이해가 필요하다. 잘못된 데이터 모델링은 심각한 성능 문제로 이어진다.39
- 결과적 일관성: 강력한 일관성을 기본으로 요구하는 금융 거래나 재고 관리 시스템과 같은 일부 애플리케이션에는 부적합할 수 있다.
- 운영의 복잡성: 툼스톤, 대용량 파티션, 컴팩션 튜닝 등 성능 유지를 위해 고려해야 할 내부적인 요소들이 많아 운영에 전문성이 요구된다 (단, K8ssandra와 같은 도구들이 이를 완화하고 있다).62
18.2 적합한 사용 사례 제시
이러한 강점과 약점을 고려할 때, 카산드라는 다음과 같은 특성을 가진 사용 사례에서 그 진가를 발휘한다.
- 대규모 쓰기 중심 워크로드: 초당 수많은 데이터가 지속적으로 유입되는 시나리오에 이상적이다.
- 사례: IoT 센서 데이터 수집, 실시간 로그 데이터 저장, 사용자 활동 추적, 메시징 시스템.113 Discord는 수조 개의 메시지를 저장하고 관리하기 위해 카산드라를 사용한다.1
- 지리적으로 분산된 글로벌 서비스: 전 세계에 분산된 데이터센터를 통해 모든 사용자에게 빠르고 안정적인 서비스를 제공해야 하는 경우.
- 사례: 소셜 미디어 피드, 스트리밍 서비스의 사용자 프로필 및 시청 기록 관리, 글로벌 전자상거래 플랫폼.5 Instagram은 전 세계 사용자의 데이터를 각 지역 데이터센터에 복제하여 빠른 서비스를 제공한다.115
- 제로 다운타임이 필수적인 ‘Always-On’ 시스템: 단 한 순간의 서비스 중단도 허용되지 않는 미션 크리티컬 애플리케이션.
- 사례: 사기 탐지 시스템, 실시간 개인화 및 추천 엔진, 규정 준수를 위한 감사 로깅.3 Netflix는 스트리밍 데이터 처리와 감사 로깅에 카산드라를 활용하여 제로 다운타임을 달성한다.115
- 시계열 데이터 관리: TimeWindowCompactionStrategy(TWCS)와 Time-To-Live(TTL) 기능을 결합하여 대규모 시계열 데이터를 효율적으로 저장하고, 오래된 데이터를 자동으로 폐기하는 데 매우 효과적이다.113
- AI/ML 애플리케이션 백엔드: Cassandra 5.0부터 네이티브로 지원되는 Vector Search 기능을 활용하여, 대규모 벡터 임베딩을 저장하고 유사성 기반 검색을 수행하는 AI 기반 추천 시스템, 이미지 검색, 자연어 처리 애플리케이션의 백엔드로 활용될 수 있다.106
결론적으로, 아파치 카산드라는 RDBMS를 대체하는 범용 데이터베이스가 아니다. 대신, 데이터의 규모가 기존 시스템의 한계를 넘어서고, 중단 없는 서비스와 빠른 쓰기 성능이 비즈니스의 성패를 좌우하는 특정 영역에서 타의 추종을 불허하는 강력한 솔루션이다. 카산드라를 성공적으로 도입하기 위해서는 그 아키텍처적 트레이드오프를 명확히 이해하고, ’쿼리 기반 설계’라는 원칙에 따라 데이터 모델을 신중하게 설계하는 것이 무엇보다 중요하다.
19. 참고 자료
- Apache Cassandra - 아파치 카산드라 - 나무위키, https://namu.wiki/w/Apache%20Cassandra
- Cassandra Basics, https://cassandra.apache.org/_/cassandra-basics.html
- [Cassandra] Apache Cassandra 란? - 좌충우돌 개발자의 기록 - 티스토리, https://lovelushi.tistory.com/entry/Cassandra-Apache-Cassandra-%EB%9E%80
- Apache Cassandra vs ScyllaDB: 분산 NoSQL 데이터베이스의 성능과 호환성 비교 - 재능넷, https://www.jaenung.net/tree/9536
- Apache Cassandra | Apache Cassandra Documentation, https://cassandra.apache.org/_/index.html
- Navigating the Cassandra vs. MongoDB vs. Hbase Landscape - Aimore Technologies, https://www.aimoretechnologies.com/cassandra-vs-mongodb-vs-hbase/
- Apache Cassandra란?. 오늘은 Distributed System에 관심있는 사람들이라면 당연히… | by Heonjang Lee | Medium, https://medium.com/@heonjang.lee96/apache-cassandra%EB%9E%80-759d68899e5b
- [Cassandra] 아파치 카산드라란? - 윤복로그 - 티스토리, https://goyunji.tistory.com/95
- 아파치 카산드라 - 오늘의AI위키, AI가 만드는 백과사전, https://wiki.onul.works/w/%EC%95%84%ED%8C%8C%EC%B9%98_%EC%B9%B4%EC%82%B0%EB%93%9C%EB%9D%BC
- Apache Cassandra - Wikipedia, https://en.wikipedia.org/wiki/Apache_Cassandra
- Apache Cassandra (r17 판) - 아파치 카산드라 - 나무위키, https://namu.wiki/w/Apache%20Cassandra?uuid=15e8dcfc-3e46-4058-9e2b-f34e68fcf3f2
- [대규모 시스템 설계 기초 정리 + Cassandra] 안정 해시 설계 + Cassandra Virtual Node, https://willseungh0.tistory.com/174
- Dynamo | Apache Cassandra Documentation, https://cassandra.apache.org/doc/latest/cassandra/architecture/dynamo.html
- Partitioning in Apache Cassandra - Medium, https://medium.com/@sadigrzazada20/partitioning-in-apache-cassandra-9eda05439a52
- Gossip Protocol in Cassandra - GeeksforGeeks, https://www.geeksforgeeks.org/dbms/gossip-protocol-in-cassandra/
- Working of GOSSIP protocol in Cassandra - GeeksforGeeks, https://www.geeksforgeeks.org/dbms/working-of-gossip-protocol-in-cassandra/
- Gossip Protocol Explained - High Scalability, https://highscalability.com/gossip-protocol-explained/
- Dynamo | Apache Cassandra Documentation, https://cassandra.apache.org/doc/3.11/cassandra/architecture/dynamo.html
- Request Routing and Snitches in Cassandra | Baeldung, https://www.baeldung.com/cassandra-request-routing-snitches
- Introduction to Snitches in Cassandra - Education Nest, https://community.educationnest.com/knowledge-base/introduction-to-snitches-in-cassandra/
- Snitches in Cassandra - GeeksforGeeks, https://www.geeksforgeeks.org/dbms/snitches-in-cassandra/
- Snitch - ScyllaDB University, https://university.scylladb.com/courses/scylla-essentials-overview/lessons/architecture/topic/snitch/
- Snitch | Apache Cassandra Documentation, https://cassandra.apache.org/doc/4.1/cassandra/architecture/snitch.html
- Cassandra Deep Dive for System Design Interviews, https://www.hellointerview.com/learn/system-design/deep-dives/cassandra
- Apache Cassandra Data Partitioning | Instaclustr, https://www.instaclustr.com/blog/cassandra-data-partitioning/
- About Cassandra Replication Factor and Consistency Level | Edge for Private Cloud v4.17.09 | Apigee Docs, https://docs.apigee.com/private-cloud/v4.17.09/about-cassandra-replication-factor-and-consistency-level
- Apache Cassandra - Tutorial 7 - Replication, Data Centers and Racks - YouTube, https://www.youtube.com/watch?v=yyVbDBSMnUw
- Cassandra vs MongoDB: Using CAP Theorem | Instaclustr, https://www.instaclustr.com/blog/cassandra-vs-mongodb/
- How Apache Cassandra® Balances Consistency, Availability, and Performance - DataStax, https://www.datastax.com/blog/how-apache-cassandratm-balances-consistency-availability-and-performance
- The CAP Theorem | Learn Cassandra - teddyma, https://teddyma.gitbooks.io/learncassandra/content/about/the_cap_theorem.html
- MongoDB vs Cassandra vs RDBMS, where do they stand in the CAP theorem? - Bikas Katwal, https://bikas-katwal.medium.com/mongodb-vs-cassandra-vs-rdbms-where-do-they-stand-in-the-cap-theorem-1bae779a7a15
- Overview | Apache Cassandra Documentation, https://cassandra.apache.org/doc/latest/cassandra/architecture/overview.html
- 아파치 카산드라 살펴보기, 설명, 기본 개념 - 데브원영, https://blog.voidmainvoid.net/466
- What is Cassandra Query Language (CQL)? Definition & FAQs | ScyllaDB, https://www.scylladb.com/glossary/cassandra-query-language-cql/
- Cassandra Query Language (CQL) | CQL for DataStax Hyper …, https://docs.datastax.com/en/cql/hcd/index.html
- What is Cassandra Partition Key? Definition & FAQs | ScyllaDB, https://www.scylladb.com/glossary/cassandra-partition-key/
- Partitioning in Azure Cosmos DB for Apache Cassandra | Microsoft Learn, https://learn.microsoft.com/en-us/azure/cosmos-db/cassandra/partitioning
- What is Cassandra Clustering Key? Definition & FAQs | ScyllaDB, https://www.scylladb.com/glossary/cassandra-clustering-key/
- Apache Cassandra Data Modeling Best Practices | Instaclustr, https://www.instaclustr.com/blog/cassandra-data-modeling/
- Cassandra Data Modeling Best Practices, Part 1 - Innovation at eBay, https://innovation.ebayinc.com/stories/cassandra-data-modeling-best-practices-part-1/
- What is a Cassandra Data Model? Definition & FAQs | ScyllaDB, https://www.scylladb.com/glossary/cassandra-data-model/
- Cassandra vs MongoDB: Everything You Need to Know | Integrate.io, https://www.integrate.io/blog/cassandra-vs-mongodb/
- RDBMS design | Apache Cassandra Documentation, https://cassandra.apache.org/doc/latest/cassandra/developing/data-modeling/data-modeling_rdbms.html
- Advanced Cassandra Data Modeling and Cluster Management | by Rajat Singh - Medium, https://medium.com/@sinrajat43/advanced-cassandra-data-modeling-and-cluster-management-5ed2df76f803
- Basic Rules of Apache Cassandra® Data Modeling - DataStax, https://www.datastax.com/blog/basic-rules-cassandra-data-modeling
- Are client-side JOINs preferred in Cassandra? - DBA Stack Exchange, https://dba.stackexchange.com/questions/316544/are-client-side-joins-preferred-in-cassandra
- How to use joins in Cassandra database? - Stack Overflow, https://stackoverflow.com/questions/52255787/how-to-use-joins-in-cassandra-database
- Cassandra Query Language (CQL) Explained - CelerData, https://celerdata.com/glossary/cassandra-query-language-cql
- Introduction to Cassandra Query Language | CQL for Cassandra 2.1 - DataStax Docs, https://docs.datastax.com/en/cql-oss/3.1/cql/cql_intro_c.html
- Useful CQL query in Cassandra - GeeksforGeeks, https://www.geeksforgeeks.org/dbms/useful-cql-query-in-cassandra/
- Cassandra Query Language (CQL) quickstart - DataStax Docs, https://docs.datastax.com/en/cql/hcd/get-started/cql-quickstart.html
- Apache Cassandra tutorial: Cheat sheet, basic setup and vector search - Instaclustr, https://www.instaclustr.com/education/apache-cassandra/apache-cassandra-tutorial-cheat-sheet-basic-setup-and-vector-search/
- What Is a Log-Structured Merge Tree (LSM Tree)? - Aerospike, https://aerospike.com/blog/log-structured-merge-tree-explained/
- What is a Log Structured Merge Tree? Definition & FAQs | ScyllaDB, https://www.scylladb.com/glossary/log-structured-merge-tree/
- Log-structured merge-tree - Wikipedia, https://en.wikipedia.org/wiki/Log-structured_merge-tree
- Storage Engine | Apache Cassandra Documentation, https://cassandra.apache.org/doc/latest/cassandra/architecture/storage-engine.html
- Building an LSM-Tree Storage Engine from Scratch - DEV Community, https://dev.to/justlorain/building-an-lsm-tree-storage-engine-from-scratch-3eom
- How is data read? | Apache Cassandra 2.2 - DataStax Docs, https://docs.datastax.com/en/cassandra-oss/2.2/cassandra/dml/dmlAboutReads.html
- Bloom Filters | Apache Cassandra Documentation, https://cassandra.apache.org/doc/4.0/cassandra/operating/bloom_filters.html
- Anatomy of Cassandra’s Read Operation - Design Gurus, https://www.designgurus.io/course-play/grokking-the-advanced-system-design-interview/doc/anatomy-of-cassandras-read-operation
- Bloom Filters: A Deep Dive into Probabilistic Data Structures - DEV Community, https://dev.to/ashokan/bloom-filters-a-deep-dive-into-probabilistic-data-structures-5gii
- What are Tombstones in Cassandra and Why Are There Too Many?, https://digitalis.io/post/what-are-tombstones-in-cassandra-and-why-are-there-too-many
- Managing Tombstones in Apache Cassandra - Instaclustr, https://www.instaclustr.com/support/documentation/cassandra/using-cassandra/managing-tombstones-in-cassandra/
- Part 1: The Hidden Cost of Deletion – How Tombstones Work in ScyllaDB - Datanised, https://datanised.com/2025/07/01/part-1-the-hidden-cost-of-deletion-how-tombstones-work-in-scylladb/
- Cassandra Tombstones: The Data Graveyard Slowing Down Your Queries - Medium, https://medium.com/@harinibooma/cassandra-tombstones-the-data-graveyard-slowing-down-your-queries-e6044240a1e2
- Tombstones in Apache Cassandra® | Aiven docs, https://aiven.io/docs/products/cassandra/concepts/tombstones
- Compaction | Apache Cassandra Documentation, https://cassandra.apache.org/doc/4.1/cassandra/operating/compaction/index.html
- What is a Cassandra Compaction Strategy? Definition & FAQs | ScyllaDB, https://www.scylladb.com/glossary/cassandra-compaction-strategy/
- What is Cassandra Compaction? Definition & FAQs | ScyllaDB, https://www.scylladb.com/glossary/cassandra-compaction/
- Deep Dive into Cassandra Compaction Strategies | by Sevanthi …, https://medium.com/@sevanthi404rt/deep-dive-into-cassandra-compaction-strategies-4eb76316ebdf
- Leveled Compaction in Apache Cassandra - DataStax, https://www.datastax.com/blog/leveled-compaction-apache-cassandra
- Apache Cassandra™ 5: The features that really count. | AxonOps, https://axonops.com/blog/apache-cassandra-5-the-features-that-really-count/
- Leveled Compaction Strategy (LCS) | Apache Cassandra Documentation, https://cassandra.apache.org/doc/latest/cassandra/managing/operating/compaction/lcs.html
- TWCS part 1 - how does it work and when should you use it ? - The Last Pickle, https://thelastpickle.com/blog/2016/12/08/TWCS-part1.html
- Apache Cassandra® 5.0: Moving Toward an AI-Driven Future, https://cassandra.apache.org/_/Apache-Cassandra-5.0-Moving-Toward-an-AI-Driven-Future.html
- Repair | Apache Cassandra Documentation, https://cassandra.apache.org/doc/4.0/cassandra/operating/repair.html
- nodetool repair | Apache Cassandra 3.x - DataStax Docs, https://docs.datastax.com/en/cassandra-oss/3.x/cassandra/tools/toolsRepair.html
- Backup and restore data procedures - Teamwork Cloud 19.0 LTR SP2, https://docs.nomagic.com/spaces/TWCloud190SP2/pages/47089984/Backup+and+restore+data+procedures
- Cassandra Maintenance & Repair Solutions - AxonOps, https://axonops.com/cassandra-maintenance/
- The cassandra.yaml configuration file | Apache Cassandra 2.1 - DataStax Docs, https://docs.datastax.com/en/cassandra-oss/2.1/cassandra/configuration/configCassandra_yaml_r.html
- Monitor Cassandra using the kube-prometheus-stack | K8ssandra …, https://docs.k8ssandra.io/tasks/monitor/prometheus-grafana/
- what to do for performance tuning of Cassandra database? - Cloudera Community, https://community.cloudera.com/t5/Support-Questions/what-to-do-for-performance-tuning-of-Cassandra-database/td-p/134099
- Configure compaction | DataStax Enterprise, https://docs.datastax.com/en/dse/6.9/managing/operations/configure-compaction.html
- Cassandra Configuration and Tuning - RHQ - Red Hat on GitHub, https://docs.jboss.org/author/display/RHQ/Cassandra%20Configuration%20and%20Tuning.html
- Tuning Java resources | Apache Cassandra 3.0 - DataStax Docs, https://docs.datastax.com/en/cassandra-oss/3.0/cassandra/operations/opsTuneJVM.html
- Low Latency Java - Optimisation through Garbage Collector Tuning - Data Intellect, https://dataintellect.com/blog/low-latency-java-optimisation-through-garbage-collector-tuning/
- Main - Main - OpenJDK Wiki, https://wiki.openjdk.org/display/zgc/Main
- Cassandra | Grafana Labs, https://grafana.com/grafana/dashboards/5408-cassandra/
- Configure Grafana to Visualize Metrics Emitted from Azure Managed Instance for Apache Cassandra | Microsoft Learn, https://learn.microsoft.com/en-us/azure/managed-instance-apache-cassandra/visualize-prometheus-grafana
- Apache Cassandra Resources - ScyllaDB, https://www.scylladb.com/learn/apache-cassandra/resources/
- System Design Solutions: When to use Cassandra and when not to | by Sanil Khurana | Geek Culture | Medium, https://medium.com/geekculture/system-design-solutions-when-to-use-cassandra-and-when-not-to-496ba51ef07a
- Apache Cassandra vs MongoDB - ScyllaDB, https://www.scylladb.com/learn/mongodb-database/apache-cassandra-vs-mongodb/
- Cassandra and HBase - Difference Between NoSQL Databases - AWS, https://aws.amazon.com/compare/the-difference-between-cassandra-and-hbase/
- Cassandra vs. MongoDB vs. Hbase: A Comparison of NoSQL Databases | Logz.io, https://logz.io/blog/nosql-database-comparison/
- ScyllaDB vs Apache Cassandra: A Decade of Evolution …, https://hackernoon.com/scylladb-vs-apache-cassandra-a-decade-of-evolution-performance-gains-and-new-capabilities
- ScyllaDB vs. Apache Cassandra, https://www.scylladb.com/compare/scylladb-vs-apache-cassandra/
- NoSQL Database Benchmarks & Testing - ScyllaDB, https://www.scylladb.com/product/benchmarks/
- What to choose: Cassandra especially JDK21 or scylladb with golang - Reddit, https://www.reddit.com/r/cassandra/comments/1i474ug/what_to_choose_cassandra_especially_jdk21_or/
- Why CockroachDB and Apache Cassandra? | Cockroach Labs, https://www.cockroachlabs.com/compare/cassandra-vs-cockroachdb/
- Requirements for running K8ssandra for development - K8ssandra …, https://k8ssandra.io/blog/articles/requirements-for-running-k8ssandra-for-development/
- K8ssandra - K8ssandra, Apache Cassandra® on Kubernetes, https://k8ssandra.io/
- Cass Operator - K8ssandra, Apache Cassandra on Kubernetes, https://docs.k8ssandra.io/components/cass-operator/
- Running K8ssandra | DataStax, https://www.datastax.com/learn/apache-cassandra-operations-in-kubernetes/running-k8ssandra
- Apache Cassandra | Apache Cassandra Documentation, https://cassandra.apache.org/_/blog.html
- Apache Cassandra 5.0 Is Generally Available! - DataStax, https://www.datastax.com/blog/apache-cassandra-5-is-generally-available
- Vector Search in Apache Cassandra® 5.0 - Instaclustr, https://www.instaclustr.com/blog/vector-search-in-apache-cassandra-5-0/
- Meet the Community - Apache Cassandra, https://cassandra.apache.org/_/community.html
- Auto Repair in Apache Cassandra: CEP-37 Scheduler in Action - YouTube, https://www.youtube.com/watch?v=UBVgvIS-gMY
- Apache Cassandra 2024 Wrapped: A Year of Innovation and Growth | DataStax, https://www.datastax.com/blog/apache-cassandra-2024-wrapped-innovation-growth
- The End of the Beginning for Apache Cassandra | by DataStax - Medium, https://datastax.medium.com/the-end-of-the-beginning-for-apache-cassandra-f58b5b4b7504
- Apache Cassandra® vs. PostgreSQL®: An Overview - NetApp Instaclustr, https://www.instaclustr.com/blog/apache-cassandra-vs-postgresql/
- Synthetic Sharding with Cassandra. Or How To Deal With Large Partitions. | by Ryan Svihla, https://foundev.medium.com/synthetic-sharding-in-cassandra-to-deal-with-large-partitions-2124b2fd788b
- Optimizing Cassandra for Time Series Data - Ksolves, https://www.ksolves.com/blog/big-data/optimizing-cassandra-for-time-series-data
- Advanced Time Series Data Modelling | Datastax, https://www.datastax.com/blog/advanced-time-series-data-modelling
- The Best Apache Cassandra® Use Cases: Netflix, SoundCloud & IG …, https://www.datastax.com/blog/exploring-common-apache-cassandra-use-cases
- What is Cassandra Database? | IBM, https://www.ibm.com/think/topics/cassandra