问题 事件采购和乐观并发控制


当您希望代码在竞争条件下工作时,通常是开发人员使用 乐观的并发控制 (OCC)。来自维基百科:

...在提交之前,每笔交易都验证没有其他交易   事务已修改它已读取的数据。如果检查显示   相互冲突的修改,提交事务回滚......

实现OCC的方法是检查a version 要修改的数据。如果版本不同,那么其他事务已修改数据,并由应用程序决定如何解决冲突(重新尝试,通知用户......)。

草案如下:

class Repository
{
    public class save($data)
    {
        $currentVersion = $data->version;
        $data->version  = $currentVersion + 1;

        $result = $this->db->update($data, [
            'id'        => $data->id,
            'version'   => $currentVersion
        ]);

        if (1 === $result) {
            // everything ok
        } else {
            // conflict!
        }
    }
}

我的问题是,如同 EventSourcing 只有我们 附加 在域中发生的所有事件,我们不能再使用这种方法来实现OCC。在使用EventSourcing时,哪些其他方法可以保留OOC?

一个可行的选项,它可以在存储时查找冲突事件。这种方法允许对事件进行细粒度控制。我不知道这是否会使解决方案复杂化,或者我认为这是一个“标准” http://danielwhittaker.me/2014/09/29/handling-concurrency-issues-cqrs-event-sourced-system/

问题描述中的任何空白都是值得赞赏的。提前致谢!


12166
2018-03-24 12:32


起源



答案:


尝试将事件附加到流时,您可以指定预期的当前版本号,并在实际当前数字与其匹配时抛出。

这种乐观的并发机制是 内置于 一些事件存储系统。

您链接到的文章似乎描述了一种类似的方法,但更强大,因为您可以访问自预期版本以来发生的事件类型,并且可以根据更细粒度的标准检测冲突。


12
2018-03-24 13:26





应用事件源您还应该在表中有一个版本字段,否则在构建聚合根时无法获取事件的顺序。但顺序很重要。您还可以使用此版本字段来支持OCC。 例如,如果您有两个具有相同ID的事件的竞争条件,并且在事件存储中几乎同时保存相同的版本,则最后一个丢失,如果使用复合,则会引发重复键异常主键由聚合ID和版本组成。


2
2018-04-21 20:47





默认 乐观的锁 不适用于事件采购,原因 乐观的锁 要求 一个状态 被锁定。在事件采购中,您没有类似州的任何内容,您只需拥有事件列表(更改流)。 在您可以使用以下方法之前已经提到过几次:

  1. 每个事件都有修订号(事件采购方法中的事件很常见)
  2. 每当有任何事件发生并且您需要保存它时,您应该从事件存储中获取最新的修订号
  3. 在事件存储中保存之前,只需增加此修订号
  4. 确保在事件存储中具有唯一的修订号索引
  5. 如果两个并行事务增加了最后修订号(例如5) 并尝试保存两个增加修订号的新事件(在我们的例子中它将是6),其中一个因为唯一索引而失败。

还请记住,您的事件存储应该允许您使用唯一索引,在这种情况下,RDBMS表是最佳选择。


1
2018-06-01 14:12