2009-11-19 71 views
2

讓說,我有表在Azure Table中存儲Azure Table中數據一致性

public class MyTable 
{ 
    public string PK {get; set;} 
    public string RowPK {get; set;} 

    public double Amount {get; set;} 
} 

和消息在Azure的隊列它說添加10〜金額

現在,讓我們說,一個工人的作用

  1. 從隊列中取出此消息
  2. 注意到,從表中的行
  3. 金額+ = 10
  4. 更新行表
  5. 並失敗

一段時間後消息再次在隊列中可用。所以下次工作者角色:

  1. 從隊列中取出此消息
  2. 從表中獲取行
  3. 金額+ = 10
  4. 更新行表
  5. 從隊列中移除消息

這些操作導致Amount += 20而不是Amount += 10

我該如何避免這種情況?

回答

1

您放入隊列中的所有消息必須是冪等的。工作人員總是有機會完成他的工作,所以信息必須是可重複的。

因此,取代金額+ = 10作爲一個任務做一些類似金額= 300. 獲取當前金額在webrole中添加10並將新金額放入隊列中。

我不確定這是否是正確的方法。如果你這樣做,如果兩個卷軸在同一時刻嘗試添加10個,則會出現問題。

+0

似乎是一個好的事件採購的故事;你不想讓錯誤的順序延遲的消息,你會? – Henrik 2010-11-15 08:44:37

2

我建議你實施一種樂觀的併發。您發送的用於更新行的消息應該包含amount屬性的「previous value」和「new value」。

因此,嘗試更新行的第二個輔助角色將首先檢查當前值是否仍等於「先前值」。如果不是工作人員的角色知道出了什麼問題,他可以例如在不進行更新的情況下取消該消息。也許還會在某些日誌中引發錯誤。

0

你是否實現了這個或者是代碼行上面只有幾個想法?

「金額」意味着您正在考慮某種銀行交易場景。直接使用SQL Azure可能會更好(因爲您有ACID保證:http://blogs.msdn.com/ssds/archive/2009/03/12/9471765.aspx 「我們一直支持服務中的完整ACID功能,並且將繼續這樣做。「)

Afaik,我們可以說windows azure中的」桌子「就像Google的bigtable,不是嗎?

0
  1. 在隊列中爲您的消息提供唯一的MessageId。
  2. 輔助角色從隊列中讀取所述消息,從所述表
  3. 更新金額字段
  4. 使間歇操作,並插入2行回表讀實體。第一個是更新後的實體合併回表中,第二個實體是插入與行密鑰相同的Partition Key和Message Id的實體。

批處理操作將以原子方式執行。

  1. 現在在您的示例中,如果另一個輔助角色第二次嘗試處理相同的消息,則該操作將失敗,因爲消息Id已經存在於表中。工作者角色應該從存儲異常中捕獲該狀態代碼並從隊列中移除消息。

這是完全冪等的,您可以根據需要擴展工作角色。另外,您不依賴不保證FIFO的隊列中的消息順序。