Menengah7 menit baca

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/SK di kode Anda (mis. CONFIG#GLOBAL) alih-alih menyisipkan id pengguna atau pesanan.
  • Baca dengan GetItem, jangan pernah Scan. 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:

PKSKattributes
SETTINGS#APPFLAGS#V1signup_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.

yatidakAplikasi / requestGetItem PK=SETTINGS#APPSK=FLAGS#V1Item ditemukan?Gunakan flag, cache lokalKembali ke default aman

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-Put ulang 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 singletonItem per-entitas
KeyKonstanta di-hardcode (SETTINGS#APP)Di-template dengan id (USER#42)
Berapa banyakTepat satuSatu per pengguna / pesanan / tenant
Pembacaan khasGetItem pada key yang diketahuiGetItem atau Query per entitas
CakupanSeluruh aplikasiSatu entitas tunggal
Digunakan untukFlag global, config, versi sistemProfil, 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 Scan untuknya. 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.

Diperbarui