你上次翻译的通过设计一个转账聚合根来在代码层面实现2pc的方法,本质上也没有实现强一致性 ...
你说的有道理,转账是REST和DDD的这个案例:http://www.jdon.com/45622/5#23143081
我们需要分清楚业务上事务和技术上事务两个,2PC两阶段提交 还是锁事务等属于技术上的事务,使用技术事务的前提是,我们首先要发现业务中需要事务的业务操作过程,注意这里首先发现的是业务操作这个动词,这种先入为主的动词发现法不是DDD对象分析法。
回到转账这个案例,如果动词先入为主,那么将转账做成一个服务,然后加上悲观锁或2PC,这是一般人的习惯思维。
使用DDD,是将转账作为一个聚合根实体,在转账这个聚合根内部来保证转账这个业务事务的实现,那么如何实现呢?简单地办法就是用一个方法如下:
void transfer(){
a.remove(100);
b.add(100);
}
这里transfer方法没有加同步,是默认转账这个对象使用Actor这样模型,而a帐号和b帐号属于transfer这个聚合内部的对象。
我在‘REST和DDD’中翻译的老外转账案例为什么在Transfer聚合根和A B帐号之间用command和event这样消息机制实现呢?前提是A和B帐号不在transfer这个聚合边界内,这其实是一种使用消息系统这样的技术手段实现事务(保证可靠性),但是不代表不是强一致性,使用消息实现可靠性在大数据分析架构中常见,例如Kafka 可以实现消息回放已经消息commit确认,只有发出去的消息完成才能commit确认,见这个帖子:http://www.jdon.com/45698#23143267
打个比喻:
Transfer <------> A
<--------> B
Transfer与A B之间的交互通过消息系统是确保消息可靠地参与到A或B扣款这个业务动作中,也就是说:只有A扣款了,带有扣款命令的消息才从队列中删除,只有B加款了,带有加款命令的消息才从队列中删除,至于这两个动作如何保证一致性,是在Transfer聚合根的transfer方法中来保证。
可以这么说,消息系统是实现分布式事务的一个技术手段,一个环节,但不是全部,更不代表使用了消息系统就意味弱一致性。