是否可以使用Azure表存储进行条件插入

时间:2012-01-31 17:21:11

标签: azure etag optimistic-concurrency event-sourcing azure-table-storage

是否可以使用Windows Azure表存储服务进行条件插入

基本上,我要做的是将新的行/实体插入到表存储服务的分区中,当且仅当我上次查看时该分区中没有任何更改。

如果你想知道,我考虑到了事件采购,但我认为问题比这更普遍。

基本上我想阅读部分或整个分区,并根据数据内容做出决定。为了确保自加载数据后分区中没有任何更改,插入应该像普通的乐观并发一样:只有在分区中没有任何更改的情况下插入才会成功 - 没有添加,更新或删除任何行。

通常在REST服务中,我希望使用ETag来控制并发性,但据我所知,分区没有ETag。

我能想出的最佳解决方案是为表中的每个分区维护一个单行/实体,其中包含时间戳/ ETag,然后使所有插入部分成为批次的一部分插入以及此'时间戳实体的条件更新'。然而,这听起来有点麻烦和脆弱。

Azure表存储服务是否可以实现这一目标?

2 个答案:

答案 0 :(得分:2)

一千英尺的视野

我可能和你分享一个小故事......

曾几何时,有人想要为一个聚合(来自Domain Driven Design成名)持续响应给定命令的事件。此人希望确保只创建一次聚合,并且可以检测到任何形式的乐观并发。

为了解决第一个问题 - 聚合应该只创建一次 - 他插入了一个事务媒体,当检测到重复聚合(或更准确地说是其主键)时,它会抛出。他插入的东西是聚合标识符作为主键和变更集的唯一标识符。处理命令时聚合生成的事件集合就是变更集的含义。如果有人或其他东西打败了他,他会考虑已经创建的聚合并留在那。变更集将预先存储在他选择的介质中。这种媒介必须做出的唯一承诺是在被问及时返回原样存储的内容。任何未能存储变更集都将被视为整个操作的失败。

为了解决第二个问题 - 在聚合的进一步生命周期中检测到乐观并发 - 在编写了另一个变更集之后,他会在事务介质中更新聚合记录,当且仅当没有人在背后更新它时(即与他在执行命令之前最后读取的内容相比较。如果发生这种情况,交易媒体会通知他。这将导致他重新启动整个操作,重新读取聚合(或其更改集)以使命令成功。(
) 当然,现在他已经解决了写作问题,随之而来的是阅读问题。如何能够读取构成其历史的聚合的所有变更集?毕竟,他只有最后提交的变更集与该事务介质中的聚合标识符相关联。因此他决定在每个变更集中嵌入一些元数据。在元数据中 - 作为变更集的一部分并不罕见 - 将是上一个最后提交的变更集的标识符。通过这种方式,他可以像他们所说的链表一样“走线”他的汇总变化集。

作为额外的特权,他还将命令消息标识符存储为变更集的元数据的一部分。这样,在阅读变更集时,他可以事先知道他即将在集合上执行的命令是否已经成为其历史的一部分。

一切都很好,结束得很好......

P.S。
 1.事务性介质和变更集存储介质可以是相同的,
 2.变更集标识符不能是命令标识符,
 3.随意在故事中打洞:-),
 4.虽然与Azure表存储没有直接关系,但我已使用AWS DynamoDB和AWS S3成功实现了上述故事。

答案 1 :(得分:2)

如何将每个事件存储在基于AggregateId / AggregateVersion创建的“PartitionKey / RowKey”中?其中AggregateVersion是一个基于聚合已经有多少事件的序列号。

这是非常确定的,因此在向聚合添加新事件时,您将确保使用它的最新版本,否则您将收到错误消息,指出该分区的行已存在。此时,您可以删除当前操作并重试,或者尝试确定是否可以合并操作,如果聚合的新更新与您刚刚执行的操作不冲突。