对CQRS架构的几点疑问

在看到CQRS架构之后觉得很有道理,但是有以下几点疑问

1.CQRS架构图中的在发生一个Command之后肯定会有一个Command Handle来做处理,并且Command这是满足并针对自身的,但是后面又看到了Command Handle来调用Domain,并且Domain在调用Repository,疑问就出现在这里了,为什么Handle要去调用Domain,还有就是Repository是否要注入到Domain中,还是说可以使用Event来调用Repository.

2.看CQRS架构中出现了Snapeshot和Event Store,疑问是SnapeShot跟Event Store之间是否有关系存在,还有就是SnapeShot跟Event Store两者区别在那里.

3.Banq老师说到了EJB推崇贫血模式,在CQRS架构在集群中是使用事件来做传递的,但是事件是有事件源的,事件在传递的过程中事件源不需要做传递么.还是将事件源存储在某个中心服务器上面.

4.Banq老师说道ActiveRecord的致命缺陷是:当业务逻辑复杂到一定程度,它开始崩溃,业务逻辑很难维护,一致性保证很困难,更进一步说:实际上是关系数据库掌管了业务状态,关系数据库成为单点风险和性能瓶颈,只能走数据库sharding 等路线进行伸缩(本站有更多关于关系数据库问题的文章),这里业务逻辑复杂之后会很难维护本人不是很明白上述几点问题,还请举例说明.

对于以上几点问题还请大家详细说明,谢谢!

1,Commond到达它被处理的Handler,这通常是一对一,然后会触发领域模型的交互,因为业务逻辑在Domain上,Domain的行为会生成领域事件,Domain没有直接掉Repository,注意那张图,Domain由Repoisitoy返回,Domain上的事件可能由Reposiotry发到事件总线。

2,Snapeshot是模型的快照,Event Store是存储在Domain上的事件,举个例子,一个人从出生就开始记录在它身上发生的任何事情,然后让他再出生的一次,同时把Event Store里事件回放一下就可以还原到它的现在。可想而知,这个事件太多了,那么就在某个时候保存一个快照,比如在他18岁的时候,这样就可以从18岁开始回放。

3,这个看你怎么设计,可以直接带事件源对象或者带ID,因为我们通常处理的是实体对象,用ID去Repository里取就可以了。Jdon框架带的只是一个Object,随便你放什么。

4,活动记录,和关系数据库绑得太死,那么问题就是关系数据库的问题,多搜索一下。

希望对你帮助!
[该贴被oojdon于2010-12-18 19:57修改过]

首先很感谢你的回答,确实帮助了我很多,但是还有有几个问题

1.Handle主要做什么,还有Handle来驱动Domain触发事件么

2.SnapeShot是模型的一个快照,我可以把它看做是一个带有时间标识的缓存么,而Event Store是存储历次状态事件的存储点,由SnapeShot返回某个时间点的模型标识(ModelId),在到Event Store去取出跟此次状态有关的事件么

3.CQRS架构的读写分离,本人不是很明白读如何进行分离,是否需要针对查询来做专类的对象。但是如果使用查询专类对象的话,那么Domain对查询专类对象有用处,因为两者还是有所区分的

1,Handler就是接受到命令然后让领域模型做事情,这个Handler我认为在某些时候还可以省略,在JiveJdon中有直接把命令打到Domain上的代码,领域模型在完成业务逻辑的时候会产生事件,比如货物到达目的地会有deliver事件,商品有上架事件或被买走事件,领域事件由领域模型扔出来的,当然系统中还有各色各样的事件。

2,事件回放产生完整Domain,DDD Factory也可以产生完整Domain,有完整Domain才会有缓存,至于怎么得到这个完整Domain,你可以事先直接把对象序列化,或者从数据库中构造。

2010年12月18日 22:06 "spawnyy"的内容
由SnapeShot返回某个时间点的模型标识(ModelId) ...
注意,对象标识是不变的,和时间没有关系。

3,想象没有数据库,数据是领域对象交互完成业务逻辑时的产物,这个产物被异步到一个sql或者nosql DB保存,然后有人直接来这个DB查询,你怎么查,怎么优化,怎么加视图,加缓存,怎么做DTO,怎么Match你的UI,是你的事,Domain已经分析和开发完成,这就是读写分离。

这是我对CQRS的理解,大家一起讨论吧。


[该贴被oojdon于2010-12-19 11:10修改过]
[该贴被oojdon于2010-12-19 11:13修改过]

我个人感觉也没什么必要增加Handle,这里的Command就是命令只要发送到Domain受理就可以了,但是可能我理解的SnapeShot有点问题,这个快照是一个模型近期的快照呢,还是历次的回放?还有就是Event Store每次存储事件的时候可以把它看做是一个存储器吧,不过存储的方式是存储事件呢还是事件源呢。对于读写分离,如何读这块需要根据自己需要去设计,而不是将Domain去为查询去做些妥协的事情,对么?
[该贴被spawnyy于2010-12-19 11:47修改过]

Handler可以做权限等事情,所以是有必要的,保持Domain层的足够内聚,DDD书中也还有应用层到领域层呢!
Domain对象可能就是一个不Match UI 和 DB的东西,我们现在不过是向两边妥协了,所以有Action几千行,Service几千行的代码
Hibernate in Action书中的案例代码,DDD sample 使用SSH的方式都不是这样的。
对于cqrs,你可以研究下axon这个框架。该框架实现的快照是可配置的,做法是直接将对象序列化,比如配置你18岁,22岁序列,然后就不用回放你18岁之前,22岁之前。
[该贴被oojdon于2010-12-19 12:16修改过]

2010年12月18日 19:45 "oojdon"的内容
Commond到达它被处理的Handler,这通常是一对一,然后会触发领域模型的交互 ...

    其实,这是我认为DDD中领域事件的局限性。在我看来,一个Commond可能会有多个handler,甚至还会有多个handler的编排,就像ESB里做的一样。在复杂的业务场景里,一个对象的创建常常会导致多个对象的状态发生变化,这还不包括仓储层的响应。