我试图实现使用的做法和原则符合各种Greg Young的启发我见过的例子事件采购系统事件存储。实现与并发检查了多个客户端
我理解的版本检查逻辑是如何工作的,并且保存汇总时,如果当前的版本不符合预期的版本就意味着另一个会话/客户端应用程序更新了总你以前。
我也明白,你可以在地方有追溯解决冲突的方法,当并发事件已经保存,这个问题是没有这么多事情了。
我想了解的是,在使用nosql数据库(如ravendb作为事件存储)的特定实现中,如何确保由于竞争条件而写入的事件从不重叠版本号。
从实例项目下面的代码来说明:
在Repository<TAggregate>
仓储类有一个保存方法
public void Save(AggregateRoot aggregate, int expectedVersion)
{
if (aggregate.GetUncommittedChanges().Any())
{
lock (_lockStorage)
{
var item = new T();
if (expectedVersion != -1)
{
//issue if two processes get to this line of code below together
//and both have the same 'version to be expected' then start writing together
item = GetById(aggregate.Id);
if (item.Version != expectedVersion)
{
throw new ConcurrencyException(string.Format("Aggregate {0} has been previously modified",
item.Id));
}
}
_storage.Save(aggregate);
}
}
}
现在基本上是当只有一个单一的应用程序能正常工作。在当前线程取得锁定,锁定版本,然后编写自己的事件时,锁定将停止任何其他线程将事件写入事件存储。
然而,想象两个独立的客户端运行在不同的机器上。很明显,这两个进程都可以同时进入锁,它们都可以执行GetById()
方法,并且都看到相同的当前提交版本。这两个进程将继续用增加的版本号编写未提交的事件。但是,这会将聚合的事件流留在可能有不同事件具有相同版本号的状态。
我知道我可以做一些回顾性的分辨率,但是这不是我想要完成的任务。
现在,很显然,这意味着需要对事物的事件存储数据库端完成某种锁定。任何人都可以建议如何做到这一点?答案并不一定是数据库特定的,但ravendb的例子会很好,因为这正是我打算用我的事件采购系统的原型。