고급5분 분량

Dynamo 논문에서 DynamoDB까지

2007년 "Dynamo: Amazon's Highly Available Key-value Store" 논문과 여러분이 오늘 호출하는 DynamoDB는 이름과 목표 — 어떤 규모에서도 예측 가능한 성능 — 를 공유하지만, 같은 시스템이 아닙니다. 논문은 여러분이 직접 운영하는 내부의, 최종적 일관성 저장소를 설명했습니다. DynamoDB는 교훈은 지키고 대부분의 기계 장치는 던져 버린 관리형 서비스입니다.

DynamoDB는 Dynamo 논문에 기반하고 있나요?

부분적으로 그렇습니다. DynamoDB는 이름과 핵심 목표 — 어떤 규모에서도 예측 가능한 성능과 높은 가용성 — 를 2007년 Amazon Dynamo 논문에서 가져왔고, 파티션 키 해싱 아이디어는 거의 그대로 지켰습니다. 하지만 이는 다른, 관리형 시스템입니다: 논문의 벡터 시계, 가십 멤버십, 튜닝 가능한 읽기/쓰기 정족수는 사라졌고, AWS가 소유하는 내부 구조로 대체되었습니다.

  • 논문은 사용 편의성이 아니라 가용성을 해결했습니다. 그 일은, 오래된 읽기를 반환하는 대가를 치르더라도, 명절 트래픽 스파이크 동안 절대 쓰기를 거부하지 않는 것이었습니다.
  • DynamoDB는 형태는 지키고 내부는 갈아 치웠습니다. 키의 해시로 파티셔닝되고, AZ에 걸쳐 복제되고, 수평으로 확장됩니다 — 하지만 충돌 해결 내장(벡터 시계, 가십, 읽기 복구)은 사라졌습니다.
  • 더는 손잡이를 튜닝하지 않습니다. 논문의 N, R, W는 하나의 선택이 되었습니다: ConsistentRead 참 또는 거짓. 나머지는 AWS가 소유합니다.
  • 그 멘탈 모델은 여전히 값을 합니다. 혈통을 알면 Scan이 비싼 이유와 GSI 읽기가 뒤처질 수 있는 이유가 설명됩니다 — 둘 다 원래 설계에서 떨어져 나옵니다.

논문이 실제로 해결하던 것

Amazon의 쇼핑 카트는 다운될 수 없었습니다. 부하 아래에서 쓰기를 거부하거나 — 실패한 복제본에서 블록하는 — 관계형 데이터베이스는 용납 불가였습니다. 2007년 Dynamo 논문은 일관성보다 가용성을 택했습니다: 항상 쓰기를 받아들이고, 불일치는 나중에 조정합니다. 그 거래가 아래 모든 것의 뿌리입니다.

단일 마스터 없이 그것을 하려면, Dynamo는 두 질문에 스스로 답해야 했습니다: 키가 어디 사는가, 그리고 읽기나 쓰기가 유효해지기 전에 몇 개의 복사본이 동의해야 하는가?

일관된 해싱: 키가 어디 사는가

논문은 모든 노드를 해시 링 위에 두었습니다. 키의 위치는 그 키의 해시입니다; 그것은 시계 방향으로 다음 노드가 소유하고, 뒤따르는 N-1개 노드에 복제됩니다. 노드를 추가하거나 제거해도 그 이웃들의 키만 재배치될 뿐 — 전체 데이터셋이 아닙니다. 그게 일관된 해싱이며, DynamoDB가 거의 그대로 지킨 하나의 아이디어입니다.

DynamoDB는 여전히 여러분의 파티션 키를 해싱해 어느 물리 파티션이 아이템을 저장할지 결정합니다. 저카디널리티 파티션 키 — 이를테면 값이 둘인 STATUS — 를 고르면, 같은 값을 가진 모든 아이템이 같은 파티션에 안착합니다. 그게 핫 파티션 지뢰이며, 링의 직접적 결과입니다: 해시는 동일한 키를 동일한 집으로 보냅니다.

정족수: 몇 개의 복사본이 동의해야 하는가

논문의 두 번째 손잡이는 정족수였습니다. N개의 복제본으로, 쓰기는 그중 W개가 확인 응답하면 성공하고, 읽기는 그중 R개에 문의합니다. R + W > N으로 설정하면 어떤 읽기든 최신 쓰기를 가진 노드 적어도 하나와 겹칩니다 — 강력한 일관성입니다. 더 낮게 설정하면 신선함을 속도와 가동 시간과 맞바꿉니다.

Dynamo는 "느슨한" 정족수를 운영했습니다: 대상 노드가 다운되어 있으면 쓰기는 대역에게 가서 나중에 되돌려졌습니다(힌트 핸드오프). 충돌하는 버전은 벡터 시계로 태깅되고 읽을 때 애플리케이션이 조정했습니다.

DynamoDB가 지킨 것 vs 바꾼 것

DynamoDB는 목표와 파티셔닝을 물려받은 다음, 원래의 것을 운영하기 어렵게 만든 부분을 삭제했습니다.

관심사2007 Dynamo 논문오늘의 DynamoDB
키 배치일관된 해싱 링파티션 키의 해시 → 관리형 파티션
복제N 노드, 여러분이 선택AZ에 걸친 3 복사본, AWS가 고정
일관성 손잡이R, W 정족수 튜닝하나의 플래그: ConsistentRead
충돌 해결벡터 시계, 읽을 때 앱 측 병합마지막 쓰기 우선; 조건부 쓰기를 옵트인
멤버십피어 간 가십 프로토콜완전 관리형; 여러분에게 보이지 않음
다중 키 연산없음 — 순수 키-값Query, GSI, 트랜잭션이 위에 얹힘

논문의 API는 두 호출이었습니다: get(key)put(key, value). DynamoDB는 같은 키-값 코어 위에 정렬 키, 인덱스, 쿼리를 더했습니다 — 그래서 Query가 값싸고(한 파티션) Scan이 그렇지 않은 것입니다(링이 만든 모든 파티션을 걷습니다).

쓰기가 이동하는 방법, 그때와 지금

아래 흐름은 논문의 정족수 쓰기와 DynamoDB의 관리형 쓰기를 대비합니다. 형태는 운율이 맞고, 책임은 여러분의 코드에서 AWS로 옮겨 갔습니다.

논문: 여러분이 N,R,W를 튜닝DynamoDB: 고정된 3 AZ 복사본put(key, value)키를 링에 해싱N 복제본에 쓰기W 확인 응답 수신?읽을 벡터 시계로 조정마지막 쓰기 우선, 정족수 숨겨짐

논문에서는 정족수 계산과 병합을 여러분이 소유했습니다; DynamoDB에서는 그 아래 절반 전체가 관리되며, 여러분은 요청별로 ConsistentRead만 고릅니다.

혈통이 여러분의 코드로 새어 드는 곳

최종적 일관성 기본값은 논문이 비치는 것입니다. Global Secondary Index는 비동기로 복제되므로, 갓 쓰인 아이템이 한순간 인덱스에서 빠져 있을 수 있습니다 — 같은 "나중에 조정" 거래, 그저 인덱스 계층에서요. 그 지연이 언제 중요한지는 GSI vs LSI를 보세요.

강력한 일관성을 두 가지 방법으로 되삽니다. 베이스 테이블 읽기에 ConsistentRead: true를 쓰거나(그것은 리더 복사본으로 라우팅됩니다), 쓰기를 ConditionExpression으로 보호해 아이템의 현재 상태가 일치할 때만 안착하게 하세요. 하나를 DynamoDB 표현식 빌더에서 스케치하세요 — 예를 들어 attribute_not_exists(PK)PutItem을 삽입 전용 연산으로 만드는 것, 논문의 충돌 탐지를 대신하는 현대적 장치입니다.

기억할 한 가지

논문은 쓰기에 절대 아니라고 하지 않는 것에 최적화했습니다. DynamoDB는 그 편향을 물려받았고, 그래서 기본값이 가용성을 선호하고 강력한 읽기가 더 비싼 것입니다. 단일 테이블 설계에서처럼 단일 파티션 Query를 위해 키를 모델링하고, 정말로 어쩔 수 없을 때만 Scan에 손을 뻗으세요 — 링은 전체 테이블 걷기를 들리는 만큼 비싸게 만듭니다.

DynoTable을 사용해 보세요 — 여러분의 파티션을 점검하고, 필요할 때 일관성 읽기를 돌리고, 여러분 자신의 테이블에 대해 GSI가 따라잡는 것을 지켜보세요.

업데이트됨