Orta5 dakikalık okuma

DynamoDB Atomik Sayaçlar: ADD Nasıl Çalışır, Ne Zaman Çalışmaz

Bir atomic counter, tek bir UpdateItem çağrısıyla yerinde artırdığınız sayısal bir attribute'tur — önce okuma yok, read-modify-write yarışı yok. DynamoDB her artışı geliş sırasına göre uygular ve iki yazıcının birbirinin sayısını asla ezmesine izin vermez.

DynamoDB atomic counter nedir?

Bir DynamoDB atomic counter, tek bir UpdateItem çağrısıyla bir ADD (veya SET x = x + :n) update expression kullanarak yerinde artırdığınız sayısal bir attribute'tur. DynamoDB değeri sunucu tarafında okur, ekler ve yazar, böylece eşzamanlı yazıcılar kayıp güncelleme olmadan serileşir — ancak idempotent değildir, bu yüzden yeniden denenen bir çağrı iki kez artırır.

  • Tek çağrıda artırmak için ADD (veya SET x = x + :n) kullanın. DynamoDB sunucu tarafında okur, ekler ve yazar — eşzamanlı çağıranlar serileşir, kayıp güncelleme yok.
  • Önce okuma yok. SQL'den gelirken SELECT sonra UPDATE yapardınız; burada okumayı tamamen atlarsınız ve işlem eşzamanlılık altında yine de güvenlidir.
  • Atomic counter'lar idempotent değildir. Yeniden denenen bir UpdateItem tekrar artırır. Fazla veya eksik saymaya tolerans gösteremiyorsanız, bir kullanın.
  • Eksik bir attribute üzerinde ADD 0'dan başlar, bu yüzden ilk artış öylece çalışır — tohum yazması gerekmez.

Read-modify-write'ın sorunu

Diyelim ki bir videodaki görüntülemeleri takip ediyorsunuz. Doğrudan SQL'den gelen naif içgüdü şudur: GetItem, uygulamanızda bir ekleyin, yeni toplamı geri PutItem yapın.

İki izleyici aynı anda oynata basar. İkisi de views = 41 okur. İkisi de 42 yazar. Bir görüntüleme saydınız, ikiyi değil. Bu bir kayıp güncellemedir — klasik eşzamanlılık ayak tuzağı, ve trafiğiniz olana kadar ortaya çıkmaz.

SQL'de bunu UPDATE videos SET views = views + 1 ile atlatır, aritmetiği veritabanına iterdiniz. DynamoDB'nin aynı hamlesi var ve bir atomic counter'ın tüm amacı bu.

Tek çağrıda artırma

Video başına bir istatistik item'ı modelleyin. Partition key VID#<id>, sort key STATS#TOTAL, sayısal bir play_count ile:

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

Bir oynatmayı kaydetmek için, bir ADD cümlesiyle tek bir UpdateItem gönderin:

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

DynamoDB play_count'u okur, 1 ekler ve sonucu tek bir sunucu tarafı işleminin içinde yazar. Başka bir yazıcının araya girmesi için bir pencere yoktur. On eşzamanlı oynatma her seferinde +10 üretir — "atomic"in sana satın aldığı budur.

Bu tam expression'ı — adlar, değerler ve dört cümle türünün tümü — DynamoDB Expression Builder ile oluşturup kopyalayabilirsiniz.

ADD, play_count henüz mevcut olmadığında bile çalışır: DynamoDB eksik bir sayısal attribute'u 0 olarak ele alır, bu yüzden ilk oynatma onu 1'de oluşturur. Ayrı bir tohum yazması yok. (AWS: Using update expressions)

ADD ve SET +: birini seçin

İki expression aynı aritmetiği yapar. AWS, genel kullanım için SET'i önerir, çünkü diğer SET eylemleriyle bir araya gelir ve daha açık okunur. (AWS: Using update expressions)

ADD play_count :oneSET play_count = play_count + :one
Eksik attrOluşturur, 0'dan başlarHata — if_not_exists gerekir
Veri türleriYalnızca sayılar ve setlerSayılar (ve daha fazlası) SET ile
SET ile birleştirAyrı cümleTek SET cümlesi, virgülle ayrılmış
AWS rehberliğiCounter'lar için uygunÖnerilen varsayılan

Attribute mevcut olmayabilirse ve SET istiyorsanız, onu koruyun: SET play_count = if_not_exists(play_count, :zero) + :one. ADD ile bunu atlarsınız — bedava 0'dan tohumlar.

Her artışın yazma maliyeti

us-east-1 bölgesinde on-demand modda, ADD içeren her UpdateItem, yazmadan sonraki item boyutunun KB başına 1 WCU'su kadarını faturalandırır (yukarı yuvarlanır). 900 baytlık bir istatistik satırı, kaydedilen her oynatma için 1 WCU tutar; on eşzamanlı oynatma yine toplamda 10 WCU olarak iner, bir değil. Counter'ı partition'lar arasında shard'lamak, item başına WCU matematiğini değiştirmeden verim tavanını yükseltir. Satırı item boyutu hesaplayıcısı ile boyutlandırın ve sıcak yolları fiyatlandırma hesaplayıcısında ölçün.

Bunu DynoTable'da yapın

Canlı counter'ı incelemek için istatistik item'ını açın, sonra her STATS#TOTAL#0..N satırı boyunca toplamı görmek için SQL Workbench'te SUM ve GROUP BY ile sharded bir counter'ı toplayın. Artışın kendisini taslak olarak oluşturmak için, ADD UpdateItem expression'ını adlar ve değerler dahil oluşturmak için web DynamoDB Expression Builder'ı kullanın.

Tuzak: counter'lar idempotent değildir

İşte üretimde ekiplerin canını yakan kısım. Bir atomic counter, UpdateItem her çalıştığında her seferinde artar. (AWS: Working with items)

Bir ağ kesintisi düşünün: artışı gönderirsiniz, yanıt geri gelmeden bağlantı kopar ve inip inmediğini bilmezsiniz. Yeniden denersiniz. İlk çağrı başarılı olduysa, o oynatmayı şimdi iki kez saydınız.

Video görüntülemeleri için bu sorun değil — bir milyon oynatmada birkaç çift-sayım kimseye zarar vermez ve AWS bu tam "ziyaretçi izleme" durumunu atomic counter'ların kanonik kullanımı olarak adlandırır. (AWS: Working with items)

Tam olması gereken hiçbir şey için sorundur: fazla satabileceğiniz envanter, iki kez harcayabileceğiniz krediler, bozabileceğiniz bir bakiye. Orada, koşullu bir güncellemeye başvurun.

Kesinliğe ihtiyaç duyduğunuzda: koşullu güncellemeler

Bir koşullu güncelleme, değiştirdiğiniz aynı attribute üzerine koşullandırırsanız idempotent'tir. play_count'u 42'ye artırın, ancak yalnızca şu anda 41 ise:

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

Şimdi bir yeniden deneme güvenli: ilk yazma play_count'u zaten 42'ye taşıdıysa, play_count = 41 koşulu ikinci seferde başarısız olur ve hiçbir şey değişmez. (AWS: Working with items)

Maliyeti eşzamanlılıktır. Aynı koşulda yarışan iki yazıcı, birinin kazanması ve birinin yeniden denemek için bir ConditionalCheckFailedException alması demektir — koşulsuz counter'ın verimini doğruluk için takas ettiniz. Tam, çekişmeli counter'lar için doğru takas budur. Görüntüleme sayıları için aşırıya kaçmaktır.

Tuzaklar

  • Bir . Tek bir counter satırı bir partition key'dir. VID#9f3a / STATS#TOTAL'ı çekiçleyen viral bir video, partition başına bir yazma tavanına çarpabilir. Onu shard'layın: yazmaları STATS#TOTAL#0..N boyunca yayın ve okumada toplayın.
  • Toplu artış yok. BatchWriteItem yalnızca put/delete'tir — 'ları çalıştıramaz. Counter'lar çağrı başına bir item ile UpdateItem üzerinden gider. Birkaç counter'ı atomik olarak artırmanız gerekiyorsa, TransactWriteItems, kabaca iki katı yazma maliyetiyle, tek bir istekte 100 item'a kadar Update eylemi çalıştırır.
  • ADD yalnızca sayılar ve setlerdir. String'lere veya boolean'lara dokunmaz; o bir SET'tir. Tam attribute modeli için DynamoDB veri türleri sayfasına bakın.

Sonraki adımlar

Atomic counter'lar bir yazma modelidir; agregasyonları nasıl okuduğunuz bir modelleme sorusudur — istatistik item'larını ebeveynlerinin yanında tutmak için single-table design sayfasına ve sharded bir counter'ı toplamanın bir Query olarak kalması için Query ve Scan sayfasına bakın.

Artışı DynamoDB Expression Builder'da taslak olarak oluşturun ve kopyalayın, sonra kendi tablolarınıza karşı atomik güncellemeler çalıştırmak ve sayıların hareket etmesini izlemek için DynoTable'ı deneyin.

Güncellendi