2017-10-12 56 views
1

假设我们有一个总计User,其中UserPortraitImageContract作为PDF文件。我想将文件存储在专用的基于文档的存储中,并在事件中保存与进程相关的数据(通过指向BLOB数据的链接)。在事件源应用程序中避免两阶段提交保存BLOB数据

但是,当我必须存储文件并存储新事件时,如何避免两阶段提交?

起初,我会存储文件,然后事件;如果第一个事务失败则无关紧要,该命令失败。如果第二个事务失败,即使我们在存储中生成了一些死文件,也没有关系,该命令失败;我们甚至可以应用回滚。 但是会有额外的问题吗?

接下来的问题是如何设计聚合和事件。如果聚合只保存对BLOB存储的引用,那么调用SignUp命令后的过程是什么?

SignUpCommand ==>存储文档(UserPortraitImageContract)==>用给定的BLOB存储引用创建新的User聚合并存储它?

是否有更好的设计,可以在知道BLOB数据保存在另一个存储区的情况下卸载聚合的负担?谁负责存储BLOB数据并将引用转发给聚合?

回答

2

听起来像您正在使用类似于AtomPub media-entry/media-link-entry对的东西。 blob进入你的数据存储,元数据被复制到聚合历史中

但是,当我必须存储文件并存储新事件时,如何避免两阶段提交?

在实践中,你可能不会。

也就是说,如果blob存储和聚合存储碰巧是同一个数据库,那么您可以在同一个事务中更新这两个存储。这两家商店结合在一起,并为您选择的存储添加了一些非常强大的限制条件,但它是可行的。

另一种可能性是,您接受您正在进行的两项更改是相互隔离的,因此在一段时间内两家商店彼此不一致。

在这第二种情况下,the saga pattern就是您要查找的内容,而这正是您所描述的;如果第二个操作失败,则将第一个操作与补偿操作配对。所以“手动”回滚。

还是不行 - 从某种意义上说,git对象数据库使用两阶段提交;一个对象被复制到对象存储中,然后树被更新,然后提交...垃圾收集随后出现以放弃不需要的对象。

谁负责存储BLOB数据并将引用转发给聚合?

那么,最终它是一个基础设施问题;你的模型实际上是否需要与文档进行交互,还是仅仅携带一个可以在以后兑换的claim check

+0

如果我使用佐贺,我在哪里同时保存BLOB数据?这个过程将如何进行? –

1

起初我会存储文件,然后事件;如果第一个事务处理失败,则该命令失败。如果第二个 事务失败,即使我们在存储中生成了一些 死文件也无所谓,该命令失败;我们甚至可以应用 回滚。但是会不会有额外的问题?

不是我能想到的,除了浪费的磁盘空间。当我想要避免分布式事务或者当它们不能跨两种类型的数据存储时,我通常会这样做。通常,两种操作中的一种操作并不重要,即使主操作稍后失败,也可以让其完成。

清理拙劣的尝试可以在异常处理期间完成,作为带外过程或者作为@VoiceOfUnreason解释的佐贺的一部分。

SignUpCommand ==>存储文件(UserPortraitImage和合同)==> 创建新的用户聚合与给定的BLOB存储引用和 店呢?

是的。通常情况下,应用层组件(您的情况下的命令处理程序)充当不同数据存储区之间的协调器,并在与另一个存储区或域交谈之前从一个存储区中获取所需信息。

相关问题