CQRS 架构中 一个事务生成的多个领域event 如何执行

CQRS 架构中 多个事务生成的领域event 谁先执行谁后执行?

https://github.com/banq/jdonframework/blob/master/example/cqrs%2Bes/match/src/main/java/sample/domain/Match.java


@Model
public class Match {
private String id;
private Date matchDate;
private Team teams[] = new Team[2];
private boolean finished;
@Inject
public EventSourcing es;
public void handle(MatchCreatedEvent matchCreatedEvent) {
this.id = matchCreatedEvent.getMatchId();
this.teams[0] = new Team(matchCreatedEvent.getMatchTeamName1());
this.teams[1] = new Team(matchCreatedEvent.getMatchTeamName2());
this.finished = false;
}
public void startMatch(Date matchDate) {
if (this.matchDate != null)
System.err.print("the match has started");
es.started(new MatchStartedEvent(this.id, matchDate));
}
public void handle(MatchStartedEvent event) {
this.matchDate = event.getMatchDate();
}
public void finishWithScore(Score score, Date matchDate) {
if (this.matchDate == null)
System.err.print(
"the match has not started");
if (finished)
System.err.print(
"the match has finished");
es.finished(new MatchFinishedEvent(this.id, matchDate, score.getHomeGoals(), score.getAwayGoals()));
}
public void handle(MatchFinishedEvent event) {
this.finished = true;
}
public String getId() {
return id;
}
public String getHomeTeamName() {
return teams[0].getName();
}
public String getAwayTeamName() {
return teams[1].getName();
}
public boolean isFinished() {
return finished;
}
}

异步框架,通过事件进行异步化.
可能一个事务生成了一场比赛事件MatchStartedEvent1,还有其他实体的事件.比如每个人出场次数+1Event PersonEvent1;
另外一个事务生成了另外两个事件. MatchStartedEvent2 ,PersonEvent2.
然后会处理这些事件,因为MatchStartedEvent1和PersonEvent1之前是属于一个事务的, 那么我的问题是执行两个事件,把Match和Persion的变化持久化到数据库.
.是否也是放在一个事务内执行?
如果不是,如何保证事务内操作的要么全部回滚,要么全部成功的特性

我不是很清楚你的事务是业务用语还是技术用语,因为我们过去技术影响,可能会将一些技术用语加入到业务中。

事务是一种高一致性的用语,这是从强一致性角度看待问题。建议参考:弱一致性在现实世界中到处存在

CQRS的EventSourcing中将事件作为原子不变量记录,然后根据时间顺序播放本身就已经有事务概念,这个事件流只能播放或追究,不能删除和修改的。

提供你一个英文参考:General-purpose databases that never delete or update data in-place

http://www.cqrs.nu
[该贴被banq于2014-06-19 13:13修改过]

值得是技术上的事务 spring @[author]Transaction[/author] .

jdbc.setAutoCommit(false)

2014-06-19 13:12 "@banq"的内容
时间顺序 ...

对,关键是用什么排序的问题.
时间排序我想过显然是不够严谨的.因为时间是有精度的.总有可能两个事件时间是一样的.
用事件数据库自增id也是错误的.
因为spring @[author]Transaction[/author] 内 ,
事务1 生成Event1 获得的数据库自增id是1
事务2 生成Event2 获得数据库自增id是2.
然后事务2提交.
然后事务1提交.

那后面操作事件的顺序应该是 event id=2 ,然后才是event id=1 .

我有点想不通,如何实现才能保证事件按照事务提交顺序进行操作.



[该贴被sinaID87521于2014-06-20 13:30修改过]

可以去看一下enode的实现。

2014-06-20 20:27 "@tangxuehua"的内容
enode的实现。 ...

感谢你的思路.
看了下,原来这个的目的是解决两个聚合跟的问题.
我重新思考了下,其实person 其实算是聚合跟match下面的一个类.
所以开赛这个动作还是只会产生一个事件.
所以说很多时候一个动作都只是操作的是一个聚合跟.
想咨询下,一般哪些情况一个动作可以操作多个聚合跟.

比如银行转账,会涉及到源账号、目标账号、还有交易三个聚合根;交易这个聚合根用于表示这一次转账的过程状态;记录转账的相关信息。

再比如用户下单,我们至少会创建订单,还会商品库存数量的减少。

这两个场景,都是修改或创建多个聚合根的场景。我建议通过领域事件的方式,实现聚合根之间的异步通信,实现最终一致性;

有些时候,你甚至只能这么做,因为商品中心和订单中心是在不同的db,那你用分布式事务代价是很高的;还有比如跨行转账,也是不同的系统之间的数据交互,两个账号聚合根在不同的系统,所以,一般也都是最终一致性;所以,你也经常看到你的一笔转账,不会立马到账。
[该贴被tangxuehua于2014-06-25 09:24修改过]