Orleans 2.0 官方文档 —— 4.9.8 Grains -> 事件溯源 -> 复制的实例

复制的grain

有时,同一个grain的多个实例,可能都处于活动状态,例如在操作多个群集时,以及使用[OneInstancePerCluster]属性时。JournaledGrain旨在以最小的摩擦,支持复制的实例。它依赖于日志一致性提供程序来运行必要的协议,以确保所有实例在相同的事件序列上达成一致。特别是,它关心以下几个方面:

  • 一致的版本:grain状态的所有版本(除了暂定版本),都基于相同的全局事件序列。特别是,如果两个实例看到相同的版本号,则它们会看到相同的状态。

  • 争用的事件:多个实例可以同时激发一个事件。一致性提供程序解决此争用,并确保每个人都遵循相同的顺序。

  • 通知/反应性:在一个grain实例上激发事件后,一致性提供程序不仅更新存储,还会通知所有其他的grain实例。

有关一致性模型的一般性讨论,请参阅我们的TechReport和GSP论文(全局序列协议)。

有条件的事件

争用事件如果发生冲突,可能会出问题,例如,由于某种原因,不应该同时提交。举例来说,当从银行账户中提取资金时,两个实例可以独立地确定有足够的资金用于提款,并发出提款事件。但两个事件的结合可能会透支。为了避免这种情况,JournaledGrain API支持RaiseConditionalEvent方法。

bool success = await RaiseConditionalEvent(new WithdrawalEvent()  { ... });

条件事件会双重检查本地的版本是否与存储中的版本相匹配。如果不是,则意味着事件序列在此期间已增长,而这意味着该事件在与其他事件的争用中输了。在这种情况下,条件事件不会附加到日志中,并且RaiseConditionalEvent会返回false。

这类似于使用有条件的存储更新的e-tags,同样提供了一种避免提交冲突事件的简单机制。

对同一grain,同时使用有条件事件和无条件事件,是有可能的,也是合理的,例如一个DepositEvent和一个WithdrawalEvent。存款不必是有条件的:即使DepositEvent输掉了争用,它也不必被取消,但仍可以附加到全局事件序列。

等待RaiseConditionalEvent返回的任务,足以确认事件,即,不必再调用ConfirmEvents

显式地同步

有时,我们希望确保grain完全符合最新版本。这可以通过调用来强制执行

await RefreshNow();

其中(1)确认所有未确认的事件,(2)从存储记载最新版本。

你可能感兴趣的:(Orleans)