本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
DynamoDB 版本控制實作的最佳實務
在 DynamoDB 等分散式系統中,透過樂觀鎖定的項目版本控制可避免更新衝突。應用程式可透過追蹤項目版本與條件式寫入,管理並行修改,確保高並行環境中的資料完整性。
樂觀鎖定是一種策略,可確保資料修改正確套用且不發生衝突。不同於在讀取資料時鎖定的悲觀鎖定方式,樂觀鎖定會在寫回前檢查資料是否已變更。在 DynamoDB 中,這透過版本控制機制實現,每個項目都包含隨更新遞增的識別碼。更新項目時,僅當識別碼與應用程式預期值一致時,操作才會成功。
適用情境
此模式適用於以下情境:
多個使用者或程序可能同時嘗試更新相同項目。
資料完整性與一致性至關重要。
應避免管理分散式鎖定所帶來的額外負荷與複雜性。
範例包括:
電子商務應用程式,其庫存層級經常更新。
協作平台,允許多位使用者編輯相同資料。
金融系統,其交易記錄必須保持一致。
取捨
雖然樂觀鎖定與條件式檢查可提供強健的資料完整性,但也伴隨以下取捨:
- 並行衝突
在高並行環境中,衝突發生的可能性提高,可能造成更多重試與更高的寫入成本。
- 實作複雜度
-
為項目新增版本控制並處理條件式檢查,可能使應用程式邏輯更加複雜。
- 額外的儲存負荷
-
為每個項目儲存版本編號會略微增加儲存需求。
模式設計
若要實作此模式,DynamoDB 結構應包含每個項目的版本屬性。以下為簡單的結構設計:
分割區索引鍵 – 每個項目的唯一識別符 (例如
ItemId)。屬性:
ItemId– 項目的唯一識別碼。Version– 表示項目版本編號的整數。QuantityLeft– 項目的剩餘庫存。
首次建立項目時,Version 屬性會設為 1。每次更新時,版本編號會遞增 1。
使用此模式
若要實作此模式,請依照應用程式流程執行以下步驟:
讀取項目的當前版本。
從 DynamoDB 擷取當前項目並讀取其版本編號。
def get_document(item_id): response = table.get_item(Key={'ItemID': item_id}) return response['Item'] document = get_document('Bananas') current_version = document['Version']在應用程式邏輯中將版本編號加一。這將是更新的預期版本。
new_version = current_version + 1嘗試使用條件式運算式更新項目,確保版本編號一致。
def update_document(item_id, qty_bought, current_version): try: response = table.update_item( Key={'ItemID': item_id}, UpdateExpression="set #qty = :qty, Version = :v", ConditionExpression="Version = :expected_v", ExpressionAttributeNames={ '#qty': 'QuantityLeft' }, ExpressionAttributeValues={ ':qty': qty_bought, ':v': current_version + 1, ':expected_v': current_version }, ReturnValues="UPDATED_NEW" ) return response except ClientError as e: if e.response['Error']['Code'] == 'ConditionalCheckFailedException': print("Update failed due to version conflict.") else: print("Unexpected error: %s" % e) return None update_document('Bananas', 2, new_version)如果更新成功,項目的 QuantityLeft 將減少 2。
處理可能發生的衝突。
若發生衝突 (例如,自上次讀取後另一程序已更新該項目),請適當處理,如重試操作或提示使用者。
每次重試都需額外讀取項目,因此在請求迴圈失敗前,應限制允許的重試次數。
def update_document_with_retry(item_id, new_data, retries=3): for attempt in range(retries): document = get_document(item_id) current_version = document['Version'] result = update_document(item_id, qty_bought, current_version) if result is not None: print("Update succeeded.") return result else: print(f"Retrying update... ({attempt + 1}/{retries})") print("Update failed after maximum retries.") return None update_document_with_retry('Bananas', 2)使用具樂觀鎖定與條件式檢查的 DynamoDB 實作項目版本控制,是確保分散式應用中資料完整性的強大模式。雖然此方法增加一定的複雜度與潛在效能取捨,但在需要強健並行控制的情境中極具價值。透過審慎設計結構並在應用程式邏輯中實作必要檢查,可有效管理並行更新並維持資料一致性。
如需更多關於在 DynamoDB 中實作資料版本控制的指引與策略,請參閱 AWS 資料庫部落格
。