含版本編號的樂觀鎖定 - Amazon DynamoDB

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

含版本編號的樂觀鎖定

樂觀鎖定是一種策略,可在寫入時偵測衝突,而不是阻止衝突。每個項目都包含一個版本屬性,每次更新都會遞增。更新項目時,您會包含條件表達式,以檢查版本號碼是否符合應用程式上次讀取的值。如果另一個程序同時修改項目,則條件會失敗,且 DynamoDB 會傳回 ConditionalCheckFailedException

何時使用樂觀鎖定

樂觀鎖定非常適合下列情況:

  • 多個使用者或程序可能會更新相同的項目,但衝突不常發生。

  • 重試失敗的寫入對您的應用程式來說並不昂貴。

  • 您想要避免管理分散式鎖定的額外負荷和複雜性。

常見的範例包括電子商務庫存更新、協作編輯平台和金融交易記錄。

取捨

在高度爭用中重試額外負荷

在高並行環境中,衝突發生的可能性提高,可能造成更多重試與更高的寫入成本。

實作複雜度

將版本控制新增至項目和處理條件式檢查,會增加應用程式邏輯的複雜性。適用於 Java v2 的 AWS SDK 增強型用戶端透過 @DynamoDbVersionAttribute註釋提供內建支援,可自動為您管理版本編號。

模式設計

在每個項目中包含版本屬性。以下為簡單的結構設計:

  • 分割區索引鍵 – 每個項目的唯一識別符 (例如 ItemId)。

  • 屬性:

    • ItemId – 項目的唯一識別碼。

    • Version – 表示項目版本編號的整數。

    • QuantityLeft – 項目的剩餘庫存。

首次建立項目時,Version 屬性會設為 1。每次更新時,版本編號會遞增 1。

ItemID (分割區索引鍵) 版本 QuantityLeft
香蕉 1 10
Apples 1 5
橘色 1 7

實作

若要實作樂觀鎖定,請遵循下列步驟:

  1. 讀取項目的當前版本。

    def get_item(item_id): response = table.get_item(Key={'ItemID': item_id}) return response['Item'] item = get_item('Bananas') current_version = item['Version']
  2. 使用檢查版本編號的條件表達式更新項目。

    def update_item(item_id, qty_bought, current_version): try: response = table.update_item( Key={'ItemID': item_id}, UpdateExpression="SET QuantityLeft = QuantityLeft - :qty, Version = :new_v", ConditionExpression="Version = :expected_v", ExpressionAttributeValues={ ':qty': qty_bought, ':new_v': current_version + 1, ':expected_v': current_version }, ReturnValues="UPDATED_NEW" ) return response except ClientError as e: if e.response['Error']['Code'] == 'ConditionalCheckFailedException': print("Version conflict: another process updated this item.") raise
  3. 使用新讀取重試來處理衝突。

    每次重試都需要額外的讀取,因此請限制重試的總數。

    def update_with_retry(item_id, qty_bought, max_retries=3): for attempt in range(max_retries): item = get_item(item_id) try: return update_item(item_id, qty_bought, item['Version']) except ClientError as e: if e.response['Error']['Code'] != 'ConditionalCheckFailedException': raise print(f"Retry {attempt + 1}/{max_retries}") raise Exception("Update failed after maximum retries.")

對於 Java 應用程式,適用於 Java v2 的 AWS SDK 增強型用戶端透過 @DynamoDbVersionAttribute註釋提供內建的樂觀鎖定支援,該註釋會自動為您管理版本編號。

如需條件表達式的詳細資訊,請參閱 DynamoDB 條件表達式 CLI 範例