Atomic Counter DynamoDB
Sebuah atomic counter adalah atribut numerik yang Anda naikkan di tempat dengan
satu panggilan UpdateItem — tanpa baca dulu, tanpa race read-modify-write.
DynamoDB menerapkan setiap kenaikan dalam urutan kedatangan dan tidak pernah
membiarkan dua penulis menabrak hitungan satu sama lain.
Apa itu atomic counter DynamoDB?
Atomic counter DynamoDB adalah atribut numerik yang Anda naikkan di tempat dengan
satu panggilan UpdateItem memakai update expression ADD (atau SET x = x + :n).
DynamoDB membaca, menambah, dan menulis nilainya di sisi server, sehingga penulis
konkuren ter-serialisasi tanpa update yang hilang — tetapi ia tidak idempoten, jadi
panggilan yang di-retry menaikkan dua kali.
- Gunakan
ADD(atauSET x = x + :n) untuk menaikkan dalam satu panggilan. DynamoDB membaca, menambah, dan menulis di sisi server — pemanggil konkuren ter-serialisasi, tanpa update yang hilang. - Tanpa baca dulu. Datang dari SQL Anda akan
SELECTlaluUPDATE; di sini Anda melewati pembacaan sepenuhnya dan operasinya tetap aman di bawah konkurensi. - Atomic counter tidak idempoten. Sebuah
UpdateItemyang di-retry menaikkan lagi. Jika Anda tak bisa mentolerir over- atau undercounting, gunakan conditional update. ADDpada atribut yang tidak ada mulai dari 0, jadi kenaikan pertama langsung jalan — tanpa penulisan seed.
Masalah dengan read-modify-write
Misalkan Anda melacak views pada sebuah video. Naluri naif, langsung dari SQL,
adalah: GetItem, tambah satu di aplikasi Anda, PutItem total baru kembali.
Dua penonton menekan play sekaligus. Keduanya membaca views = 41. Keduanya
menulis 42. Anda menghitung satu view, bukan dua. Itu adalah update yang hilang
— jebakan konkurensi klasik, dan ia tak muncul sampai Anda punya lalu lintas.
Di SQL Anda akan mengelaknya dengan UPDATE videos SET views = views + 1,
mendorong aritmetika ke dalam database. DynamoDB punya langkah yang sama, dan
itulah inti seluruh atomic counter.
Naikkan dalam satu panggilan
Modelkan sebuah item stats per-video. Partition key VID#<id>, sort key
STATS#TOTAL, dengan sebuah play_count numerik:
| PK | SK | play_count |
|---|---|---|
| "VID#9f3a" | "STATS#TOTAL" | 41 |
Untuk mendaftarkan sebuah play, kirim satu UpdateItem dengan klausa ADD:
# UpdateItem
Key PK = "VID#9f3a", SK = "STATS#TOTAL"
UpdateExpression ADD play_count :one
Values :one = 1
DynamoDB membaca play_count, menambah 1, dan menulis hasilnya di dalam satu
operasi sisi-server. Tak ada jendela bagi penulis lain untuk menyelinap masuk.
Sepuluh play konkuren menghasilkan +10, setiap kali — itulah yang dibeli
"atomic".
Anda bisa membangun dan menyalin ekspresi yang persis ini — nama, nilai, dan keempat tipe klausa — dengan DynamoDB Expression Builder.
ADD bekerja bahkan saat play_count belum ada: DynamoDB memperlakukan atribut
numerik yang hilang sebagai 0, jadi play pertama menciptakannya pada 1. Tanpa
penulisan seed terpisah. (AWS: Using update expressions)
ADD vs SET +: pilih satu
Dua ekspresi melakukan aritmetika yang sama. AWS merekomendasikan SET untuk
penggunaan umum karena ia menyatu dengan aksi SET lain dan membaca lebih
eksplisit. (AWS: Using update expressions)
ADD play_count :one | SET play_count = play_count + :one | |
|---|---|---|
| Atribut hilang | Menciptakannya, mulai dari 0 | Error — butuh if_not_exists |
| Tipe data | Number dan set saja | Number (dan lainnya) via SET |
Gabung w/ SET | Klausa terpisah | Satu klausa SET, dipisah koma |
| Panduan AWS | Oke untuk counter | Default yang direkomendasikan |
Jika atributnya mungkin tidak ada dan Anda ingin SET, jaga ia:
SET play_count = if_not_exists(play_count, :zero) + :one. Dengan ADD Anda
melewatkan itu — ia menyemai dari 0 secara gratis.
Lakukan di DynoTable
Buka item-nya, sunting play_count, dan Anda bisa mengamati sebuah kenaikan
atomic mendarat tanpa menulis JSON dengan tangan — panel update mengeluarkan
ekspresi ADD untuk Anda dan menunjukkan nilai baru begitu ia ter-commit.
Jebakannya: counter tidak idempoten
Inilah bagian yang menggigit tim di produksi. Sebuah atomic counter menaikkan
setiap kali UpdateItem berjalan. (AWS: Working with items)
Bayangkan sebuah blip jaringan: Anda mengirim kenaikan, koneksi putus sebelum respons kembali, dan Anda tak tahu apakah ia mendarat. Anda retry. Jika panggilan pertama memang berhasil, Anda kini telah menghitung play itu dua kali.
Untuk views video itu baik-baik saja — beberapa hitungan-ganda dalam sejuta play tak akan menyakiti siapa pun, dan AWS menyebut kasus "track visitors" yang persis ini sebagai penggunaan kanonik atomic counter. (AWS: Working with items)
Itu tidak baik-baik saja untuk apa pun yang harus persis: inventaris yang bisa Anda oversell, kredit yang bisa Anda double-spend, sebuah saldo yang bisa Anda rusak. Di sana, jangkau sebuah conditional update.
Saat Anda butuh ketepatan: conditional update
Sebuah conditional update idempoten jika Anda mengondisikan pada atribut yang
sama yang Anda ubah. Naikkan play_count ke 42, tapi hanya jika ia saat ini
41:
# UpdateItem
Key PK = "VID#9f3a", SK = "STATS#TOTAL"
UpdateExpression SET play_count = :next
ConditionExpression play_count = :current
Values :next = 42, :current = 41
Kini sebuah retry aman: jika penulisan pertama sudah memindahkan play_count ke
42, kondisi play_count = 41 gagal kali kedua dan tak ada yang berubah. (AWS:
Working with items)
Biayanya adalah konkurensi. Dua penulis beradu pada kondisi yang sama berarti
satu menang dan satu mendapat ConditionalCheckFailedException untuk di-retry —
Anda menukar throughput counter tak-bersyarat demi kebenaran. Untuk counter yang
persis dan ter-contend itu adalah trade yang tepat. Untuk hitungan view itu
berlebihan.
Jebakan
- Satu item panas. Sebuah baris counter tunggal adalah satu partition key.
Sebuah video viral yang menggempur
VID#9f3a/STATS#TOTALbisa mengenai batas tulis per-partition. Shard ia: sebar penulisan di seluruhSTATS#TOTAL#0..Ndan jumlahkan saat baca. - Tanpa batch increment.
BatchWriteItemhanya put/delete — ia tak bisa menjalankan update expression. Counter melewatiUpdateItem, satu item per panggilan. ADDhanya number dan set. Ia tak akan menyentuh string atau boolean; itu sebuahSET. Lihat tipe data DynamoDB untuk model atribut lengkapnya.
Langkah berikutnya
Atomic counter adalah pola tulis; bagaimana Anda membaca agregat kembali adalah
pertanyaan pemodelan — lihat single-table design
untuk menyimpan item stats di samping induknya, dan Query vs
Scan agar menggulung sebuah counter ter-shard tetap
sebuah Query.
Draf dan salin kenaikan di DynamoDB Expression Builder, lalu coba DynoTable untuk menjalankan update atomic terhadap tabel Anda sendiri dan amati hitungan bergerak.