중급5분 분량

DynamoDB 원자 카운터: ADD 작동 방식 및 작동하지 않는 경우

원자 카운터는 단일 위치에 부딪히는 숫자 속성입니다. UpdateItem 호출 — 먼저 읽지 않고 읽기-수정-쓰기 경쟁이 없습니다. DynamoDB가 적용됩니다. 각 도착 순서는 증가하며 두 작가가 서로의 작가를 방해하는 것을 결코 허용하지 않습니다. 카운트.

DynamoDB 원자 카운터란 무엇입니까?

DynamoDB 원자 카운터는 ADD(또는 SET x = x + :n) 업데이트 표현식을 사용하여 단일 UpdateItem 호출로 그 자리에서 증가시키는 숫자 속성입니다. DynamoDB는 서버 측에서 값을 읽고 추가하고 쓰기 때문에 동시 작성자는 업데이트 손실 없이 직렬화합니다. 하지만 멱등성이 아니므로 재시도된 호출은 두 번 증가합니다.

  • 한 번의 호출로 증가하려면 ADD(또는 SET x = x + :n)를 사용합니다. DynamoDB는 다음을 읽습니다. 서버측 추가 및 쓰기 — 동시 호출자가 직렬화하며 업데이트가 손실되지 않습니다.
  • 먼저 읽지 않습니다. SQL에서 SELECT 다음으로 UPDATE를 입력합니다. 여기서는 건너뛰세요 전체 읽기 및 작업은 동시성 하에서 여전히 안전합니다.
  • 원자 카운터는 멱등성이 아닙니다. 재시도된 UpdateItem 증분 다시. 과잉 또는 과소 계산을 허용할 수 없는 경우 를 사용하십시오.
  • 누락된 속성에 대한 ADD는 0에서 시작하므로 첫 번째 증분은 작동 — 시드 쓰기가 필요하지 않습니다.

읽기-수정-쓰기 문제

동영상 조회수를 추적한다고 가정해 보겠습니다. SQL에서 바로 나온 순진한 본능은 다음과 같습니다. GetItem, 앱에 하나를 추가하고, PutItem 새로운 총계를 되돌립니다.

두 명의 시청자가 동시에 플레이를 눌렀습니다. 둘 다 views = 41로 읽혀졌습니다. 둘 다 42라고 씁니다. 당신 두 개가 아닌 하나의 보기로 계산되었습니다. 그것은 잃어버린 업데이트입니다 - 고전적인 동시성 풋건, 교통량이 생길 때까지 표시되지 않습니다.

SQL에서는 UPDATE videos SET views = views + 1로 이를 피하고 데이터베이스에 산술 연산을 수행합니다. DynamoDB는 동일한 움직임을 가지고 있으며 전체입니다. 원자 카운터의 지점.

한 번의 호출로 증가

동영상별 통계 항목을 모델링합니다. 파티션 키 VID#<id>, 정렬 키 STATS#TOTAL, 숫자 play_count 사용:

PKSKplay_count
"VID#9f3a""STATS#TOTAL"41

연극을 등록하려면 ADD 절과 함께 하나의 UpdateItem을 보내십시오.

# UpdateItem
Key               PK = "VID#9f3a", SK = "STATS#TOTAL"
UpdateExpression  ADD play_count :one
Values            :one = 1

DynamoDB는 play_count를 읽고 1을 더한 다음 결과를 단일 서버 측 작업. 다른 작가가 끼어들 창은 없습니다. 동시 플레이는 매번 +10를 생산합니다. 이것이 바로 "원자"가 당신을 구매하는 이유입니다.

이름, 값 및 네 가지 모두와 같은 정확한 표현식을 작성하고 복사할 수 있습니다. 조항 유형 - DynamoDB Expression Builder.

ADDplay_count가 아직 존재하지 않는 경우에도 작동합니다. DynamoDB는 누락된 항목을 처리합니다. 숫자 속성은 0이므로 첫 번째 플레이에서는 1에 생성됩니다. 별도의 종자 없음 쓰다. ([AWS: 업데이트 표현식 사용][upd])

ADD vs SET +: 하나 선택

두 표현식은 동일한 산술을 수행합니다. AWS는 일반적인 용도로 SET를 권장합니다. 다른 SET 액션과 구성되어 더 명확하게 읽혀지기 때문입니다. ([AWS: 업데이트 표현식 사용][upd])

ADD play_count :oneSET play_count = play_count + :one
누락된 속성0부터 시작하여 생성오류 — if_not_exists 필요
데이터 유형숫자와 세트만SET를 통한 숫자(및 기타)
SET와 결합별도 조항하나의 SET 절, 쉼표로 구분됨
AWS 지침카운터에 벌금권장 기본값

속성이 존재하지 않을 수 있고 SET를 원하는 경우 이를 보호하십시오. SET play_count = if_not_exists(play_count, :zero) + :one. ADD을 사용하면 건너뜁니다. 즉 — 0부터 무료로 시드됩니다.

각 증분의 쓰기 비용

us-east-1의 주문형, 각 UpdateItem에는 ADD 청구서 당 1WCU 쓰기 후 항목 크기의 KB입니다(반올림). 900바이트 통계 행 등록된 플레이당 1 WCU 비용; 10개의 동시 플레이가 여전히 10으로 표시됩니다. WCU 전체, 하나가 아님. 여러 파티션에 걸쳐 카운터를 샤딩하면 항목별 WCU 계산을 변경하지 않고 처리량 한도를 조정합니다. 다음을 사용하여 행 크기를 조정합니다. item-size calculator 및 회선 속도 핫 pricing calculator의 경로.

DynoTable에서 해보기

통계 항목을 열어 라이브 카운터를 확인한 다음 분할된 카운터를 굴립니다. SQL Workbench에서 SUMGROUP BY를 사용하여 각 항목의 합계를 확인합니다. STATS#TOTAL#0..N 행. 증분 자체 초안을 작성하려면 웹을 사용하십시오. DynamoDB Expression Builder를 구성하려면 ADD UpdateItem 표현식, 이름 및 값이 포함됩니다.

함정: 카운터는 멱등성이 아니다

원자 카운터는 UpdateItem이 실행될 때마다 **증가합니다. (AWS: 작동 중 항목 포함)

네트워크 오류를 생각해 보세요. 증분을 보내면 연결이 끊어지기 전에 끊어집니다. 응답이 돌아오지만 응답이 도착했는지 여부는 알 수 없습니다. 다시 시도하세요. 만약 첫 번째 호출이 did 성공했습니다. 이제 해당 플레이를 두 번 계산했습니다.

비디오 조회수는 괜찮습니다. 백만 번 재생 중 몇 번 중복 계산해도 문제가 되지 않습니다. AWS는 이 정확한 "방문자 추적" 사례를 정식 사용이라고 부릅니다. 원자 카운터. (AWS: 항목 작업)

정확해야 하는 모든 것에는 적합하지 않습니다: 과도하게 판매할 수 있는 재고, 크레딧을 두 배로 쓸 수 있고 잔액이 손상될 수도 있습니다. 거기에서 조건부 업데이트.

정확성이 필요한 경우: 조건부 업데이트

조건부 업데이트는 멱등성입니다. 동일한 속성을 조건으로 하면 변하는_. play_count에서 42로 증가합니다. 단, 현재 41인 경우에만 해당됩니다.

# UpdateItem
Key                  PK = "VID#9f3a", SK = "STATS#TOTAL"
UpdateExpression     SET play_count = :next
ConditionExpression  play_count = :current
Values               :next = 42, :current = 41

이제 재시도는 안전합니다. 첫 번째 쓰기가 이미 play_count에서 42로 이동했다면, 조건 play_count = 41가 두 번째로 실패하고 아무 것도 바뀌지 않습니다. (AWS: 항목 작업)

비용은 동시성입니다. 두 명의 작가가 동일한 조건으로 경주하면 한 명이 승리함 그리고 한 사람은 재시도할 수 있는 ConditionalCheckFailedException를 얻습니다. — 당신은 정확성을 위한 무조건적인 카운터 처리량. 정확하고 주장됨 카운터는 올바른 거래입니다. 조회수로는 과잉입니다.

함정

  • 1개의 . 단일 카운터 행은 하나의 파티션 키입니다. 바이럴 영상 VID#9f3a / STATS#TOTAL를 두드리면 파티션당 쓰기 한도에 도달할 수 있습니다. 분할: 쓰기를 STATS#TOTAL#0..N에 분산하고 읽기 시 합계를 냅니다.
  • 배치 증분 없음. BatchWriteItem은 넣기/삭제만 가능하며 실행할 수 없습니다. . 카운터는 UpdateItem를 통과하며, 통화 당 하나의 항목. 여러 카운터를 원자적으로 충돌시켜야 하는 경우, TransactWriteItems는 한 번의 요청으로 최대 100개 항목에 대한 업데이트 작업을 실행합니다. 쓰기 비용은 대략 두 배입니다.
  • ADD은 숫자이며 집합만 해당됩니다. 문자열이나 부울을 건드리지 않습니다. 그것은 SET입니다. 전체 내용은 DynamoDB data types를 참조하세요. 속성 모델.

다음 단계

원자 카운터는 쓰기 패턴입니다. 어떻게 읽어 다시 집계하는지는 모델링입니다. 질문 — 유지하려면 single-table design를 참조하세요. 상위 항목 옆에 통계 항목이 있으므로 Query vs Scan 분할된 카운터를 롤업하면 Query가 유지됩니다.

초안을 작성하고 증분을 복사합니다. DynamoDB Expression Builder, 그럼 try DynoTable 자신의 테이블에 대해 원자성 업데이트를 실행하고 카운트가 움직이는 것을 지켜보세요.

업데이트됨