Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 如何管理CQRS和x2B中的视图模型更改;事件源架构_Design Patterns_Architecture_Cqrs_Event Sourcing - Fatal编程技术网

Design patterns 如何管理CQRS和x2B中的视图模型更改;事件源架构

Design patterns 如何管理CQRS和x2B中的视图模型更改;事件源架构,design-patterns,architecture,cqrs,event-sourcing,Design Patterns,Architecture,Cqrs,Event Sourcing,我们目前正在评估CQR和事件源架构。我试图了解使用这种设计对维护的影响。我正在努力寻找答案的两个问题是: (一) 如果在应用程序启动并运行一段时间后,有新的需求需要在ReadModel数据库的ViewModel中添加一个额外的字段,会发生什么情况?比如说,CustomerList ViewModel上需要客户邮政编码,而以前没有。因此,可以很容易地将额外的列添加到ViewModel数据库中,但是如何填充它呢?就我所见,唯一的方法是清除read数据库,从头开始重放所有事件以构建ReadModel数

我们目前正在评估CQR和事件源架构。我试图了解使用这种设计对维护的影响。我正在努力寻找答案的两个问题是:

(一) 如果在应用程序启动并运行一段时间后,有新的需求需要在ReadModel数据库的ViewModel中添加一个额外的字段,会发生什么情况?比如说,CustomerList ViewModel上需要客户邮政编码,而以前没有。因此,可以很容易地将额外的列添加到ViewModel数据库中,但是如何填充它呢?就我所见,唯一的方法是清除read数据库,从头开始重放所有事件以构建ReadModel数据库。但是,如果应用程序已经启动并运行了数月或数年(我们希望如此),该怎么办。这可能需要重播数百万个事件,只需为zipcode列添加数据

无论出于何种技术原因,如果ReadModel数据库不同步,或者我们想添加一个新的ReadModel数据库,我都会有同样的担忧。看起来应用程序越老,使用的越多,就越难收回最新的readmodel,成本也就越高。还是我错过了什么把戏?比如ReadModel快照

(二) 如果在所有数百万个事件被重放以建立读取数据库之后,某些数据与预期不符(即,看起来是错误的),会发生什么情况。人们认为,可能是事件存储或非规范化例程中的某个错误导致了这一点(似乎如果在编码中有一件事可以依赖的话,那就是错误)。如何调试这个!这似乎是一项不可能完成的任务。或者,也许我又错过了一个窍门

我很想听听任何一个已经运行了一段时间的系统的人,他们的维护和升级路径是如何为您工作的


感谢您的时间和投入。

我对CQRS有些陌生,所以这可能不是最合适的路线(但iirc我从CQRS/DDDD邮件列表中选择了它)

我们创建了一个命令和相应的处理程序,该命令和处理程序特定于预期在弃用后运行的目的


在处理程序中,我们使用任何方便的机制,因此在添加邮政编码字段的情况下,我们可以运行一次性查询,从另一个视图模型中提取当时的邮政编码并填充新列。我们不太担心这些场景中的架构纯度,因为它预计是一次性操作(在这些情况下已成功使用)。

我还没有准备好使用CQR和事件源的生产应用程序,所以这里是我尝试构建一个应用程序的经验

1)
读取模型重建
。是的,一旦数据库中的某些内容发生变化,您基本上必须重建整个读取模型数据库。如果有很多活动,这可能需要很长时间。因此,必须高度优化读取模型重建(使用事件批处理等)。我觉得事件源最适合高读写比的情况。因此,对于一些极不稳定的数据,最好不要将其存储为域事件。但是,关于存储容量的问题也并不遥远。在任何情况下,您都可以将CQR应用于系统的一部分,即它最适合的部分(例如,我可能不会将图形图像存储为事件的一部分)

2)
调试

事件存储中出现错误的可能性很小(这应该是框架的问题),而且检查存储中的事件总是很容易的。至于生成预期事件的命令,您应该在这里进行测试,这些测试可能是系统中最有价值的测试。对于反规范化程序,您也可以进行测试,但如果肉眼可以看到它们的核心,我就不会为琐碎的反规范化程序编写测试了。也就是说,我使用调试器几次,在一些更复杂的反规范化程序中发现问题;试图确定哪些事件会导致事情出错并没有那么有趣。

将事件源与CQR结合使用的好处在于能够破坏读取模型并从头开始重建它,正如前面提到的那样。出于某种原因,人们有这样一种想法,那就是当你超越一些任意数量的事件之后,这将需要很长时间。如果您正在为读取模型使用关系数据库,那么很容易打开一个事务,通过处理程序读取所有事件,然后提交该事务。只有当事务提交时,我们才真正接触磁盘。其他一切都是在内存中执行的,所以它可以是闪电般的快。事实上,如果你的系统能在几分钟内完成几百万个事件,我也不会感到惊讶

从头开始重建读取模型的方式应该与将事件反规范化为读取模型的日常方法完全相同。如果没有,您的读取模型非规范化代码中就有一个bug。这里最棒的是,从消息处理程序的角度来看,在常规/生产场景和读取模型重建场景中,接收到的事件和非规范化到读取模型中的事件之间没有区别


如果确实遇到错误,您可以通过将生产事件流式传输/复制到本地工作站、在处理程序中设置断点,然后通过读取模型处理代码运行这些事件来轻松进行调试。

也可以在模型中添加净额结算事件。这可以在收到X个事件(比如500个)后作为任意任务运行

要重建,您将事件推到堆栈上,直到遇到净额结算事件,这将用作基线,从这里您将事件从堆栈中弹出,并将其值与基线事件聚合。