CQRS事件持久化到重建过程的疑问

14-03-16 wilsonp
在实践CQRS架构的时候,不太理解事件源的重建,所以一直不敢用eventsourcing。对事件的持久化可以理解,但对读取事件并使其重建聚合不知道该如何实现?

比如分析一个持久化然后重建的流程:

1、领域对象在特定时刻有特定的状态,此时发生状态改变的事件

2、将事件进行持久化

3、事件持久化之后发出一个事件已持久化的事件到事件总线,通知查询端

4、这时服务器宕机了,系统重新启动的时候,需要从事件源中读取事件来重现宕机是的内存状态

在此过程中有些问题:

1)关于第2点---这时领域对象的状态已经改变,也需要持久化吗?只是in memory?

2)关于第3点---此时的事件对象中是否包含第一步中状态发生改变的领域对象?如果不包括,那查询端如何知晓“哪个对象”的“哪个(些)状态发生改变”?

3)关于第4点,事件重建过程是我感觉模糊的过程,也是这点无法理解:

a、读取哪些事件?也就是事件持久化的时候需要进行编号?或者是通过时间戳来读取?如果是时间戳,那需要读取到什么时候的事件呢?

b、读取事件之后,事件源的状态不可确定,只能确定该事件中记录的修改之后状态,因为事件源的状态没有持久化

c、事件源的重建采用什么方式进行呢?也就是如何将读取到的相关联的事件进行关联。能够想到的方式是将所有相同事件源的事件对象进行重建,然后讲这些事件中保存的属性copy到事件源对象中,不知道这种考虑是否有问题

4)是否事件持久化和重读事件进行状态恢复的时候是有些关联?

问题有点多,但确确实实是CQRS初学者的疑问,这个过程理解了,在CQRS的架构上也基本清楚了

banq
2014-03-17 08:33
首先 EventStore存储的是事件,而事件与状态有对应关系,一个事件比如对应一个状态,因此状态就不必持久化了,要需要某个实体的状态,只要从这个状态初始开始的事件一直读取到当前,实际就是事件流,然后执行这些事件,实体状态也就重塑到当前状态。

下面引自:http://www.jdon.com/46051:

事件源系统的一个问题是"late joining client", 客户端为了获得系统的某个时刻的状态,将得重播整个系统的历史事件,为了解决这个问题,一种称为"Last value Cache"(LVC)的组件可以解决,LVC保持的是当前系统状态,并允许后来者late joining通过查询启动,当客户端数量增加时,LVC组件将又变成瓶颈。

wilsonp
2014-03-17 15:33
今天在向brighthas请教这个问题的时候,他提出了我之前没有想到的问题,也就是解决第一个问题的答案--snapshot,我之前没有想到这个答案。感谢brighthas。

因为snapshot保存了该对象实例当时的状态,而从这个状态为起点在读取向后发生的事件就可以准确还原出该实例的当前状态,但新问题又来了:

1、创建snapshot的粒度,也即是快照策略(snapshot strategy)?

2、snapshot的结构,是创建整个聚合根的快照呢还是聚合根内的所有实体都要单独创建快照并持久化?

3、snapshot包含当时领域对象的所有属性么?因为可能会存在集合属性这种1对N的情况

tangxuehua
2014-03-19 13:34
你问的问题确实比较多。你的问题其实不是CQRS架构,而是Event Sourcing。建议你看一些框架的实现,就能明白大部分问题了。随着你思考的深入,你还会想到更多的问题的。慢慢来,不要尝试一下子知道所有问题的答案。

猜你喜欢