Azure表存储能否进行有条件的插入?

7
在 Windows Azure 表存储服务中,是否可能实现 有条件的插入
基本上,我想做的是,只有在我上一次查看时该分区中没有任何更改时,才将新的行/实体插入到表存储服务中。
如果你好奇的话,我考虑了事件溯源,但我认为这个问题比那更普遍。
基本上,我想读取部分或整个分区,并根据数据内容做出决策。为了确保在加载数据后分区中没有发生任何更改,插入应像正常的乐观并发控制一样:只有在分区中没有更改 - 没有添加、更新或删除行 - 的情况下插入才能成功。
通常在 REST 服务中,我希望使用 ETags 来控制并发,但据我所知,没有针对分区的 ETag。
我能想到的最好的解决方案是,在表中为每个分区维护一个单独的行/实体,其中包含时间戳/ETag,并使所有插入成为批处理的一部分,包括插入以及对此“时间戳实体”的有条件更新。然而,这听起来有点麻烦和脆弱。
Azure 表存储服务是否支持这种操作?

我对Azure没有任何实际经验,但您是否在寻找“插入或合并实体”?http://msdn.microsoft.com/en-us/library/windowsazure/hh452241.aspx...我怀疑您没有看过这个。 - Yves Reynhout
2个回答

4

千尺之高

我能和你分享一个小故事吗?

从《领域驱动设计》中闻名的聚合(aggregate)在响应给定命令时,有人想要持久化其事件。这个人想要确保一个聚合只被创建一次,并且可以检测到任何形式的乐观并发。

为了解决第一个问题——聚合只应该被创建一次——他在事务性介质中插入了一个会在检测到重复的聚合(或更准确地说是其主键)时抛出异常的操作。他所插入的是聚合标识符作为主键和变更集的唯一标识符。这里所说的变更集是指聚合在处理命令时产生的事件集合。如果有人或其他东西比他先完成了这项操作,他将认为聚合已经被创建,并且不再执行任何操作。变更集将预先存储在他选择的介质中。这个介质必须做出的唯一承诺是在被询问时按原样返回已存储的内容。任何存储变更集失败的情况都将被视为整个操作的失败。

为了解决第二个问题——在聚合的进一步生命周期中检测乐观并发——在写入另一个变更集之后,如果没有人在他背后更新了聚合记录(即与他在执行命令之前最后读取的内容相比),他只会在事务性介质中更新聚合记录。事务性介质将通知他是否发生了这种情况。这将导致他重新启动整个操作,重新读取聚合(或其变更集)以使命令成功执行。

当然,现在他已经解决了写入问题,阅读问题也随之而来。如何能够读取组成其历史的聚合的所有变更集?毕竟,在该事务性介质中,他只有与聚合标识符相关联的最后提交的变更集。因此,他决定将某些元数据嵌入到每个变更集中。元数据是作为变更集的一部分而不那么常见的。其中之一是上一个已提交的变更集的标识符。这样,他就可以“沿着线路”查看聚合的变更集,就像链表一样。

作为额外的好处,他还将命令消息标识符作为变更集的元数据存储。这样,在阅读变更集时,他就可以提前知道要在聚合上执行的命令是否已经是其历史的一部分。

一切都圆满结束了...

P.S.
1.事务性介质和变更集存储介质可以是相同的,
2.变更集标识符不得是命令标识符,
3.请随意挑剔这个故事 :-),
4.虽然与Azure Table Storage无直接关系,但我已经成功地使用AWS DynamoDB和AWS S3实现了上述故事。


顺便提一下,我之前写过关于这种方法的博客:http://seabites.wordpress.com/2011/12/07/your-eventstream-is-a-linked-list/ - Yves Reynhout

2
如何将每个事件存储在基于AggregateId/AggregateVersion创建的"PartitionKey/RowKey"中?其中,AggregateVersion是基于聚合已有多少个事件的顺序号。
这种方法非常确定,因此在向聚合添加新事件时,您必须确保正在使用它的最新版本,否则会出现错误,提示该分区的行已存在。此时,您可以放弃当前操作并重试,或者尝试弄清楚是否仍可合并操作,如果聚合的新更新与您刚刚执行的操作不冲突的话,那么就可以进行合并。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接