Skip to the content.

事件溯源模式

使用一个仅追加的存储来记录一系列完整的事件,这些事件描述了在领域中数据的行为,而不是仅仅存储当前状态,以便于用存储来实现领域对象。这个模式能简化任务,在复杂的领域通过避免同步数据模型和业务模型的要求;提高性能,伸缩性以及响应能力;提供事务数据一致性; 维护完整的审计跟踪和历史记录,以支持补偿措施。

问题上下文

大多数应用程序都会使用数据,典型的方法就是用户使用数据时,通过维护数据的当前状态来更新它。举个例子,

在传统的创建,读取,更新以及删除(CRUD)模型,一个数据将会从存储中读取出来处理,然后做一些修改,并且更新这个数据的状态 —— 这种操作经常用事务锁住数据。

CRUD 方法有一些限制:

解决方案

事件溯源模式定义了一个方法通过一系列的事件来处理数据操作,每个事件记录都是追加存储的。应用程序代码发送一些事件,这些事件描述了数据上发生的每个操作并持久化。每个事件都代表一组数据的改变(例如 AddedItemToOrder)。

事件作为源的原始记录存储在存储区,或关于系统数据当前状态的记录(给定一段数据元素或信息的数据源来验证)。事件存储区会指定发布这些事件,以便按需通知消费者处理它们。消费者可以这么做,例如初始化一个任务,在事件中提供一个操作到其他系统,或执行所有相关的动作并完成它。注意,应用程序代码生成事件要从事件订阅系统解耦。

事件发布的典型用法在应用程序中是通过事件存储区来维护一个实体的物化视图来改变它的行为,并且集成到内部系统中。例如,一个系统可能会维护一个所有客户订单的物化视图,作为 UI 的一部分填充。当应用程序添加新的订单时,在订单上添加或删除一项,以及添加新的运输信息,这个事件就会描述这些变化并更改这个物化视图。

关于物化视图模式请移步 Materialized View pattern

另外,在任何时候应用程序都能读取事件事件历史并使用它来物化实体的当前状态,通过有效的 “重播” 和恢复所有的相关联的事件到实体。这可能发生在物化一个领域对像,当处理一个请求或通过任务调度时候,以便于实体状态能够作为物化视图来支持显示层,这可能会根据需求发生。

图 1 显示了这个模式大概逻辑,包括一些可选事件流,如创建新的物化视图,集成事件到应用程序和系统,并且指定实体状态下重播事件来创建项目。

​ 图 1 - 事件溯源模式概述和例子

事件溯源模式提供很多优势,包括以下几点:

事件源一般跟 CQRS 模式结合,在响应事件中,执行数据管理任务,并且从事件存储区中物化视图。

问题及思考

当决定实现这个模式的时候要考虑以下几点:

何时使用这个模式

这个模式适合于以下场景:

事件溯源模式不适合以下场景:

例子

会议管理系统需要跟踪会议已完成预定的数量,以便于检查是否还有座位能够继续预定。系统至少有两种方式来存储会议预定:

图 2 显示了如何使用事件溯源实现会议管理系统的座位预定子系统。

​ 图 2 - 使用事件源来捕捉会议管理系统中关于预定座位的信息

预定两个座位的行为依次如下:

  1. 用户接口发起命令预定两个座位。这个命令是由单独的命令程序处理的(这段逻辑解耦了用户接口和响应这个命令请求处理程序)。

  2. 聚合包含关于所有预定相关的信息,查询事件描述了预定和取消。这个聚合被称为 SeatAvailability,并且还包含了领域模型,它开放查询和修改数据的方法。

    考虑使用快照优化(你可以无需查询和重播所有的事件来获取聚合的当前状态),以及维护一个缓存,它拷贝了聚合的副本在内存中。

  3. 命令处理程序调用了领域模型开放的这个方法来预定。

  4. SeatAvailability 聚合记录了事件,事件包含了已经预定的座位数。下次聚合会应用这个事件,所有的预定事件都将被用来计算到底还有多少个座位。

  5. 系统追加新的事件到事件存储区中

如果用户希望取消座位,系统会按照上面相似的预期的命令处理命令处理程序,它会生成一个取消事件并追加到事件存储区中。

只要为灵活性提供更多的空间,使用事件存储区也能为关于会议的预定和取消提供完成历史记录,或审计追踪。在事件存储区中的事件记录了源的真相。这里不需要以其他方式持久化聚合,因为系统能很容易的从重播事件以及在那个时间点还原状态。

原文

https://docs.microsoft.com/en-us/previous-versions/msp-n-p/dn589792(v=pandp.10)?redirectedfrom=MSDN