원문: The CAP Theorem With Apache Cassandra® and MongoDB
MongoDB와 Apache Cassandra는 모두 유명한 분산 NoSQL 데이터베이스 시스템입니다. 여기서는 CAP이론과 PACELC이론으로 두 데이터베이스를 분류할 것입니다. 그리고 나서 두 시스템들이 어떻게 프로덕션 환경에서 자신들의 분류에 맞추어질 수 있는지 보여드리겠습니다.
CAP 이론
CAP이론에서는 분산 시스템이 일관성(Consistency), 유효성(Availity), 분리저항(Partition Tolerance) 세 가지의 특성 중 두가지만을 가질 수 있다고 이야기합니다.
일관성 (Consistency): 모든 클라이언트가 같은 데이터를 읽지만 가장 최신의 데이터가 아닐 수 있습니다. 가용성 (Availability): 모든 요청이 에러가 아닌 응답을 주지만, 가장 최신의 데이터가 아닐 수 있습니다. 분리 저항 (Partition Tolerance): 시스템은 네트워크나 노드 중단으로 인한 노드간 통신 장애가 하나 이상 있어도 동작합니다.
분산 시스템은 반드시 분리 저항이어야 하기 때문에 언제나 가용성과 일관성 사이의 선택이 됩니다. 클러스터의 일부분이 사용할 수 없게 된다면 시스템은 둘 중 하나의 상태에 빠지게 됩니다: - 전체 시스템의 가용성이 떨어지더라도 요청을 취소시켜 데이터 일관성을 지킵니다. 이런 시스템들을 CP 시스템이라고 합니다. - 일관적이지 않은 데이터가 전송될 수 있더라도 가용성을 제공합니다. 이런 시스템들을 AP 시스템이라고 합니다.
CAP 이론에 의하면, MongoDB는 CP 시스템이고 Cassandra는 AP 시스템입니다.
CAP 이론은 MongoDB와 Cassandra와 같은 오늘날의 분산 시스템을 매우 단순하게 보여줍니다. 일반적인 상황에서, 가용성과 일관성은 조절이 가능하고 특정 요구사항에 맞춰 설정할 수 있습니다. 하지만 CAP에 어울리게, 한쪽이 늘어나면 다른 쪽이 줄어들 것입니다. 그런 이유에서 MongoDB 또는 Cassandra의 기본 동작이 CP 또는 AP라고 말하는 것이 더 정확할 것입니다. 아래에서 더 자세히 설명하겠습니다.
PACELC 이론
PACELC 이론은 2010년에 Daniel J. Abadi에 의해 제안되었으며 CAP에 대한 두 가지 오해를 바로잡기 위해 제안되었습니다. 1. CAP 이론은 분산 시스템의 동작을 오직 실패 환경에서만 (네트워크 단절) 고려합니다. 2. CAP 이론은 일반적인 작업에서 언제나 일관성과 지연 시간 간의 트레이드오프가 있다는 사실을 고려하지 않습니다.
PACELC는 이렇게 정리합니다: 분산 시스템은 부분적인 중단이 발생했을 때 반드시 가용성(A)와 일관성© 사이에서 선택해야 하고, 그 외(E) 정상적으로 동작할 때에는 지연 시간(L)과 일관성© 사이에서 선택해야 한다는 것입니다.
MongoDB는 PC+EC 시스템으로 분류됩니다. 일반적인 작업과 부분 중단 동안에 MongoDB는 일관성을 강조합니다. Cassandra는 PA+EL 시스템입니다. 부분 중단시에는 가용성을 추구합니다. 일반적인 작업에는 일관성을 희생하고 더 적은 지연 시간을 가져갑니다. 하지만 CAP와 같이, PACELC 역시 기본 동작을 정의합니다.
(번외로 AC 또는 PA+EC인 분산 시스템은 존재하지 않습니다. 이런 분류는 단독 ACID를 준수하는 관계형 데이터베이스 시스템을 정의합니다).
Apache Cassandra vs. MongoDB 아키텍쳐
MongoDB는 NoSQL 도큐먼트 데이터베이스입니다. 이것은 싱글-마스터 분산 시스템으로 비동기 복제를 사용하여 여러 데이터 복제본을 분배함으로 가용성을 높입니다. MongoDB는 mongod를 실행하는 인스턴스들의 그룹으로 같은 데이터를 유지합니다. MongoDB 문서에서는 이 그룹을 레플리카셋이라고 부릅니다. 하지만 단순하게 표현하기 위해 여기서는 MongoDB 클러스터라고 부르겠습니다.
MongoDB 클러스터는 두 종류의 데이터 보유 멤버로 이루어져 있습니다. Primary: primary는 마스터 노드이며 모든 쓰기 작업을 수신합니다. Secondaries: primary에게서 복제된 데이터를 수신하여 동일한 데이터셋을 유지합니다.
기본적으로 primary 멤버가 모든 읽기와 쓰기를 처리합니다. MongoDB는 선택적으로 일부 또는 모든 읽기 작업을 secondary 멤버에게 보낼 수 있습니다. 쓰기 작업은 반드시 primary에게 보내야 합니다.
primary 멤버가 중단되면 secondary 멤버들 중에서 새로운 primary를 선택하기 전까지 모든 쓰기 작업이 멈추게 됩니다. MongoDB 문서에 의하면 최대 12초까지 걸릴 수 있습니다.
클러스터는 가용성을 늘리기 위해 지리적으로 떨어진 데이터센터 간에 분산될 수 있습니다. MongoDB 레플리카셋의 최대 크기는 50멤버입니다.
Cassandra 클러스터는 노드라고도 불리는 인스턴스들이 p2p로 연결된 “아무것도 공유하지 않는” 분산 구조의 집합입니다. 마스터 노드가 따로 존재하지 않고 모든 노드가 모든 데이터베이스 작업들을 하며 각자 클라이언트 요청을 처리할 수 있습니다. 데이터는 파티션 키의 일관적인 해시를 기준으로 노드들에 파티션됩니다. 파티션은 하나 또는 여러 row들을 가지고 있으며 각 노드는 한 개 이상의 파티션을 가집니다. 하지만 파티션은 한번에 하나의 노드에만 존재할 수 있습니다.
데이터에는 얼마나 많은 복사본을 만들지 정하는 복제 변수가 있습니다. 복사본들은 자동적으로 다른 노드에 저장됩니다.
클라이언트에게서 요청을 받는 첫번째 노드를 coordinator라고 합니다. 데이터를 가지고 있는 노드에 이 요청을 전달하는 것이 coordinator의 임무이며 그 결과를 받는 것도 coordinator입니다. 클러스터의 어느 노드던지 coordinator가 될 수 있습니다.
일관성
MongoDB는 기본적으로 강한 일관성 시스템입니다. 쓰기 작업이 끝나면 이후의 읽기 작업들은 최신 값을 반환합니다.
카산드라는 기본적으로 최종 일관성 시스템입니다. 쓰기 작업이 끝나고 다른 변경 사항이 없다면 결국에는 최신 데이터가 반환될 것입니다.
MongoDB 역시 읽기 작업이 secondary 멤버에서 처리될 때 최종 일관성 시스템이 된다는 것을 염두에 두시기 바랍니다. 그 원인은 바로 복제 랙입니다(primary에 데이터가 기록되는 시점과 secondary에서 데이터가 사용 가능해지는 시점 사이의 딜레이). 랙이 길어질수록 읽기 작업이 일관적이지 않은 데이터를 반환할 확률이 높아집니다.
설정 가능한 일관성
MongoDB와 Cassandra 모두 일관성을 설정할 수 있습니다. 그 말인즉슨, 특정 요구사항을 위해 일관성과 가용성을 조절할 수 있다는 것입니다. 각각의 읽기/쓰기 작업은 성공하기 위해서 확인받아야 할 레플리카의 수를 정의하고 있습니다. MonogDB에서는 read concern과 write concern이라고 부릅니다. Cassandra에서는 작업의 consistency level이라고 합니다. 각각의 정의들은 아래에 설명되어 있습니다.
(생략)
마지막 설정은 강한 일관성을 얻는 대신 모든 분리 저항을 잃게 되는 극단적인 예제입니다. 레플리카 하나가 중단되면 쿼리가 실패하게 되는 것입니다.
반대로 MongoDB는 read concern과 write concern을 매우 낮게 설정해서 최종 일관성이 되도록 할 수도 있습니다.
read/write concern의 Majority는 Cassandra의 쿼럼 일관성 레벨과는 다릅니다. Majority는 대다수의 노드에 커밋된 데이터만을 반환합니다. Cassandra는 쿼럼에서 커밋되지 않은 데이터를 읽어옵니다.
두 시스템 모두 일부 제약 아래 선형화 가능한 일관성 제한으로 작업을 보낼 수 있습니다.
MongoDB에서는 majority write concern과 “linearizable” read concern의 조합으로 선형화 일관성을 제공합니다. 하지만 선형화 가능한 읽기를 하려면 반드시 primary에서 수행해야 합니다.
Cassandra는 변형된 paxos 합의 프로토콜을 사용하여 경량 트랜잭션을 구현했습니다. 경량 트랜잭션은 SERIAL 또는 LOCAL_SERIAL 일관성 레벨을 사용합니다(QUORUM 또는 LOCAL_QUORUM과 동일).
일반 작업에서 일관성 상실
Cassandra와 MongoDB는 여러 데이터 복사본을 분산하는 식으로 가용성을 증가시킵니다. 이 복사본은 일반 작업 중에 일관적이지 않는 경우가 있을 수 있습니다. 하지만 앞으로 보게 되겠지만 Cassandra는 백그라운드 처리를 통해 이런 비일관성을 해결합니다.
MongoDB의 복제 렉으로 인해 primary와 secondary 멤버 간에 비일관성이 생기는 경우 유일한 해결 방법은 secondary 멤버가 갱신될 때까지 기다리는 것입니다. MongoDB 4.2에서는 렉이 설정 가능한 임계점을 넘을 경우 복제 속도를 조절할 수 있습니다.
하지만 secondary의 데이터가 너무 오래되었을 경우 유일한 해결책은 수동으로 멤버를 동기화하는 것인데, 데이터를 전부 지우고 멤버를 초기화시켜 클러스터의 다른 멤버에게서 최근 데이터를 복사하거나 스냅샷 백업에서 복원하는 식으로 이루어집니다.
Cassandra는 두 개의 백그라운드 프로세스를 사용하여 재시작이나 데이터 복원 없이도 레플리카들의 일관되지 않은 데이터를 동기화합니다: 읽기 복구와 힌트로 말이죠.
레플리카가 읽기 요청에 일관되지 않은 데이터를 반환하려고 하는 것을 Cassandra가 알게 되면 read repair(읽기 복구)라고 하는 백그라운드 프로세스가 가장 최근에 쓰여진 데이터를 선택하도록 하여 클라이언트에게 전달하게 됩니다.
Cassandra 노드 하나가 오프라인이 되면 coordinator는 사용할 수 없게 된 레플리카를 자신의 로컬 파일시스템에 실패한 쓰기 작업들을 힌트로 임시 저장하게 됩니다. 만약 (기본 세 시간이 만료인) 힌트가 만료되지 않았다면 레플리카가 돌아왔을 때 쓰여지는데, 이 프로세스를 hinted handoffs라고 합니다.
Anti-entropy repairs (복구라고도 하는)는 레플리카 간의 데이터를 수동으로 동기화하는 프로세스입니다. 복구를 실행하는 것은 Cassandra 클러스터의 주기적인 유지보수의 일부입니다.
장애 상황에서 일관성 상실
MongoDB의 primary 멤버에 장애가 생기는 경우 새로운 primary가 선출될 때까지 모든 쓰기 작업을 중지함으로 일관성을 유지합니다. 장애가 생겨 복제되지 않은 primary로의 쓰기는 모두 해당 노드가 secondary로 돌아가게 될 때 롤백됩니다. MongoDB 최신 버전(4.0 이후)에서는 롤백 중에 롤백 파일을 생성합니다.
Cassandra 노드에 장애가 생긴 경우 작업은 계속되며 실패한 쓰기 작업은 coordinator에 힌트로 임시 저장됩니다. 힌트가 만료되지 않았다면 노드가 다시 돌아왔을 때 적용됩니다.
가용성
MongoDB와 Cassandra 모두 데이터에 여러 복사본을 복제함으로 가용성을 확보합니다. 복사본이 많을수록 가용성이 높아집니다. 클러스터 역시 지리적으로 다른 데이터 센터에 분산하여 더욱 향상된 가용성을 가질 수 있습니다.
MongoDB 클러스터는 7개의 투표 멤버를 넘지 않는 한도에서 최대 50 멤버로 되어있습니다. Cassandra에는 노드 수에 강한 제한이 없지만 복제 변수를 너무 높게 잡으면 성능과 저장 용량에 페널티가 있을 수 있습니다. 일반적인 복제 변수는 대부분의 클러스터에서 3이며 높은 가용성이 필요한 경우 5로 하기도 합니다. 반대로 데이터가 언제든 다시 생성할 수 있어 가용성이 덜 중요하다면 복제 변수를 낮춰 용량 및 성능 향상을 가질 수도 있습니다.
장애 저항
MongoDB 클러스터의 primary 멤버가 electionTimeoutMillis(기본 10초) 이상 사용 불가인 경우 secondary 멤버들이 새 primary 멤버를 정하기 위해 투표를 합니다. 이 투표는 대다수의 멤버에 도달할 때까지 이루어집니다.
MongoDB는 이 최대 12초까지 걸리는 투표 중에는 부분적으로만 서비스가 동작합니다: 1. 새 primary가 선출될 때까지는 어떤 쓰기 작업도 허용되지 않습니다. 2. secondary의 majority 만큼의 멤버들이 온라인이고 secondary에서의 읽기가 활성화된 경우 secondary에서 데이터를 읽는 것이 가능합니다.
Cassandra의 모든 노드들은 peer이기 때문에 Cassandra 클러스터는 지정된 일관성 레벨에 부합하다면 여러 레플리카가 내려가더라도 버틸 수 있습니다. 심지어 대다수의 레플리카가 내려가는 경우에도 기본 일관성 레벨을 ONE 또는 LOCAL_ONE으로 하여 작업을 지속시킬 수 있습니다.
여러 데이터 센터로 장애 저항하기
MongoDB와 Cassandra 클러스터 모두 높은 가용성을 위해 지리적으로 다른 데이터 센터로 확장할 수 있습니다. 만약 한 데이터 센터에 장애가 있더라도 다른 데이터 센터를 사용하여 작업을 계속할 수 있습니다.
MongoDB가 데이터센터 장애에 대응하는 방법은 데이터센터들에 배치된 멤버의 수에 달려 있습니다. primary 서버가 있는 데이터 센터에 장애가 생기면 새로운 primary가 선출될 때까지 가용성이 사라집니다.
데이터가 여러 데이터센터에 분산되어 있다면 데이터센터 중 하나에 장애가 있더라도 읽기 작업은 여전히 가능합니다. 만약 소수의 멤버들이 다운되더라도 클러스터에서는 읽기 및 쓰기가 모두 정상적으로 동작합니다. 만약 대다수의 데이터센터가 다운된다면 읽기 작업만 가능하게 됩니다.
세 개의 데이터 센터가 있고 어느 데이터 센터 하나가 내려가도 다른 멤버들이 투표를 할 수 있기 때문에 쓰기 가능합니다.
Cassandra 클러스터의 장애 저항은 데이터 센터 수와 얼마나 많은 일관성을 희생할지 정하는 복제 변수에 의존합니다. 지정한 일관성 레벨에 맞기만 하면 작업은 계속할 수 있습니다.
Cassandra vs. MongoDB 결론
CAP 및 PACELC 이론을 근거로 MongoDB는 가용성보다는 일관성을 보장하는 분산 시스템이고 Cassandra는 가용성을 추구하는 시스템으로 분류됩니다. 하지만 이 분류는 단지 두 시스템 모두의 기본 동작만을 설명할 뿐입니다. MongoDB는 primary 멤버에 읽기와 쓰기를 모두 할 때에만 강한 일관성을 제공합니다. primary 멤버에만 읽기가 제한되더라도 read/write concern에 따라 일관성을 낮출 수 있습니다. Cassandra 역시 가용성과 지연 시간을 합리적으로 조절하여 강한 일관성을 만들 수 있습니다.
'강좌번역' 카테고리의 다른 글
[번역] 톤 매핑 (2) | 2022.02.11 |
---|---|
[번역] 자동 노출 (0) | 2022.02.11 |
물리 개체의 PID제어 (0) | 2018.10.17 |
그래픽스 API 선택하기 (2) | 2015.09.06 |