[DynamoDB] 3. Read Consistency, Operation · Transaction

조성우·2025년 10월 9일

DynamoDB

목록 보기
3/4
post-thumbnail

1. CAP 이론

분산 시스템인 NoSQL은 대부분 CAP 이론을 따른다. 이는 분산 시스템이 일관성(Consistency), 가용성(Availability), 분할 내성(Partition Tolerance) 세 가지 중 두 가지만 보장할 수 있다는 원칙이다.

분산 네트워크 환경에서 시스템은 가용성(AP) 또는 일관성(CP) 중 하나를 우선해야 한다. DynamoDB는 이 CAP 이론을 위배하지 않으면서도 요청별로 사용자가 두 가지 모드(Strong Consistency or Eventual Consistency) 중 하나를 선택할 수 있도록 하여 AP와 CP 모두를 지원한다.


2. Read Consistency (읽기 일관성)

A. Strong Consistency (강한 일관성)

: 가장 최신 상태의 데이터를 반환하도록 보장한다.

  1. 작동 방식: DynamoDB는 높은 가용성을 위해 데이터를 최소 세 개 이상의 AWS 가용 영역(AZ)에 복제하며, 이는 리더-팔로워 토폴로지로 운영된다. 모든 쓰기 요청은 리더에서만 처리되는데, 강한 일관성 읽기는 반드시 이 리더 복제본에 의해 처리된다.
  2. CAP: CP를 지원한다.
  3. 가용성 트레이드오프: 네트워크 분할 시, DynamoDB가 리더 복제본과의 연결을 설정하거나 리더를 인식하는 데 어려움을 겪으면, 강한 일관성 읽기 요청은 서버 오류(500 error)가 발생할 수 있다. (최종 일관성 읽기에 비해 상대적으로 낮은 가용성)
  4. 격리 수준: 동시 쓰기 요청과 강한 일관성 읽기 요청은 SERIALIZABLE 수준으로 처리된다. 즉, 각 요청은 다른 요청이 동시에 처리되지 않은 것처럼 작동한다.

B. Eventual Consistency (최종 일관성)

: 강한 일관성 읽기보다 빠르고 비용 효율적이지만, 쓰기 직후에 데이터가 최신 상태가 아닐 수 있다.

  1. 작동 방식: 최종 일관성 읽기 요청은 파티션의 복제 그룹 내 세 개의 복제본 중 하나에 접속하여 데이터를 제공받는다. DynamoDB의 쓰기 작업은 리더와 최소 한 개의 팔로워에게 복제가 완료되면 성공으로 간주한다. 따라서 최신 데이터를 반환할 확률은 3분의 2이다. (아직 최신 쓰기를 반영하지 못한 복제본에서 쓰기 요청 직후에 읽으면, 오래된(stale) 데이터일 수 있다.)
  2. CAP: AP를 지원한다. (강한 일관성보다 높은 가용성을 보장)
  3. 비용 효율성: 강한 일관성 읽기의 절반의 비용만 청구된다. 강한 일관성 읽기가 4KB당 1 RCU(읽기 용량 단위)가 청구되는 데 비해, 최종 일관성 읽기는 4KB당 0.5 RCU가 청구된다.
  4. 처리량: 세 복제본 중 어느 하나에서 읽기를 처리할 수 있으므로, 파티션당 문서에서의 한도(3,000 RCU/초)보다 더 높은 읽기 처리량을 가져갈 수 있다.

DynamoDB는 요청 시 간단한 Boolean flag를 사용하여 일관성 수준을 설정할 수 있도록 한다.

모드장점단점적합한 사례
강한 일관성최신 데이터 보장. SERIALIZABLE 격리 수준비용이 두 배 높음. 가용성이 떨어질 수 있음.은행 거래 검증, 실시간 재고 관리 등.
최종 일관성비용 효율적(절반). 높은 가용성 및 처리량쓰기 직후 데이터가 stale data일 수 있음.소셜 미디어 좋아요/댓글 수, 개인 프로필 세부 정보 업데이트 등.

3. Operation

DynamoDB가 지원하는 read API는 다음과 같다.

  1. GetItem
  2. BatchGetItem
  3. Query
  4. Scan
  5. ExecuteStatement, BatchExecuteStatement (PartiQL)
  6. TransactGetItems, ExecuteTransaction (트랜잭션 API)

A. GetItem

가장 간단한 키-값 조회(key-value lookup)를 제공한다.
잘못된 키를 제공하면 오류가 아닌 빈 목록을 반환한다.

제한 사항: GetItem보조 인덱스(GSI or LSI)에서는 수행될 수 없다. 보조 인덱스는 다른 키 구조를 사용하므로 (예: GSI는 다른 attribute를 Partition Key나 Sort Key로 가질 수 있다), 보조 인덱스의 키만으로는 '항목이 유일하다'는 보장이 없다.

B. BatchGetItem

개별 GetItem 요청들을 배치로 묶어 실행할 수 있게 해준다.

단일 네트워크 요청으로 최대 100개의 개별 GetItem 요청을 처리합니다.
(network round trips를 줄여 밀리초 단위의 성능을 최적화한다.)

C. Query

항목 컬렉션(동일한 PK를 공유하는 항목 그룹)을 읽는 가장 효율적인 방법이다.

동일한 파티션 키(PK) 값을 가지지만 정렬 키(SK) 값이 다를 수 있는 하나 이상의 항목을 검색한다. (PK 값과 1:M 관계를 공유하는 항목을 처리할 때 유용함)

  • 정렬 · 필터링: 결과 항목은 정렬 키 값에 따라 오름차순(기본값) 또는 내림차순으로 정렬되며, begins_with()와 같은 함수를 정렬 키에 사용하여 여러 관련 엔터티를 단일 요청으로 검색할 수 있다.
  • 응답 크기 제한 · 페이지네이션:Query 응답은 최대 1MB의 항목으로 제한됩니다. 이 제한을 초과하면 LastEvaluatedKey 요소가 반환되어, 클라이언트가 후속 요청을 통해 다음 페이지의 결과를 요청해야 합니다.

D. Scan

DynamoDB 테이블 데이터에 액세스하는, 유연하지만 Resource-intensive Operation(많은 자원을 요구)이다.

  • SCAN allows filtering on every attribute in the data, supporting functions such as contains(), logical AND/OR operators, and more.
  • 성능 및 비용: 대규모 테이블에서 완료하는 데 시간이 오래 걸릴 수 있으며, 모든 항목을 순회하므로 테이블의 모든 항목 크기만큼 RCU를 소비한다. (지연 시간에 민감한 OLTP 애플리케이션에서는 피해야 한다)
  • 사례: 접근 빈도가 낮고 작업 완료 시간에 제약이 없는 시나리오(주간/월간 보고서 생성, 야간 백그라운드 프로세스의 데이터 유효성 검사)에 적합하다.
  • 스캔 유형: 순차 스캔(Sequential Scan), 병렬 스캔(Parallel Scan)을 지원함

E. PartiQL Read Operation

--생략--


4. 트랜잭션과 원자성

DynamoDB의 단일 항목 작업은 본질적으로 ACID이지만, 특정 트랜잭션 API는 다중 항목 작업에도 ACID를 보장한다.

DynamoDB는 기존 RDBMS와 달리 명시적인 트랜잭션 시작/종료 지시어가 없다.

DynamoDB 트랜잭션의 경우, all-or-nothing으로 실행되어야 하는 모든 Put, Update, Delete 작업은 단일 트랜잭션 쓰기 요청에 포함되어야 한다. 마찬가지로, all-or-nothing으로 실행되어야 하는 모든 읽기 작업은 단일 트랜잭션 읽기 요청에 포함되어야 한다.

읽기 또는 쓰기 트랜잭션 요청에 포함된 항목이 다른 진행 중인 트랜잭션의 일부인 경우, 최신 트랜잭션 요청은 TransactionConflict Exception과 함께 즉시 취소된다.

쓰기 트랜잭션 요청에는 조건 검사(condition check) 외의 작업으로는 오직 쓰기 작업만 허용된다. 즉, DynamoDB의 쓰기 트랜잭션 API 중 하나인 TransactWriteItems API에는 다음 작업이 포함될 수 있다.

  • Put: 새 항목을 삽입하거나, 이미 존재하는 경우 조건식 없이 항목을 덮어씀
  • Update: 기존 항목을 업데이트하거나, 존재하지 않는 경우 조건식 없이 새 항목을 생성함
  • Delete: 기존 항목을 삭제하며, 항목이 존재하지 않더라도 조건식 없이 성공 처리됨
  • ConditionCheck: 개별 항목에 대한 유효성 검사

단일 TransactWriteItems 요청은 Put, Update, Delete, ConditionCheck를
조합하여 최대 100개의 작업을 허용한다.

트랜잭션 내부 매커니즘: 2단계 프로토콜

  1. PREPARE: 트랜잭션 읽기 또는 쓰기 요청 내의 모든 작업은 오류, 조건 검사, 스로틀링 예외, 트랜잭션 충돌에 대해 검증된다. 검증에 실패하면 COMMIT은 절대 실행되지 않고 해당하는 예외와 함께 트랜잭션이 거부된다.
  2. COMMIT: 검증된 작업들은 트랜잭션에 기여하는 모든 백엔드 노드에 의해 병렬로 커밋된다.

5. 트랜잭션 API 사용 시 고려 사항

  • 다중 항목 ACID 준수가 절대적으로 필요한 경우
    금융 거래 검증이나 복잡한 일관성 요구 사항이 있는 시나리오와 같이, read-after-write consistencyall-or-nothing이 필수적일 때 사용된다.

  • 복잡한 작업의 회피
    만약 ACID가 필수적이지 않다면, 벌크 업데이트(BatchWriteItem, BatchGetItem)와 같은 비트랜잭션 연산이 더 적합하며, 비용 절감, 평균 지연 시간 개선, 복잡성 감소 및 고가용성을 제공할 수 있다.

여러 항목을 한 번에 쓰면서 all-or-nothing 동작을 보장하려는 경우, 읽기 작업에도 트랜잭션 API를 사용하는 것이 바람직하다. 트랜잭션 쓰기 중 COMMIT 단계가 병렬로 실행되기 때문입니다.

DynamoDB는 가용 영역(AZ)에 걸쳐 분산된 저장 노드로 구성된 분산 시스템이기 때문에, COMMIT 단계에서 각 노드가 병렬로 요청을 독립적으로 처리한다.

따라서, 트랜잭션이 아직 진행 중인 상태에서 트랜잭션에 포함된 항목에 대해 비트랜잭션 읽기를 수행하면, 일부 노드는 COMMIT을 완료했지만 다른 노드는 완료하지 못한 상태일 수 있다.
따라서 이 경우, 최신 커밋된 데이터를 읽을 수도, 읽지 못할 수도 있는 상황이 발생할 수 있다.

0개의 댓글