Amazon Dynamo(2007), DynamoDB, Aurora DSQL의 아키텍처적 관계를 내구성, 일관성, 프로그래밍 모델, 가용성과 지연 관점에서 비교하며, 지난 20년간의 학습과 인프라 발전을 바탕으로 초기 주장들을 재평가한다.
이름 짓기는 어렵습니다, 맞죠?
사람들은 종종 고전적인 2007년 SOSP 논문에 기술된 Amazon Dynamo, AWS의 서버리스 분산 NoSQL 데이터베이스인 Amazon DynamoDB, 그리고 AWS의 서버리스 분산 SQL 데이터베이스인 Aurora DSQL 사이의 아키텍처적 관계에 대해 묻곤 합니다. 이 주제에 대해 할 말은 정말 많지만, 여기서는 몇 가지 핵심 특성을 시스템들이 어떻게 달성하는지 비교하는 것으로 시작하겠습니다.
이 글의 주요 참고문헌은 다음과 같습니다.
내구성
여기서 살펴보는 데이터베이스들은 서로 다른 수준의 내구성을 제공하지만, 셋 모두 단일 호스트 장애 시 데이터를 잃지 않도록 설계되어 있습니다. Dynamo는 일관 해싱(consistent hashing) 방식을 활용하여 해시 링에서 순서대로 여러 호스트에 데이터를 복제함으로써 이를 달성합니다:
높은 가용성과 내구성을 달성하기 위해 Dynamo는 데이터를 여러 호스트에 복제한다. 각 데이터 항목은 N개의 호스트에 복제된다. … 각 키 k는 코디네이터 노드에 할당된다[]. 코디네이터는 자신의 범위에 속하는 데이터 항목의 복제를 담당한다. 자신의 범위에 있는 각 키를 로컬에 저장하는 것 외에도, 코디네이터는 해시 링에서 시계 방향으로 이어지는 N-1개의 후속 노드에 이러한 키를 복제한다.
Dynamo와 마찬가지로 DynamoDB도 해시 링에서 각 개별 항목에 노드를 할당합니다. 하지만 유사점은 거기까지입니다. 링의 여러 노드에 복제하는 대신, DynamoDB에서는 각 노드가 여러 AZ의 여러 서버로 구성된 복제 그룹(replica group)이며 Paxos를 사용해 데이터를 복제합니다. 각 항목은 링에 _N_번 나타나는 대신 한 번만 나타나고, 여러 노드에 퍼뜨리는 대신 내결함성 있는 노드에 의존합니다.
쓰기 요청을 수신하면, 쓰기 대상 키의 복제 그룹 리더가 선행 로그(Write-Ahead Log) 레코드를 생성하여 피어(복제본)에게 전송한다. 정족수(quorum)의 피어가 해당 로그 레코드를 자신의 로컬 선행 로그에 영속화하면 애플리케이션에 쓰기 성공을 응답한다.
DynamoDB의 내구성 접근법은 Dynamo에 비해 여러 장점이 있습니다. 첫째, 내구성이 복제 세트(replica set)에 기반하고 복제 세트의 수가 키의 수보다 훨씬 적기 때문에, 시스템이 특정 키의 복제본이 충분치 않은 상황을 더 쉽게 탐지하고 적절히 대응할 수 있습니다2. 둘째, 스케일 업이나 스케일 다운 중에도 내구성 저하가 필요 없습니다. Dynamo에서는 스케일링 시 키의 복제본 집합이 바뀌지만, DynamoDB에서는 복제 세트를 분할(split)하거나 병합(merge)하는 방식으로 스케일링하며 복제본 수가 감소하지 않습니다.
중재자(adjudicator)가 트랜잭션 커밋 가능하다고 결정하면, 복제를 위해 저널(Journal)에 기록합니다. (DSQL 소품: 트랜잭션과 내구성 중에서)
DSQL은 앞의 둘과는 다릅니다. DynamoDB처럼 변경 로그를 복제하기 위해 Paxos 변형을 사용하지만, 스토리지 노드와 분리된 추가 컴포넌트(저널)를 통해 이를 수행합니다. 이는 DynamoDB와 같은 이점을 제공할 뿐 아니라, 읽기와 쓰기의 독립적 확장과 샤드 간 원자적 커밋을 가능하게 합니다. 또한 DSQL은 기본적으로 Dynamo와 DynamoDB의 해시 기반 스키마와 달리 범위 기반 기본 키 샤딩 방식을 사용합니다. 이러한 선택의 트레이드오프는 별도의 글로 다룰 만한 주제입니다.
일관성
Dynamo는 클라이언트에게 오직 최종적 일관성만을 제공합니다.
Dynamo는 최종적 일관성을 제공하며, 업데이트는 비동기적으로 모든 복제본에 전파된다.
다만 복제본이 수렴하도록 노력하며, 논문에서는 다소 혼동스럽게도 이를 일관성(consistency)이라고 부르기도 합니다.
복제본 간 일관성을 유지하기 위해 Dynamo는 정족수 시스템에서 사용하는 것과 유사한 일관성 프로토콜을 사용한다. 이 프로토콜에는 두 가지 핵심 구성 가능한 값 R과 W가 있다. R은 읽기 작업이 성공하려면 참여해야 하는 최소 노드 수, W는 쓰기 작업이 성공하려면 참여해야 하는 최소 노드 수다. R과 W를 R + W > N이 되도록 설정하면 정족수 유사(quorum-like) 시스템이 된다.
R + W > N을 다루는 방식이 논문의 다른 부분에서 말하는 일관성과 잘 맞지 않는 것 같아 다소 혼란스럽습니다. 또한 일부 Dynamo 영감 시스템들이 달성했듯, 더 강한 일관성으로 가는 경로를 제시하기도 합니다.
이에 반해 DynamoDB는 강한 일관성의 쓰기3와 강/약 일관성 중 선택 가능한 읽기를 제공합니다. 선택 방식은 꽤 단순합니다.
오직 리더 복제본만이 쓰기와 강한 일관성 읽기 요청을 처리할 수 있다.
그리고
복제 그룹의 어떤 복제본도 최종적 일관성 읽기를 제공할 수 있다.
이 모델은 깔끔합니다. 최종적 일관성 읽기를 감내할 수 있는 애플리케이션은 더 낮은 비용과 지연을 선택할 수 있고, 모든 쓰기는 강한 일관성을 유지합니다(약한 쓰기를 수용하면서 발생하는 Dynamo의 벡터 시계와 객체 버저닝 같은 복잡성을 피합니다). 또한 애플리케이션 개발자가 정족수 같은 개념을 이해하지 않아도 강한 일관성을 활용할 수 있습니다(사실 많은 개발자들이 잘 모르죠).
반면 DSQL은 물리적 시간과 다중 버전 동시성 제어(MVCC)를 결합해, 장시간 상호작용형 트랜잭션에서도 모든 읽기와 쓰기에 강한 일관성을 제공합니다.
이를 위해 각 트랜잭션을 시작할 때 트랜잭션 시작 시간, 를 선택한다. 우리는 강한 오차 한계를 가진 정확한 시계를 제공하는 EC2의 정밀 시간 인프라를 사용한다. 그런 다음 QP가 스토리지에 대해 수행하는 각 읽기에 대해, 스토리지에 해당 읽기를 의 시점(as of)으로 수행하도록 요청한다. (DSQL 소품: 읽기와 컴퓨트 중에서)
DSQL의 접근은 DynamoDB 대비 두 가지 이점이 있습니다. 강한 일관성 읽기가 어느 스토리지 복제본으로도 갈 수 있고, 작성자(쓰기)를 결코 차단하지 않으면서 상호작용형 트랜잭션에서도 강한 일관성을 유지할 수 있다는 점입니다. 그 대가로는 추가 복잡성과 물리적 시간에 대한 의존이 있습니다. DSQL도 약간 더 낮은 지연으로 약한 일관성 읽기(예: 검사 없이 키의 최신 버전을 바로 읽는 방식)를 제공할 수는 있지만, 현재는 제공하지 않습니다.
프로그래밍 모델
Dynamo는 어떤 형태의 트랜잭션도 제공하지 않는 단순 키-값 저장소입니다:
Dynamo는 어떠한 격리 보장도 제공하지 않으며, 단일 키 업데이트만 허용한다.
DynamoDB는 여러 읽기와 쓰기로 구성되는 원샷 직렬화 가능한 ACID 트랜잭션을 제공합니다. DSQL은 상호작용형 트랜잭션, 완전한 SQL 지원, 풍부한 타입 시스템을 제공하여 가장 풍성한 프로그래밍 모델을 갖습니다.
가용성과 지연 시간
Dynamo 논문은 일관성, 가용성, 지연 시간 간의 트레이드오프에 대해 오늘날의 시점에서는 타당하지 않은 여러 주장을 합니다. 논문 저자들을 지적하려는 것은 아닙니다(몇 분은 제 개인적 친구들이고, 많은 분은 오랜 동료들이기도 합니다). 다만 지난 20년간 분산 데이터베이스 구축에 대해 우리가 많은 것을 배웠다는 점을 말하고 싶습니다. 클라우드 인프라도 크게 발전했습니다.
Amazon에서의 경험에 따르면 ACID 보장을 제공하는 데이터 저장소는 가용성이 낮은 경향이 있다.
이는 2000년대 중반에는 사실이었지만, 오늘날 많은 ACID 시스템은 훌륭한 가용성을 제공합니다. DynamoDB, DSQL, 그리고 Aurora Postgres 같은 시스템이 그렇습니다. DynamoDB와 DSQL은 호스트 장애나 심지어 전체 가용 영역(AZ)의 장애에도 일관성, 내구성, 가용성을 잃지 않습니다.
초기의 복제 데이터베이스 연구들에서 잘 알려졌듯, 네트워크 장애 가능성을 고려하면 강한 일관성과 높은 데이터 가용성을 동시에 달성할 수 없다.
여기서 Dynamo 논문은 가용성과 일관성 간의 본질적 트레이드오프를 강조하기 위해 Bernstein와 Goodman(1984)과 Lindsay 외1(1979)을 인용합니다. 이 결과들이 틀린 것은 아니지만, (제가 예전에 주장했듯이) 실제 실무에서는 Dynamo 논문이 암시하는 만큼 중요하지 않습니다. 강한 일관성 시스템은 다양한 장애( 전체 리전 장애 포함)에서도 훌륭한 가용성을 제공합니다.
Dynamo는 또한 성능을 위해 내구성, 일관성, 가용성 중 일부를 희생하는 선택을 애플리케이션에 허용합니다.
Dynamo의 주요 장점은 클라이언트 애플리케이션이 N, R, W의 값을 조정하여 원하는 수준의 성능, 가용성, 내구성을 달성할 수 있다는 점이다.
이것은 2000년대 중반에는 완전히 합리적이었습니다. 하지만 복제와 장애 상관관계에 대한 더 나은 사고방식, 비약적으로 향상된 시스템 성능(SSD 덕분이죠!), 그리고 훨씬 나아진 데이터센터 네트워크 덕분에, 이런 종류의 조정 가능성은 이제는 그다지 흥미롭지 않습니다. 주목할 점은, 논문에서 논의된 트레이드오프를 전혀 수용하지 않으면서도 Dynamo보다 훨씬 낮은 지연 시간을 DynamoDB와 DSQL이 모두 제공한다는 것입니다.
결론
Amazon Dynamo 논문은 고전입니다. 아직 읽지 않았다면 꼭 읽어보세요. 하지만 시간은 흘렀고, 우리는 많은 것을 배웠으며, 더 좋은 하드웨어와 더 좋은 아이디어를 갖게 되었습니다. 그 결과 Dynamo 논문이 말하는 많은 것들이 이제 실제 세계에서는 잘 맞지 않습니다. 좋은 일입니다!
각주
UpdateItem 호출도 엄밀 직렬화 가능한 원샷 트랜잭션으로 대략 생각할 수 있습니다. 셋째, 성공한 DynamoDB 쓰기는 완전한 내구성을 갖춘 상태로 커밋되며 적절한 수의 복제본에 동기식으로 복제됩니다. 이는 쓰기가 비동기적으로 복제되는 Dynamo와는 다릅니다.