[분산 시스템] CAP 이론 제대로 이해하기 (CAP Theorem) (CAP에 대한 오해를 풀어보자)
NoSQL을 공부하다보면 가장 많이 접하게 되는 단어 중 하나가 CAP이다. 아무래도 NoSQL 스토리지들이 분산 시스템으로 동작하다보니, 이들을 이해하기 위해서는 꼭 알아두어야 할 개념이기 때문이다. 프로젝트 특성에 따라 데이터베이스 솔루션을 선택해야 하는데, 이 때 이 개념을 잘 이해하고 있으면 프로젝트 특성에 맞는 솔루션을 선택하는데 도움이 된다. 근데 이 CAP Theorem은 매우 심플하게 분산 시스템의 성질을 설명해주는 정리 같으면서도 잘못 읽으면 오히려 오해가 생길 위험이 있다. 따라서 CAP이 의미하는 바가 무엇이고, 이 정리가 진정 무엇을 알려주고자 하는지 좀 제대로 이해해보기 위해 글을 쓴다.
참고로 이번 글은 분산시스템과 데이터베이스에 대한 기본적인 이해가 됐다는 전제하에 쓴 글이다. 이해가 잘 안되거나 어려운 용어가 있을 때는 댓글로 남겨주면 관련해서 설명하는 글을 별도로 다루도록 하겠다.
본 글은 다음을 목적으로 작성했다.
(1) CAP에서 각 C, A, P가 의미하는 바가 무엇인지 정리
(2) CAP 정리의 한계 : 셋 중 둘을 선택할 수 있는게 맞는 말인지 (Spoiler: 아님)
들어가며
분산 시스템이란 최소 두 개 이상의 노드가 네트워크를 구성하여 마치 하나의 컴퓨터가 동작하는 것처럼 보이도록 하는 시스템을 의미한다. 대부분의 NoSQL 스토리지들은 분산 시스템으로 동작하고 물리적으로 별개의 노드들이 하나의 시스템을 구성하기 위해 네트워크를 통해 서로 통신하고 동기화한다. 이러한 분산 환경은 데이터베이스 관점에서는 NoSQL과 SQL 데이터베이스를 구분짓는 가장 큰 특성이기도 하다.
분산 시스템은 더 많은 트래픽을 감당할 수 있도록 수평확장이 가능하며 이로 인한 비용 효율을 얻을 수 있고, fault tolerant한 시스템을 구축할 수 있다는 장점들이 있다. 하지만 결국 여러 대의 노드들이 동작하는 물리적 환경으로 인해 어쩔 수 없이 발생하는 여러 한계점도 존재한다. 따라서 CAP Theorem은 분산환경의 성질을 크게 3가지 특성으로 나누어 설명하고, 각 특성들의 상충관계에 대해 설명하면서 분산 시스템을 선택할 때 고려해야할 주요 특성들을 논한다. CAP을 이해했다고 분산시스템의 모든 것을 이해할 수 있는 것은 아니지만 그래도 입문자 입장에서 분산시스템에 대한 기본적인 이해를 하는데는 큰 도움이 되기 때문에 여러 논란이 있지만 공부해보는 것이 좋다고 생각한다.
자 그럼 한번 들어가보자!!
CAP 각각 들여다보기
Consistency(일관성)
우선 CAP 정리에서의 C는 ACID의 C와는 다른 개념이다. (ACID에 대해 궁금하다면 내 블로그의 다른 글들을 읽어보자)
ACID의 C는 데이터베이스에 정의된 데이터 타입, Contraints등이 언제나 일관성있게 유지되고 이 일관성이 깨지지 않아야 한다는 것을 의미한다. 예를 들어 A계좌에서 B계좌로 돈을 전송하고, B계좌에서 A계좌로 전송하는 등 여러 트랜잭션이 발생한다 하더라도, A+B의 돈의 양은 항상 같아야 한다(consistent state)
반면에 CAP에서의 C는 분산 시스템 하에 동작하는 모든 노드들은 항상 동일한 데이터를 가지고 있어야 한다는 의미다. 다시 말해 분산 시스템에 2개의 노드가 동작하고 있다면, 둘 중 어디에 요청하든 동일한 데이터가 리턴된다는 의미다. 이를 또 다르게 표현하면 2개의 노드가 모두 Write을 허용한다는 전제 하에, 어디에 Write을 하든 모두 동기화가 돼야한다. 즉 Write이 성공적으로 된 것으로 인정하려면 해당 operation의 결과가 다른 모든 노드로 복제돼야 한다.
전통적인 RDBMS들은 분산 시스템이 아닌 단일 서버를 통해 C를 보장하는 반면 NoSQL 데이터베이스들은 여러 개의 노드가 동시에 돌아가기 때문에, replication lag이 당연히 발생할 수 밖에 없고, 따라서 같은 시간에 모든 노드들이 같은 데이터를 가지는건 당연히 불가능하다. 우주의 법칙을 깨트리는 거랄까. 따라서 "우리가 느끼지 못할 정도로" 혹은 "우리가 발견하지 못할 정도로" 혹은 "동시라고 느낄만큼" 일관적이게 유지한다 정도로 이해해두자.
Availability(가용성)
Availability는 쉽게 말해서 분산 시스템하에 동작하는 여러 노드 중 하나가 장애가 발생하거나 꺼지더라도 계속해서 데이터베이스에 READ, WRITE이 가능해야 한다는 것을 의미한다. 항상 서비스가 가능해야 한다는 의미로 쉽게 이해할 수 있는 대목이다.
Partition Tolerance
사실 CAP Theorem에 있어서 가장 많은 오해와 잘못된 해석이 발생하게 되는 가장 큰 이유가 Partition Tolerance에 대한 정의 때문이다.
Partition Tolerance란 분산 시스템에서 네트워크 장애로 인해 노드 간에 연결이 단절되는 등의 이유로 network partition(Split-Brain)이 발생해도 시스템이 계속해서 동작해야 함을 의미한다. 사실 이 세상에 완벽하게 네트워크 장애가 발생하지 않는 시스템은 없기 때문에 분산 시스템 하에서는 사실 필수적으로 고려돼야한다. CAP 정리를 정리한 몇몇 글들을 읽어보면 P를 선택할 수 있는 것처럼 말하지만 P는 현실적으로 생각했을 때 무조건 선택될 수 밖에 없는 특성이다.
앞에서 잠깐 Split-Brain이라는 용어를 사용했는데, Split Brain이란 네트워크 파티션으로 인해 시스템이 여러 조각으로 쪼개져서 각각이 스스로를 Primary로 여기는 상태를 의미한다. 즉 Partition Tolerance란 이런 현상이 발생했을 때에도 정상 동작할 수 있어야 함을 의미한다.
먼저 Split-Brain이 무엇인지 한번 알아보자. {A, B, C, D, E} 노드들이 하나의 클러스터를 이루고 있다가 네트워크 단절로 인해 {A, B}, {C, D, E} 이렇게 두 개의 그룹으로 나뉘어지는 케이스를 생각해보자. 이때는 A와 B 끼리만 서로 통신이 가능하고, 또다른 그룹인 C, D, E 끼리만 통신이 가능한 상태다. 이 나뉘어진 두 그룹은 서로가 Primary라고 생각하는 바람에 이중으로 클러스터가 실행되게 된다. 따라서 WRITE이 어느 한 그룹의 노드에서만 수행되면서 다른 그룹에 데이터가 동기화되지 못해 나중에(Eventually) 노드간의 통신이 정상화 됐을때 data에 충돌이 발생해 inconsistent한 상태가 될 수 있다. 이때 분산 시스템은 특정 그룹에만 변경된 state를 동기화하여 데이터의 consistency와 integrity를 보장해주어야 한다. 여기서 해결방안 까지 자세히 다루지 않겠지만 대표적인 해결방안으로 쿼럼을 적용하는 방법이 있다. 쉽게 얘기해 시스템에서 합의를 위한 최소한의 투표수를 가진 소그룹을 쿼럼이라고 할 수 있는데, 이때 홀수의 수로 쿼럼을 구성(클러스터를 구성)하고 최소 절반 이상의 노드의 동의를 얻어야 데이터베이스에 특정 operation을 허용하는 식의 방법으로 Split-Brain문제를 해결할 수 있다. 이렇게 하면 오직 하나의 active partition만이 클러스터에 존재할 수 있기 때문에 data inconsistency를 방지할 수 있다. 또한 홀수로 설정하는 이유는 무승부를 방지하고 과반수가 가능하게 하기 위함임은 참고하자.
참고로 말하자면 분산 시스템에서 노드 끼리 통신할 때 timeout이 발생하는 경우도 network partition에 해당한다. 무조건 network partition = split brain이다 이런식으로 생각할 필요는 없다.
CAP중 두개를 선택할 수 있다고?
위의 글을 읽었다면 아마 예상했겠지만 CAP Theorem에서 P는 필수불가결하게 선택돼야 하는 요소다. 따라서 몇몇 DB들은 본인들이 P를 포기하고 CA를 보장한다고 하긴 하지만 사실 이는 불가능하다고 봐야한다. P를 포기한다면 네트워크 장애를 그냥 두거나 네트워크 장애가 절대 발생하지 않는 시스템을 구축해야 하는데 둘 다 불가능하다. 따라서 CAP Theorem이 CAP 3개중 2개를 선택할 수 있다라는 식으로 이해해선 안되고 분산 시스템에서 network partition이 발생했을 때(그리고 무조건 발생할꺼임) “Consistency, Availability 이 둘 중에 무엇을 보장하면서 정상동작할 것인가 선택해!” 라고 이해하는게 바람직하다. 즉, CAP에서 선택할 수 있는 두 가지 옵션은 CP, AP라고 할 수 있다. 근데 그렇다고 무조건 한쪽으로 치우쳐져야만 하는 것은 아니다. 둘 중에 어느 쪽에 좀 더 치우친 시스템인지 정도로 이해하는게 좋다.
CP 데이터베이스 (MongoDB)
그럼 CP 데이터베이스들은 어떤식으로 동작할까? CP를 보장하는 데이터베이스들은 Consistency가 우선이기 때문에, Network Partition이 발생했을 때, non-consistent한 node는 partition이 해결될때까지 unavailable하게 된다. Consistent한 데이터가 아니면 아예 동작하지 않도록 하는 것이다. 따라서 일관성을 갖기 위해 가용성과 성능을 희생하는 데이터베이스다.
MongoDB가 대표적으로 CP를 만족하는 data store이다. MongoDB에서는 각 replica set마다 single-master만 있을 수 있도록 해서, replica set안에 오직 하나의 primary node만 모든 write operation을 수행할 수 있다. 나머지 replica node들은 secondary node로서 primary node의 operation log를 읽어서 데이터를 복제해간다. 그리고 만약 primary node가 unavailable해지면, secondary node 중에 가장 최근의 log를 읽은 node가 primary node가 되고 나머지 secondary node와 데이터가 동기화 될 때까지는 client가 write request를 수행할 수는 없지만 전체 네트워크에는 consistent한 데이터가 유지될 수 있도록 한다. 기본적으로는 primary node를 통해서만 읽을 수 있고, eventual consistency를 허용한다면 secondary node를 통해서도 데이터를 읽을 수 있다.
참고 : mongoDB에서의 replica set은 다수의 mongod 프로세스의 그룹을 의미한다. 이 그룹 내 mongod 프로세스는 모두 같은 같은 데이터셋을 유지하며, 복수 개의 데이터 셋을 유지함을 통해 고가용성(High Availability)과 다중화(Redundancy)를 제공한다.
AP 데이터베이스 (Cassandra)
이와 다르게 AP 데이터베이스는 Availability가 우선이기 때문에 Network Partition이 발생했을 때 모든 노드들은 다 available한 상태가 된다. 하지만 당연히 Consistency를 일정 부분 포기했기 때문에 몇몇 노드들은 partition이 해결될 때까지 예전 버전의 데이터를 리턴할 수 있다. 그리고 partition이 해결되고 나면 노드간의 데이터를 동기화해 inconsistency를 없애도록 한다.
Cassandra는 MongoDB와는 다르게 masterless 아키텍처를 채택하고 있다. 따라서 CAP 정리와 비교해보자면 AP 데이터베이스다. network partition이 발생했을 때 잠시 inconsistent한 데이터가 발생하지만 빠르게 이를 reconcile하는 방식으로 극복하려고 한다(Eventual Consistency). 그리고 consistency를 일정 수준 포기하고, master가 없기 때문에 살아 있는 노드가 client의 요청을 처리하기 때문에 계속해서 Available하다.
정리하며
이렇게 유명한 CAP Theorem에 대해 알아보았다. 분산환경에서 동작하는 데이터베이스를 선택할 때는 내 프로젝트가 Consistency가 핵심인 기능들이 있는지, 아니면 Availability가 더 중요한지 이 두가지 핵심 요소는 최소한으로 고려하는게 좋다는 차원에서 공부하는게 좋다고 생각한다.
이제 다음으로는 PACELC이론을 공부할 차례다. CAP의 이론만으로는 부족한 설명을 보완하기 위해 만들어졌다. PACELC이론이 더 분산환경의 특성을 더 잘 설명해주긴 하지만 그래도 CAP을 먼저 공부하고 접근하는게 이해에 도움이 될 것이라고 생각한다.
댓글 혹은 좋아요가 많이 눌린다면 더 열심히 공부해서 빠른 시일내에 글을 쓰게 될지도..
참고 자료
https://www.ibm.com/topics/cap-theorem
https://codahale.com/you-cant-sacrifice-partition-tolerance/#errata10221010 (꼭 읽어볼 것 추천)
http://eincs.com/2013/07/misleading-and-truth-of-cap-theorem/
https://blog.naver.com/alice_k106/221310093541
http://happinessoncode.com/2017/07/29/cap-theorem-and-pacelc-theorem/