实践DDD的一种思路

在实践DDD的道路上,我们一开始容易被各种概念带偏,写出各种样板式代码。首先定义聚合 实体 值对象,对聚合操作要有Repository,当聚合比较复杂时还要有Factory,后面又冒出来一个领域服务的概念,这个是大家最容易迷惑的,领域服务领域内的服务,不是对领域能力包装成的一个服务,领域服务是实在不知道放到哪个聚合下才妥协的产物,领域服务能不用最好就不用,因为它本来是不该存在的。在实践过程中增加的读写放大,多次操作数据库怎么优化,没有给出解法。

综上:我觉得这也是大家实践起来一个很大的门槛

CQRS的迷思

近些年,对我影响最大的一个概念就是CQRS,在各种业务场景的设计中,或多或少都会有类似的设计

EventSourcing

事件溯源,比较难落地的一个概念,短平快的互联网应用,要记录每次操作的事件,无疑是一种负担

最终一致性

当我们采取了传统DDD的架构思路,为了写出符合DDD的代码,在复杂技术的实现上还要考虑到会不会兼容这种写法,为了实现聚合间的最终一致,我们的分布式事务如何做

enode提供了一个思路解决上述问题

整体架构

这个是enode的架构图 image.png

使用约束

  • 一个命令一次只修改一个聚合根
  • 聚合间只能通过领域消息交互
  • 聚合内强一致性
  • 聚合间最终一致性

核心思路

通过一次只修改一个聚合根 首先做这个限制是从业务研发的角度来考虑的,这会让命令的职责更加具体,便于问题的拆解,职责的划分,如果一个命令要修改多个聚合根,应该通过Saga(Process Manage)来完成

加上这个约定后带来的收益:

  • 同一个聚合根的命令操作都会路由到同一个分区,聚合根就可以常驻内存(In-Memory),这样就不必每次重建聚合根,缓存利用率聚合是100%,是一种大限度利用内存的设计、
  • 命令路由到同一个分区,命令的操作顺序就可以保障(携带聚合根的版本),这就保障了聚合根在同一时刻只有一个在操作,直接避免你了并发问题,因为在设计上是无锁的
  • 关于命令操作顺序的保障,为了提升吞吐,要求队列是无序消费,但队列无序了怎么保证操作是有序的呢,这点就有点类似Flink中的watermarker的设计了,聚合根的mailbox会记录每个消息的版本,如果高版本的数据先到,数据就会暂存,等到中间的版本处理完成才处理,通过mailbox中的顺序保证了操作的有序

基建依赖

  • 依赖了分布式消息队列
  • 存储需要多建立两张表

编程模型

事件驱动的迷思

什么时候采取事件驱动,什么时候使用过程式编程

扫描二维码关注公众号,回复: 13620095 查看本文章

命令和事件的区别,两者都是消息,为什么要分开表示呢?

命令可以被拒绝。

事件已经发生。

这可能是最重要的原因。在事件驱动的体系结构中,毫无疑问,引发的事件代表了已发生的事情。

现在,因为命令是我们想要发生的事情,并且事件已经发生了,所以当我们命名这些事情时,我们应该使用不同的动词。这会驱动单独的表示。

我可以看到,命令通常由系统外调用,事件是由处理程序和系统中的其他代码提供的。

这是他们分开表示的另一个原因。概念清晰度。

命令和事件都是消息。但它们实际上是独立的概念,应该明确地对概念进行建模。

这两者我理解都是符合人类思维的,首先是基于大脑接收到感知到的消息(Event)产生一个想法(Command),然后如何实现这个想法,思考的维度是过程式的,在实现的过程中,会产生一些事件消息,这个消息又会影响到其他的大脑。如此往复循环

猜你喜欢

转载自juejin.im/post/7042508477247258661