Azure表存储数据一致性

时间:2009-11-19 14:00:17

标签: azure azure-queues

假设我在Azure表存储中有表

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

  public double Amount {get; set;}
}

Azure队列中的消息,其中将金额添加到金额

现在让我们说一个工人角色

  1. 从队列中获取此消息
  2. 从表中取出行
  3. 金额+ = 10
  4. 更新表格中的行
  5. 并失败
  6. 一段时间后,队列中的消息再次可用。所以下一个工人角色:

    1. 从队列中获取此消息
    2. 从表中取出行
    3. 金额+ = 10
    4. 更新表格中的行
    5. 从队列中删除邮件
    6. 这些操作会产生Amount += 20而不是Amount += 10

      我该如何避免这种情况?

4 个答案:

答案 0 :(得分:2)

我建议你实现一种乐观并发。您发送以更新行的消息应包含amount属性的“previous value”和“new value”。

因此,尝试更新行的第二个辅助角色将首先检查当前值是否仍等于“之前的值”。如果不是工作者角色知道出错了,他可以例如取消消息而不进行更新。也许还会在某些日志中引发错误。

答案 1 :(得分:1)

您放入队列的所有邮件都必须是幂等的。工人角色总是有可能无法完成工作,因此信息必须是可重复的。

所以代替金额+ = 10作为任务执行类似金额= 300的操作。 获取webrole中的当前金额添加10并将新金额放入队列。

我不确定这是不是正确的方法。如果您这样做,如果两个webroles尝试在同一时刻添加10,则会出现问题。

答案 2 :(得分:0)

你实现了这个或者只是一些想法的代码行吗?

“金额”意味着您正在考虑某种银行交易方案。直接使用SQL Azure可能会更好(因为您有ACID保证:http://blogs.msdn.com/ssds/archive/2009/03/12/9471765.aspx “我们一直支持服务中的完整ACID功能,并将继续这样做。”)

Afaik,我们可以说Windows azure中的“表格”就像谷歌大牌一样,不是吗?

答案 3 :(得分:0)

  1. 在队列中为您的邮件添加唯一的MessageId。
  2. 辅助角色从队列中读取消息,从表中读取实体
  3. 更新金额字段
  4. 进行批处理操作并将2行插回表中。第一个是更新的实体合并回到表,第二个是插入了相同的分区键和消息ID作为行键的实体。
  5. 批量操作将以原子方式执行。

    1. 现在,在您的示例中,如果另一个辅助角色尝试第二次处理相同的消息,则该操作将失败,因为表中已存在消息Id。然后,Worker角色应该从存储异常中捕获该状态代码,并从队列中删除消息。
    2. 这是完全幂等的,您可以根据需要扩展工作者角色。此外,您不依赖队列中的消息顺序,这不保证FIFO。