Penguncian terdistribusi dengan DynamoDB Lock Client - Amazon DynamoDB

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

Penguncian terdistribusi dengan DynamoDB Lock Client

Untuk aplikasi yang memerlukan lock-acquire-release semantik tradisional, DynamoDB Lock Client adalah pustaka sumber terbuka yang mengimplementasikan penguncian terdistribusi menggunakan tabel DynamoDB sebagai toko kunci. Pendekatan ini berguna ketika Anda perlu mengoordinasikan akses ke sumber daya eksternal (seperti objek S3 atau konfigurasi bersama) di beberapa instance aplikasi.

Klien kunci tersedia sebagai pustaka Java open-source.

Cara kerjanya

Klien kunci menggunakan tabel DynamoDB khusus untuk melacak kunci. Setiap kunci direpresentasikan sebagai item dengan atribut kunci berikut:

  • Kunci partisi yang mengidentifikasi sumber daya yang dikunci.

  • Durasi sewa yang menentukan berapa lama kunci valid. Jika pemegang kunci mogok atau menjadi tidak responsif, kunci secara otomatis kedaluwarsa setelah durasi sewa.

  • Detak jantung yang dikirim pemegang kunci secara berkala untuk memperpanjang sewa. Ini mencegah kunci kedaluwarsa saat dudukan masih aktif diproses.

Klien kunci menggunakan penulisan bersyarat untuk memastikan bahwa hanya satu proses yang dapat memperoleh kunci pada satu waktu. Jika kunci sudah ditahan, penelepon dapat memilih untuk menunggu dan mencoba lagi atau gagal segera.

Kapan menggunakan klien kunci

Klien kunci sangat cocok ketika:

  • Anda perlu mengoordinasikan akses ke sumber daya bersama di beberapa instance aplikasi atau layanan mikro.

  • Bagian kritis berjalan lama (detik hingga menit) dan mencoba kembali seluruh operasi pada konflik akan mahal.

  • Anda memerlukan kedaluwarsa kunci otomatis untuk menangani kegagalan proses dengan anggun.

Contoh umum termasuk mengatur alur kerja terdistribusi, mengoordinasikan pekerjaan cron di beberapa instance, dan mengelola akses ke sumber daya eksternal bersama.

Pengorbanan

Infrastruktur tambahan

Membutuhkan tabel DynamoDB khusus untuk manajemen kunci, dengan kapasitas baca dan tulis tambahan untuk operasi kunci dan detak jantung.

Ketergantungan jam

Kedaluwarsa kunci bergantung pada stempel waktu. Kemiringan jam yang signifikan antara klien dapat menyebabkan perilaku yang tidak terduga, terutama untuk jangka waktu sewa yang pendek.

Risiko kebuntuan

Jika aplikasi Anda memperoleh kunci pada beberapa sumber daya, Anda harus mendapatkannya dalam urutan yang konsisten untuk menghindari kebuntuan. Durasi sewa menyediakan jaring pengaman dengan secara otomatis melepaskan kunci dari pemegang yang tidak responsif.

Implementasi

Contoh berikut menunjukkan cara menggunakan DynamoDB Lock Client untuk memperoleh dan melepaskan kunci:

import java.io.IOException; import java.util.Optional; import java.util.concurrent.TimeUnit; import software.amazon.awssdk.services.dynamodb.DynamoDbClient; final DynamoDbClient dynamoDB = DynamoDbClient.builder() .region(Region.US_WEST_2) .build(); final AmazonDynamoDBLockClient lockClient = new AmazonDynamoDBLockClient( AmazonDynamoDBLockClientOptions.builder(dynamoDB, "Locks") .withTimeUnit(TimeUnit.SECONDS) .withLeaseDuration(10L) .withHeartbeatPeriod(3L) .withCreateHeartbeatBackgroundThread(true) .build()); // Try to acquire a lock on a resource final Optional<LockItem> lock = lockClient.tryAcquireLock(AcquireLockOptions.builder("my-shared-resource").build()); if (lock.isPresent()) { try { // Perform operations that require exclusive access processSharedResource(); } finally { // Always release the lock when done lockClient.releaseLock(lock.get()); } } else { System.out.println("Failed to acquire lock."); } lockClient.close();
penting

Selalu lepaskan kunci di finally blok untuk memastikan kunci dilepaskan meskipun logika pemrosesan Anda mengeluarkan pengecualian. Kunci yang belum dirilis memblokir proses lain sampai masa sewa berakhir.

Anda juga dapat menerapkan mekanisme penguncian sederhana tanpa pustaka klien kunci dengan menggunakan penulisan bersyarat secara langsung. Contoh berikut menggunakan UpdateItem dengan ekspresi kondisi untuk memperoleh kunci, dan DeleteItem untuk melepaskannya:

from datetime import datetime, timedelta from boto3.dynamodb.conditions import Attr def acquire_lock(table, resource_name, owner_id, ttl_seconds): """Attempt to acquire a lock. Returns True if successful.""" expiry = (datetime.now() + timedelta(seconds=ttl_seconds)).isoformat() now = datetime.now().isoformat() try: table.update_item( Key={'LockID': resource_name}, UpdateExpression='SET #owner = :owner, #expiry = :expiry', ConditionExpression=Attr('LockID').not_exists() | Attr('ExpiresAt').lt(now), ExpressionAttributeNames={'#owner': 'OwnerID', '#expiry': 'ExpiresAt'}, ExpressionAttributeValues={':owner': owner_id, ':expiry': expiry} ) return True except table.meta.client.exceptions.ConditionalCheckFailedException: return False def release_lock(table, resource_name, owner_id): """Release a lock. Only succeeds if the caller is the lock owner.""" try: table.delete_item( Key={'LockID': resource_name}, ConditionExpression=Attr('OwnerID').eq(owner_id) ) return True except table.meta.client.exceptions.ConditionalCheckFailedException: return False

Pendekatan ini menggunakan ekspresi kondisi untuk memastikan bahwa kunci hanya dapat diperoleh jika tidak ada atau telah kedaluwarsa, dan hanya dapat dilepaskan oleh proses yang memperolehnya. Pertimbangkan untuk mengaktifkan Time to Live (TTL) di meja kunci untuk secara otomatis membersihkan item kunci yang kedaluwarsa.