Item Singleton di DynamoDB
Sebuah Item singleton adalah satu baris dengan key tetap yang di-hardcode yang menampung state untuk seluruh aplikasi Anda — bukan satu record per pengguna atau per pesanan, melainkan satu record, titik. Feature flag, sebuah blob config, sebuah kill-switch global: jenis hal yang akan disimpan aplikasi relasional di tabel settings satu-baris.
Datang dari SQL, Anda akan meraih sebuah tabel config dengan id = 1 dan sebuah
SELECT * FROM config. Di DynamoDB Anda melakukan hal yang sama dengan partition key yang
di-hardcode — dan karena Anda selalu mengetahui key itu, Anda membacanya dengan
sebuah GetItem, bukan sebuah QueryatauScan.
Apa itu item singleton di DynamoDB?
Item singleton adalah satu baris DynamoDB yang disimpan di bawah key tetap yang di-hardcode, yang menampung state global untuk seluruh aplikasi Anda — feature flag, blob config, versi sistem — bukan satu record per pengguna atau pesanan. Karena Anda selalu mengetahui key-nya, Anda membacanya dengan GetItem dan memperbaruinya dengan update expression plus condition expression.
- Sebuah singleton adalah satu Item dengan key konstan. Anda meng-hardcode
PK/SKdi kode Anda (mis.CONFIG#GLOBAL) alih-alih menyisipkan id pengguna atau pesanan. - Baca dengan
GetItem, jangan pernahScan. Anda selalu mengetahui key lengkapnya, jadi sebuah point read adalah satu RCU yang konsisten dan dapat-diprediksi — tanpa filter, tanpa menjelajahi tabel. - Ia adalah hot key menurut definisinya. Setiap request bisa menyentuh partition yang sama, jadi cache-lah dan jaga Item-nya kecil; jangan jadikan ia bottleneck tulisan.
- Mutasikan dengan aman menggunakan update + condition expression, bukan read-modify-write di aplikasi Anda — di situlah race lost-update bersemayam.
Kenali polanya
Anda memiliki state global ketika data tidak tercakup ke entitas mana pun. Beberapa tandanya:
- Sebuah flag yang sama untuk semua orang (
signup_enabled = false). - Sebuah blob tunable yang dibaca aplikasi Anda saat boot (rate limit, kuota default).
- Sebuah counter atau nomor versi untuk seluruh sistem, bukan per-baris.
Apa pun yang tercakup ke pengguna, tenant, atau pesanan bukan singleton — itu sebuah Item biasa yang di-key oleh id entitas tersebut. Singleton adalah irisan global sisa yang tak punya tempat lain untuk tinggal.
Beri ia key konstan
Seluruh pola bergantung pada satu keputusan: key adalah literal, bukan template. Untuk sebuah Item feature-flag global dalam single table yang di-overload, pilih prefix tetap dan nilai tetap:
| PK | SK | attributes |
|---|---|---|
| SETTINGS#APP | FLAGS#V1 | signup_enabled, maintenance_mode, ai_search_enabled |
PK = "SETTINGS#APP" dan SK = "FLAGS#V1" ditanamkan di kode. Tak ada id pengguna,
tak ada id tenant — aplikasi meminta tepat Item ini setiap kali. Prediktabilitas
itulah intinya: key yang diketahui adalah sebuah GetItem, dan sebuah GetItem
adalah pembacaan termurah dan paling konsisten yang ditawarkan DynamoDB.
Suffix V1 itu disengaja. Jika bentuk schema flag berubah nanti, Anda menulis
sebuah Item FLAGS#V2 dan membalik pembaca ke sana, alih-alih memutasi yang aktif
di tempat. Mem-versi-kan key singleton membeli Anda sebuah celah migrasi yang bersih.
Baca dengan GetItem
Karena key sepenuhnya diketahui, Anda tidak pernah Query dan tidak pernah Scan
untuk sebuah singleton. Sebuah Scan membaca seluruh tabel dan memfilter di
sisi-klien — footgun Scan klasik — dan itu berlebihan
secara absurd untuk mengambil satu baris yang bisa Anda alamati langsung.
Sebuah GetItem terhadap SETTINGS#APP / FLAGS#V1 mengembalikan flag dalam satu
pembacaan yang strongly- atau eventually-consistent. AWS menagih sebuah GetItem
dari Item ≤ 4 KB sebagai 0.5 RCU eventually-consistent atau 1 RCU
strongly-consistent
(dokumentasi read/write capacity AWS).
Jaga singleton tetap kecil dan biaya itu tetap rata selamanya.
Jalur pembacaannya hanyalah: aplikasi boot atau sebuah request masuk, Anda
GetItem key tetap, Anda cache hasilnya. Berikut alurnya.
Key tetap mengubah pencarian global menjadi satu point read dengan jalur default bawaan.
Perhatikan cabang tidak: singleton yang hilang tidak boleh membuat Anda crash.
Default ke nilai aman (fitur mati, maintenance menyala) sehingga celah
deploy-pertama atau key yang buruk gagal-tertutup, bukan terbuka.
Perbarui tanpa race
Jebakannya adalah memperbarui singleton dengan read-modify-write di aplikasi Anda:
Anda GetItem flag-nya, balik satu di memori, lalu PutItem seluruhnya kembali.
Dua penulis bersamaan keduanya membaca Item lama dan Put kedua menabrak perubahan
yang pertama. Lost update.
Dua fitur DynamoDB membunuh race tanpa locking di sisi-aplikasi:
- Update expression memutasi satu atribut di sisi-server, membiarkan sisanya
tak tersentuh. Tak perlu mem-
Putulang seluruh Item. - Condition expression membuat tulisan berhasil hanya jika Item masih terlihat
seperti yang Anda harapkan, sehingga tulisan basi ditolak dengan
ConditionalCheckFailedException(dokumentasi condition expression AWS).
Untuk membalik satu flag, targetkan hanya atribut itu dengan sebuah SET dan jaga
dengan kenaikan versi sehingga penulis bersamaan tidak bisa saling menabrak:
# UpdateItem
Key PK=SETTINGS#APP SK=FLAGS#V1
UpdateExpression SET signup_enabled = :on, schema_version = :next
ConditionExpression schema_version = :current
Jika dua penulis ber-race, pemeriksaan schema_version = :current yang kedua gagal
dan ia mencoba ulang terhadap nilai segar. Anda bisa menyusun names, values, dan
bentuk expression persis ini di
DynamoDB Expression Builder sebelum
menyambungkannya ke kode. Untuk pandangan lebih dalam tentang operator, lihat panduan
idiom update-expression.
Perhatikan hot key
Sebuah singleton, secara konstruksi, adalah sebuah hot key — setiap bagian aplikasi Anda mungkin membaca partition yang sama. Itu baik-baik saja untuk pembacaan jika Anda cache, tapi itulah satu risiko nyata dari pola ini.
- Cache secara agresif. Baca flag sekali per proses (atau per N detik), bukan pada setiap request. Nilai singleton adalah hal termurah untuk di-memoize.
- Jangan jadikan ia hot spot tulisan. Sebuah flag yang di-toggle oleh admin beberapa kali sehari tak ada apa-apanya. Sebuah singleton yang Anda increment pada setiap request adalah bottleneck throughput partition — itu masalah counter, bukan singleton.
- Jaga tetap kecil. Biaya pembacaan menskala dengan ukuran Item dalam blok 4 KB. Sebuah blob config yang membengkak membuat setiap boot lebih mahal dari yang perlu.
Jika Anda benar-benar butuh counter global ber-tulisan-tinggi, singleton adalah bentuk yang salah — shard ia ke N Item dan jumlahkan saat pembacaan. Itu pola yang berbeda.
Singleton vs Item per-entitas
Garisnya hanyalah data itu tercakup ke apa.
| Item singleton | Item per-entitas | |
|---|---|---|
| Key | Konstanta di-hardcode (SETTINGS#APP) | Di-template dengan id (USER#42) |
| Berapa banyak | Tepat satu | Satu per pengguna / pesanan / tenant |
| Pembacaan khas | GetItem pada key yang diketahui | GetItem atau Query per entitas |
| Cakupan | Seluruh aplikasi | Satu entitas tunggal |
| Digunakan untuk | Flag global, config, versi sistem | Profil, pesanan, apa pun per-id |
Jika Anda mendapati diri menginginkan dua singleton dari jenis yang sama, Anda tidak memiliki singleton — Anda memiliki Item per-entitas dan entitasnya adalah hal yang lupa Anda jadikan key (config per-tenant, misalnya).
Jebakan dan langkah berikutnya
- Jangan
Scanuntuknya. Anda tahu key-nya; alamati langsung. - Jangan read-modify-write ia. Gunakan update + condition expression.
- Jangan biarkan ia hilang diam-diam. Default ke nilai aman pada cache miss.
- Jangan overload ia dengan tulisan berfrekuensi-tinggi. Itu pekerjaan sharded-counter.
Singleton hidup dengan nyaman di dalam sebuah single-table design — ia hanyalah satu item collection lagi dengan key tetap di samping baris entitas Anda.
Coba DynoTable untuk menjelajahi tabel Anda, temukan baris singleton melalui key tetapnya, dan edit flag dengan tangan sembari Anda membangun jalur tulisan.