簡體   English   中英

DynamoDB 更新是否高度一致?

[英]Are DynamoDB Updates strongly consistent?

DynamoDB 快速且可擴展的全部原因是基於它的最終一致性這一事實。 但與此同時,它為getbatchGetquery等操作提供了ConsistentRead選項,可幫助您確保正在讀取的數據是最新的。

我的問題是關於update操作。 首先,它沒有ConsistentRead選項(一個原因是, update不是讀取。),但與此同時,您可以使用ConditionExpression以原子方式更新記錄,如下所示:

await docClient.update({
    TableName: 'SomeTable',
    Key: {id},
    UpdateExpression: "set #status = :new_status",
    ConditionExpression: '#status = :old_status',
    ExpressionAttributeNames: {
        "#status": "status",
    },
    ExpressionAttributeValues: {
        ":old_status": "available",
        ":new_status": "done",
    },
}).promise()

這將確保在更新時,舊值available ,如果不可用,操作將失敗並拋出異常。 所以,從某種意義上說,你可以說update是強一致的。

但我的問題是關於您需要確保記錄存在的場景。 假設您有一個 function 插入一條記錄。 另一個更新同一條記錄(給定它的id )。 我擔心的是,如果在執行update操作時,由於 DynamoDB 的最終一致性,沒有匹配的記錄並且更新失敗怎么辦。 如前所述, update操作不帶有ConsistentRead選項以使其具有強一致性。

這是一個合理的擔憂嗎? 有什么我可以做的嗎?

沒有強烈一致的更新。 強一致性適用於讀取,其中基本上在寫入后立即查看的數據對於實體的所有觀察者來說都是一致的。

當您的應用程序將數據寫入 DynamoDB 表並收到 HTTP 200 響應 (OK) 時,寫入已發生(在至少一個存儲位置)並且是持久的。 數據最終在所有存儲位置保持一致,通常在一秒或更短的時間內。 然后,您可以選擇以最終一致性或強一致性方式讀取此數據。

應使用樂觀並發處理對同一項目的並發寫入,您可以使用 DynamoDB 事務庫(適用於 Java 的 AWS SDK 中提供)進行條件寫入

如果您需要以原子方式更新多個項目,您可以使用 DynamoDB 事務。

DynamoDB 事務為開發人員提供跨單個 AWS 賬戶和區域內的一個或多個表的原子性、一致性、隔離性和持久性 (ACID)。 在構建需要對多個項目進行協調插入、刪除或更新作為單個邏輯業務操作的一部分的應用程序時,您可以使用事務。

https://aws.amazon.com/blogs/aws/new-amazon-dynamodb-transactions/

或者,您的用例可能會受益於DynamoDB 全局表,該表在並發寫入之間使用“最后寫入者獲勝”協調。

這個問題過去在這里被問過很多次,例如參見

dynamodb 更新表達式是否具有強一致性?

DynamoDB 條件寫入是否具有強一致性?

上面接受的答案或多或少表明,在作為寫入的一部分發生的讀取中,所有賭注都已關閉,並且您不能相信它們是一致的 - 因此您需要使用新的“DynamoDB 事務”功能。 但我認為那個答案的結論是錯誤的。 當您有一個事務需要隔離對幾個不同項目的寫入並安全地支持失敗的非冪等寫入時,就需要新的“DynamoDB 事務”。 但是在UpdateItem支持的單項更新中,我相信涉及的先讀后寫實際上是強一致的:

不幸的是,DynamoDB 的文檔對此並不完全清楚,但這里有一些來自 DynamoDB 文檔的證據來支持我的信念:

  1. 有幾個原因導致UpdateItem可能需要讀取項目的舊值(所謂的先讀后寫)——問題是這些讀取的一致性。 讀取的原因之一是UpdateExpression (例如,更新可以增加屬性),另一個是ConditionExpression (更新可以以屬性的舊值為條件),第三種情況是ReturnValues用戶要求獲取項目的舊值。 盡管UpdateItem 文檔沒有明確說明前兩種情況下的一致性,但對於第三種情況下的一致性卻非常明確: “返回的值是強一致的”。 . 我看不出為什么在這種情況下先讀后寫是強一致的,而在其他情況下則不是,所以我相信它在所有三種情況下都是強一致的。
  2. 來自 DynamoDB 的 DynamoDB 內部結構的幾個演示解釋了它在內部是如何工作的:它為每條數據保留三個副本,並且在任何時候三個副本中的一個被認為是“領導者”; 始終首先將 go 寫入領導者,並在領導者和第二個副本成功時成功,最終一致性隨機將 go 讀取到三個副本之一(因此可能從一個尚未收到寫入的副本讀取)但強烈-consistent 始終讀取 go 給領導者。 這意味着強一致性讀取和寫入 go 到同一個副本(領導者),並具有相同的一致性保證。 此外,領導者線性化了對該項目的寫入(即,按某種順序進行,而不是同時進行),因此一次寫入的先讀后寫可以看到之前寫入同一項目時寫入的所有內容。

以上所有答案都不正確。 沒有寫入強一致性。

UpdateItem 將在復制組的領導節點被確認時返回,一旦對等點的法定人數將日志記錄保存到他們的本地預寫日志中。 這意味着只有預寫日志被復制到日志節點,而不是實際的存儲節點。 因此 UpdateItem 不保證復制組中的所有存儲節點都能成功寫入。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM