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

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

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

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

如果您想知道,我想到的是事件溯源,但我认为问题比这更普遍。

基本上我想读取部分或整个分区,并根据数据内容做出决定。为了确保自加载数据以来分区中没有任何变化,插入的行为应该像正常的乐观并发一样:只有在分区中没有任何变化时插入才应该成功 - 没有添加、更新或删除行。

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

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

使用 Azure 表存储服务可以实现这一点吗?

最佳答案

千英尺处的景色

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

曾几何时,有人想要保留聚合事件(来自领域驱动设计名声)以响应给定的命令。此人希望确保聚合仅创建一次,并且可以检测到任何形式的乐观并发。

为了解决第一个问题——聚合只能创建一次——他在事务介质中进行了插入,当检测到重复聚合(或更准确地说是其主键)时,该插入就会抛出。他插入的是作为主键的聚合标识符和变更集的唯一标识符。此处所说的变更集是在处理命令时由聚合产生的事件集合。如果有人或其他事比他先一步,他会考虑已经创建的聚合并保留它。变更集将预先存储在他选择的介质中。该媒介必须做出的唯一 promise 是在被要求时按原样返回已存储的内容。任何未能存储变更集的行为都将被视为整个操作的失败。

为了解决第二个问题 - 在聚合的进一步生命周期中检测乐观并发 - 在编写另一个变更集之后,当且仅当没有人在他背后更新它时,他才会更新事务介质中的聚合记录(即与他在执行命令之前最后阅读的内容进行比较)。如果发生这样的事情,交易媒介会通知他。这将导致他重新启动整个操作,重新读取聚合(或其变更集)以使命令这次成功。

当然,现在他解决了写作问题,随之而来的是阅读问题。人们如何能够读取构成其历史的聚合的所有变更集?毕竟,他只有与该事务介质中的聚合标识符相关联的最后提交的变更集。因此,他决定嵌入一些元数据作为每个变更集的一部分。在元数据中(作为变更集的一部分并不罕见)将是先前最后提交的变更集的标识符。这样他就可以“沿着”聚合的变更集“走线”,就像一个链接列表一样。

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

一切都好,结局好......

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

关于azure - 是否可以使用 Azure 表存储进行条件插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9083972/

相关文章:

azure - 新的 Azure 服务总线库可以与之前的服务总线库一起使用吗?

Azure 表存储 (412) 前提条件失败

azure - 无法在 azure 机器学习服务工作区中注册 ONNX 模型

node.js - 尝试从 Node 查询 documentDB 时请求 url 无效

performance - 根据资源的时间戳生成 ETag 的最佳方法是什么

ruby-on-rails - Rails fresh_when 应该在 etag 中包含当前用户 ID

python - 在 Django 的基于类的通用 View 中使用 ETag/Last-Modified 装饰器

c# - Entity Framework 6 Oracle 和乐观并发

entity-framework - 在 Entity Framework 中处理并发

azure - Azure 函数应用程序上忽略了routePrefix