我正在尝试使用Postgres实现一个事件采购系统。 解释的最佳方式是通过示例。 所以我们假设我的事件最终需要描述一个人。 我有以下事件:
事件1只会在一个人的一生中发生一次 事件2 - 3可以多次发生 事件4 - 5可以多次发生。
在一天结束时,我最终会得到一张主要与事件4和5一致的表格。
因此,如果我的桌子上有1000万人,我可能会有数十亿的事件,而其中99%基本上是4和5.这将导致庞大的数据存储,不确定Postgres会很好地使用它(它可以..但是有大量工作\基础设施增加。)
这只是一个例子,我的实体可能由100个字段组合,这意味着每个实体至少有100个事件。一些领域具有事件4和5的特征。
在我的案例中使用事件来源的附加值是我在我的实体上固有的历史记录,这在我的情况下是产品要求。
在这种情况下,最佳做法是什么? 也许更频繁的属性应该在其他地方处理?
更新: 另一个例子是查看设备聚合。
同样在这里 1.事件1可以解雇一次 2.事件2可以多次heppen 3.事件3可能每天都会出现问题 4.事件4可能每天都会咳几次 5.事件5可能每分钟都会麻醉
如果我通过postgress实现这个,我最终会得到一个巨大的表,主要包含事件4和5。
答案 0 :(得分:3)
对我来说,似乎你有一个(粒度)CRUD系统而且你不需要Event sourcing。这不错,您只需要通过重新应用历史记录中的所有事件来重建状态,以便验证命令。在您的情况下,可能当前状态就足够了。
如果您喜欢事件的想法(更像是需要),那么您可以使用Event log。这就像事件采购,但您以最终一致的方式使用事件,并且仅用于读取方。
在任何情况下,为了按行为拆分实体,您可以使用DDD。也许你可以有两个共享相同ID的聚合:PersonDetails
和PersonAccountBalance
?为什么?因为当你更新余额时检查他的余额应该是正数时你不需要这个人的姓名(或地点)(关于那个,你{{1}很奇怪而不是update his balance
或makeADeposit
,但这取决于您的域名。
答案 1 :(得分:2)
我的实体可能合并了100个字段,这意味着每个实体至少有100个事件
可能表示您的事件以错误的粒度为您的实体建模。一件事"发生在影响100个属性的域中通常应该在历史记录中显示为具有大量数据的一个事件,而不是每个具有一个数据的许多事件。
这并不是说你最终无法获得潜在的大量事件,特别是如果你有很多实体的话。
这有两个常见的答案。一个借鉴domain-driven-design;我们从聚合方面考虑域 - 可以相互隔离的状态集合。因为实体可以是隔离的,所以如果它们位于相同的耐用存储区中,或者商店是分片的,则无关紧要。所以你可以发布活动。
另一种可能性 - 在许多领域,存在自然的时间节奏;在会计年度结束时,您汇总当前状态,使用该状态标记新流的开头,并退出旧流。
还有垃圾收集的可能性 - 在正确的数据结构到位的情况下,您可以通过历史记录查看后台进程,替换低值事件。
最主要的是摆脱粗暴采购的概念。
更广泛地说,您还需要考虑业务是否通过跟踪实体的整个历史来获得价值。对于成本/收益分析告诉您将信息存储在文档快照中的实体,您不应该使用事件历史记录。
答案 2 :(得分:2)
对我而言,在同一聚合根目录中使用AgeUpdated和BalanceUpdated事件看起来很奇怪。有 Something 的事件在其名称中更新了,告诉我它是CRUD用例,或者您需要在集合设计上更多地工作。
是否有另一组交易可以有趣而不是人物?为了解决这个问题,你应该考虑应该保留哪些不变量。也就是说,在哪种情况下交易失败,什么应该永远是真的? (如果你没有,请阅读域驱动设计聚合
)例如,如果您为帐户进行某种交易,则业务规则可能是该帐户不能透支超过100美元。在这种情况下,您可以使用帐户作为聚合根,而不是拥有帐户的人。
要获得一个人的完全余额,您需要一个读取模型来聚合用户的所有内容。
但一切都取决于你的用例。
祝你好运!