关于DDD跨多个聚合对象的更新?

10-01-04 abayi
    

如果保证更新俩个聚合对象的内部状态的最终一致性。

eg)jdonjive

假设状况如下,必须同时更新俩个不同的聚合对象

ForumMessageReply tmp;//create a Object

Forum1.addNewMessage(tmp);//

Forum2.addNewMessage(tmp);//当执行到这儿时,业务规则不通过。

你们是如何维护或恢复第一个聚合对象的状态呢?

如果有transaction ,那么问题就解决了。(条件是没有软更新,软更新也是需要靠JMS 去触发进行软更新,以保证最终一致性)

可我看了jdonjive的源码,多是软更新,并没有任何的防范措施。

或许在论坛不用这么复杂。但是DDD其中一个目的就是为了复用对象呀。我找了很久,但就是没人说说如何更新俩个聚合对象,如何保证内部状态的最终一致性。

请解惑。谢谢。

我想到的是。通过已下方案解决

1)base on JMS solution.

UserTransaction trans=getTransaction

trans.begin();

try

{

ForumMessageReply tmp;//create a Object

// submit to jms,current state still not update,when JMS commit will triger

// object to update it,and notice Repository to store that state.

Forum1.addNewMessage(tmp);

// submit to jms,current state still not update,when JMS commit will triger

// object owner to update it,and notice Repository to store that state.

Forum2.addNewMessage(tmp);

trans.commit();

//JMS will notice Object to update that reference.

}

catch(Exception e)

{

trans.rollback();

//when rollback,JMS not commit, so not event to update object state.

}

2)Base on transaction support 的 reference , List, Map .....

trans.begin();

Forum1.addNewMessage(tmp); //add object to List(Transaction Support).

Forum2.addNewMessage(tmp); //add object to List(Transaction Support).

trans.commit();

    

3
banq
2010-01-05 09:37

2010年01月04日 21:12 "abayi"的内容
没人说说如何更新俩个聚合对象,如何保证内部状态的最终一致性

通过Domain Events实现,可见使用CQRS重新考虑架构

当一个聚合状态被修改时,由这个聚合发出事件,更新另外一个聚合对象的状态。

至于最终一致性,可根据CAP定律和BASE思想,需要在一致性 性能和容错性三个只能取两个,不可能三个都要,反而要不到。

所以,具体最终一致性根据业务需求,从你的解决方案来看,你是想获得最高一致性,使用分布式事务,当然这以牺牲性能可用性为代价的,会使得你的系统非常得慢,丧失了可用性。

如果想提高性能,获得一定可用性,就采取BASE思想,降低高可用性,不要用分布式事务,而是使用分布式事件,这个使用CQRS重新考虑架构已经讲得很清楚了。

abayi
2010-01-05 12:02

可是俩个模型中数据一致性的问题呢?(我不是说数据库中的数据 与 模型中数据 的一致性)

“当一个聚合状态被修改时,由这个聚合发出事件,更新另外一个聚合对象的状态”

Object1 --Send Event Update ----Object2

|

|------Send Event Save to db。

那么("更新另外一个聚合对象")当第二个聚合对象内部状态更新失败的时候,如何恢复或保持两个聚合对象的状态呢?

因为object1 可能已经更新本身的状态了(数据库的更新通过异步达成)

object1也发出了更新事件给object2 了。刚好object2不同过本身的更新逻辑发出失败。

可是业务逻辑需要俩个更新都通过才行呀。

如果不是在交易事务下去控制事件的发出,那么聚合对象内部的状态不是会有不一致的情形吗?

banq
2010-01-05 13:44

2010年01月05日 12:02 "abayi"的内容
当第二个聚合对象内部状态更新失败的时候,如何恢复或保持两个聚合对象的状态呢

这实际上是事件总线Event bus设计任务,在CQRS中也提到了:将事件进行记录log,通过事件回滚,可以将状态返回之前状态。

如果你采取分布式交易事务也可以,但是可用性性能会很差,因为出问题概率很小,不能因为小概率失误发生而耽误大概率的可用性。所以,你对事务乐观还是悲观决定了你对延迟的态度。