我試圖實現使用的做法和原則符合各種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的例子會很好,因爲這正是我打算用我的事件採購系統的原型。