Mar*_*edy 5 optimistic-concurrency ravendb event-sourcing
我正在尝试使用符合我所看到的各种 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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当只有一个应用程序时,这基本上可以正常工作。当当前线程获取锁、检查版本然后写入自己的事件时,锁会停止任何其他线程将事件写入事件存储。
然而,想象两个独立的客户端在不同的机器上运行。显然,这两个进程都可以一起进入锁,然后它们都可以执行该GetById()方法,并且都可以看到相同的当前提交的版本。然后,两个进程将继续写入具有递增版本号的未提交事件。但是,这会使聚合的事件流处于可能存在具有相同版本号的不同事件的状态。
我知道我可以做一些回顾性决议,但这不是我想要完成的。
现在很明显,这意味着需要在事件存储数据库方面进行某种锁定。谁能建议如何做到这一点?答案不一定是特定于数据库的,但是 ravendb 示例会很棒,因为这就是我计划用它来构建我的事件源系统原型的原因。
| 归档时间: |
|
| 查看次数: |
680 次 |
| 最近记录: |