Kontrol konkurensi optimis (OCC) adalah strategi untuk mengelola resource bersama dan mencegah update yang hilang atau kondisi race saat beberapa pengguna atau proses mengubah resource yang sama secara bersamaan.
Misalnya, saat menggunakan Identity and Access Management, kebijakan IAM adalah resource bersama yang dilampirkan ke resource seperti project, bucket, atau layanan. Tanpa kontrol konkurensi, modifikasi simultan dapat menimpa perubahan kebijakan terbaru, sehingga secara tidak sengaja mencabut akses yang sah atau memberikan izin yang tidak sah.
Untuk menerapkan OCC, sistem biasanya menggunakan nomor versi atau kolom etag (tag entitas) pada struct resource.
Cara kerja OCC
Misalkan dua proses, A dan B, mencoba memperbarui resource bersama secara bersamaan:
- Proses A membaca status resource saat ini.
- Proses B membaca status saat ini yang sama.
- Proses A mengubah salinannya dan menulisnya kembali ke server.
- Proses B mengubah salinannya dan menulisnya kembali ke server.
Karena Proses B menimpa resource tanpa mengetahui bahwa Proses A telah mengubahnya, update Proses A akan hilang.
OCC memecahkan masalah ini dengan memperkenalkan sidik jari unik yang berubah setiap kali entity diubah. Di banyak sistem, seperti IAM, sidik jari ini adalah etag. Server memeriksa tag ini pada setiap penulisan:
- Saat Anda membaca resource, server akan menampilkan
etag(sidik jari unik). - Saat mengirim kembali resource yang diubah, Anda harus menyertakan
etagasli. - Jika
etagyang disimpan tidak cocok denganetagyang Anda kirim—artinya proses lain mengubah resource setelah Anda membacanya—operasi tulis akan gagal dengan errorABORTEDatauFAILED_PRECONDITION.
Kegagalan ini memberi sinyal kepada klien untuk mencoba kembali seluruh proses: membaca ulang status yang diperbarui, menerapkan kembali perubahan, dan mencoba menulis lagi dengan etag baru.
Mengimplementasikan loop OCC
Inti dari implementasi OCC adalah loop percobaan ulang yang membaca, mengubah, dan mencoba menyimpan resource, lalu keluar setelah penulisan berhasil. Untuk mencegah loop tak terbatas selama pertentangan tinggi, konfigurasikan jumlah maksimum upaya percobaan ulang yang wajar.
Langkah-langkah loop
Tabel berikut menjelaskan setiap langkah dalam loop percobaan ulang OCC:
| Langkah | Tindakan | Contoh penerapan |
|---|---|---|
| Melihat | Ambil status resource saat ini, termasuk etag. |
let mut policy = client .get_iam_policy() .set_resource(&secret_name) .send() .await?; |
| Mengubah | Terapkan perubahan pada struct lokal. | policy.bindings.push(new_binding); |
| Menulis dan memeriksa | Mencoba menyimpan resource yang diubah menggunakan etag yang ada, dan memeriksa kode error serentak. |
match client .set_iam_policy() .set_resource(&secret_name) .set_policy(policy) .send() .await { Ok(p) => return Ok(p), Err(e) => { /* ... */ } } |
| Berhasil atau coba lagi | Jika penulisan berhasil, keluar dari loop. Jika gagal dengan error konkurensi, tambahkan penghitung percobaan ulang dan lanjutkan loop dari langkah Read. | - |
Contoh
Contoh berikut menunjukkan cara menerapkan loop OCC yang memperbarui kebijakan IAM pada resource secret Secret Manager dengan memberikan peran roles/secretmanager.secretAccessor kepada anggota.
Untuk menjalankan contoh ini, deklarasikan dependensi terlebih dahulu dalam file Cargo.toml Anda:
cargo add google-cloud-secretmanager-v1
Kemudian, terapkan loop percobaan ulang OCC:
Kode lengkap
Kode berikut menunjukkan fungsi lengkap dengan semua impor yang diperlukan: