领域事件、事件溯源、事件风暴建模

  事件代表过去发生的事件,事件既是技术架构概念,也是业务概念。以事件为驱动的编程模型称为事件驱动架构EDA,事件驱动与事件溯源EventSourcing是两种概念,EDA是技术架构概念,而事件溯源则是业务概念,兼具技术概念,“通过事件驱动”和”根据事件追溯跟踪源头“从词面意义上也是不同的。事件溯源将颠覆关系数据库!

  一个事件代表某个已经发生的事情,在计算机系统中,事件是由一个对象表达,其包含有关事件的数据,比如发生的时间,地点等等。这个事件对象可以存在在一个消息或数据库记录或其他组件的形式中,这样一个对象称为"一个事件"。事件本身是不可变的值对象。  

  事件在技术架构上应用能提供无堵塞的高并发性能,如Nginx和Node.js,而Vert.x. 比 Node.js快好几倍?其他还有Event Stream Processing如Esper等,结合DDD实现的CQRS等。

  事件概念业务系统中应用,诞生领域事件和EventSourcing等DDD实现方式:通过引入事件,类似服务概念一样,跨越业务和技术鸿沟,同时又能表达面向函数编程思维。在业务上将事件和领域驱动设计DDD结合在一起,可以形成统一语言DSL,事件是触发状态变化的根源。参考:荷兰还有媲美光刻机的软技术:组件建模和分析框架Comma为复杂软件提供了高可靠性 – Bits&Chips

  领域事件是领域中发生的事件。如CustomerRelocated, CargoShipped, or InventoryLossageRecorded. 领域事件将领域模型的改变显式化,突出暴露出来。如下图:

领域事件

 

事件日志

  几乎所有数据库都支持高可用性集群,大多数数据库对系统一致性模型提供一个易于理解的方式,保证强一致性模型的安全方式是维持数据库事务操作的有序日志,理论上理由非常简单,一个事件日志是一系列数据更新操作的动作有序记录集合,当其他节点从主节点获得这个事件日志时,能够按照这种有序动作集合重新播放这些操作,从而更新自己所在节点的数据库状态,当这个事件日志完成后,次节点的状态最终会和主节点状态一致,

  这种事件日志非常类似于财务中记账模型,或者类似银行储蓄卡打印出来的流水账,哪天存入一笔钞票(更新操作),哪天又提取了一笔钞票(更新操作),最后当前余额是多少(代表数据库当前状态)。

  

 

事件溯源Event Sourcing

  Event sourcing事件溯源是借鉴数据库事件日志的一种数据持久方式,在事件日志中记录导致状态变化的一系列领域事件。通过持久化记录改变状态的事件,通过重新播放获得状态改变的历史。 事件回放可以返回系统到任何状态。

  在ES中,事务单元变得更细粒度,使用一系列有序的事件来代表存储在数据库中的领域模型状态,一旦一个事件被加入事件日志,它就不能被移走或重新排序,事件被认为是不可变的,事件序列只能被追加方式存储。

 

  由于事件流本身具有逻辑上严格次序性,因此使用统一的事件流(事件日志)能够很自然实现事务机制,无需额外ACID机制或2PC之类同步强硬方式。

 

函数式编程

  在微服务等无状态应用架构中,我们不是需要状态时就发出命令从数据库中查询获得,这样,可变的状态会遍布整个应用代码中,带来很多副作用,而我们将这些状态操作统一为事件流声明式订阅,订阅了某个事件流,通过重播事件流中各个事件一直到最新最后的事件,也就获得了最终的状态。函数式编程Stream风格为这种播放提供了方便,具体Reactive框架有RxJS、React.js、RxJava、Reactor等等。

Spring Cloud Stream实战

  这种实现其实已经在Reactive前端中有着同样实现思路,见:为什么要使用GraphQL和Falcor?,应用程序(微服务)将可变的状态被限定在一个单个的序列化对象中,从而整个应用就变成了无态,可变状态不会扩散到整个应用代码的各个本地变量中。

 

事件模型

  我们甚至可以使用领域事件直接对业务需求进行事件建模,通过事件功能的发现挖掘需求中深层次的概念。动态流的事件模型加上结合DDD的聚合实体 状态 和上下文场景Bounded context,我们实际上统一了需求分析和软件设计两个阶段的语言,使用这套统一语言分析需求以后,能够直接落地为代码,如下图是总结了在Jdon多位牛人的思想后的Jdon分析法:

event

  该图表达了用户操作者和被操作者事物之间的本质关系,以用户和购物车为案例,从购物车这个事物角度看:领域聚合实体表达的是购物车这个事物的分析设计方法,以一种静态结构性来表达事物;从用户购买者这个角度看:用户将选购的商品放入购物车,删除购物车已有商品,这些都是用户的操作行为,每一个操作行为相当于发出一个个命令command,在一定场景中转化为事件,事件会改变购物车状态,这是一种以动态行为(面向函数)来表达与人有关的需求。

   事件建模原理,找出意图 执行和结果范式:

  对应意图 执行和结果范式的事件风暴图:

   更多事件风暴#EventStorming

 

区块链

   通过引入事件概念,可以实现多线程并发到分布式去中心化计算的平滑过渡,区块链本质上就是一种事件链。 通常区块链是指一种分布式账簿,账本其实是记账明细,记录着每笔进出明细,这些发生的每笔明细其实代表系统发生的事件,因此,记账明细其实就是事件日志,区块链其实就是一种分布式事件链,只不过另外增加了一层安全层。

  事件溯源的适用场景是和区块链的应用场景类似的,因为两者本质上是一致的,可以说区块链就是一种事件溯源,传统的集中式的事件溯源是将事件日志集中保存到事件库或Apache Kafka之类流处理框架,而区块链则是将事件日志分别保存在各个聚合所在的点,如何向这个大而全的事件日志写入新事件?传统分布式系统通过PaxosRaft选举主节点单独向事件日志写入事件,而区块链通过工作证明算法选举,CRDT通过事件数据本身携带的向量时钟合并,可谓各有巧妙。

   从CRUD编程切换到事件溯源和区块链编程

 

工作流

   事件是BPMN流程建模元素,表示在流程过程中“发生”的事情,事件会影响流程的走向,事件主要分开始事件、中间事件和结束事件,所谓中间事件就是位于开始和结束之间的事件类型。什么是BPMN事件?

   DDD、领域事件和BPMN流程和Saga可以有机结合在一起,详见Jdon框架

 

相关文章

基于领域事件的本站原创:《复杂软件设计之道:领域驱动设计全面解析与实战》(专门章节讨论CQRS/ES/分布式事务)

最全面DDD微服务教程:SpringBoot + DDD + Apache Kafka实现最终一致性的教程与源码 - itnext

荷兰还有媲美光刻机的软技术:组件建模和分析框架Comma为复杂软件提供了高可靠性 – Bits&Chips

事件模型-下一个前沿

Jdon分析法

Java的CQRS和事件溯源ES入门:如何从CRUD切换到CQRS/ES

DDD CQRS和Event Sourcing的案例:足球比赛

通过实体快照实现事件建模

为什么使用Event Sourcing?

使用Spring Cloud和Reactor在微服务中实现EventSourcing

如何理解Stream processing, Event sourcing, Reactive, CEP?

业务流程的新实现:微服务和事件编排

通过事件风暴和DDD建立微服务时优先考虑事件

两个领域事件驱动的开源项目介绍

事件是一等公民

最全面的CQRS和事件溯源介绍

经验分享:采用事件溯源的误区(以及我们是如何避免的)

分布式事务的替换者:在线事件处理OLEP(事件溯源)

金融领域微服务架构中如何实现分布式事务?如何记录更多事件,存储在哪里?事件顺序如何保证? - Revolut

Apache Kafka和Spring Boot的容错和可靠消息传递

hediet/vscode-drawio:此插件能将Draw.io集成到VS Code中,产品经理能更无缝衔接软件开发

更多#领域事件专题

相关话题

#EventStorming   #Event Sourcing #CQRS

#工作流专题 #Saga流程管理器 #分布式事务

#业务与系统分析 #DDD

猜你喜欢