共计 1687 个字符,预计需要花费 5 分钟才能阅读完成。
事件溯源
事件溯源是构建业务逻辑和长久化聚合的另一种抉择。
通过聚合一系列事件的形式长久化保留。每个事件代表聚合的一次状态变动。应用程序通过重放来从新创立聚合的以后状态。
模式:事件溯源
应用一系列示意状态更改的畛域事件来长久化聚合。
1. 传统长久化技术的问题
- 对象和关系的“阻抗失调”
关系型数据的表格构造模式,与畛域模型及其简单关系的图状构造之间,存在基本概念不匹配的问题。 - 不足聚合的历史
传统长久化的另一个限度是,它只存储聚合的以后状态。聚合更新后,其先前的状态将会失落。
如果应用程序必须保留聚合的历史,那么必须实现相应的业务逻辑。实现这个逻辑是十分耗时的一项工作,因为其中还有波及到复制必须与业务逻辑保持一致的代码。 - 实现审计性能十分繁琐且容易出错
为了满足安全性或监管的要求,要实现审计性能以反对。
挑战在于,除了这个是一个耗时的工作之外,负责审计日志的业务代码,可能与业务逻辑产生偏离,导致各种谬误。 - 事件公布凌驾于业务逻辑之上
传统长久化的另一个限度是,它通常不反对公布畛域事件。
2. 什么是事件溯源
事件溯源是一种以事件为核心的技术,用于实现业务逻辑和聚合的长久化。
事件溯源通过事件来长久化聚合
通过设置事件存储库(event 表),构造如下:
evenv_id | event_type | entity_type | entity_id | event_data |
---|---|---|---|---|
101 | OrderCreated | Order | 101 | {…} |
102 | OrderApproved | Order | 101 | {…} |
103 | OrderShipped | Order | 101 | {…} |
104 | OrderDelivered | Order | 101 | {…} |
… | … | … | … | … |
记录了 Order 变动的事件及所需的数据,通过加载事件存储库,可重放事件加载聚合。
- 一般来说,依照以下步骤:
- 加载聚合事件列表
- 应用默认构造方法创立聚合实例
- 调用聚合事件绝对应的 apply 办法,重放事件
- 事件溯源罕用实现如下:
- 应用 process 办法接受命令,返回事件列表
- 应用 apply 办法,承受事件,更新聚合
2.1 通过事件来长久化聚合
2.2 事件代表状态的扭转
2.3 聚合办法都与事件相干
2.3.1 创立聚合的步骤如下:
- 应用聚合默认的构造函数实例化聚合根
- 调用 process 办法,生成事件列表 1
- 遍历事件列表 1,并调用 apply 办法更新聚合的状态
- 将事件列表保留至事件存储库
2.3.2 更新聚合的步骤如下:
- 从事件存储库加载事件列表 1
- 应用其默认构造函数实例化聚合根
- 遍历加载的事件列表 1,并在聚合根上调用 apply 办法
- 调用 process 办法以生成事件列表 2
- 遍历事件列表 2,并调用 apply 办法更新来聚合的状态
- 将新事件存储至事件存储库
2.4 并发更新
两个或多个申请同时更新同一聚合。
对于并发,防止问题呈现的形式是,进行串行化的解决。
-
对事件存储库新增一列,is_publish
event_id is_publish 101 0 - 将事件存储至事件存储库(即时),is_publish 为 0
- 投递事件至音讯代理
- 将事件标记为已公布,is_publish=1
事件执行反馈记录,这里不聊
2.5 畛域事件的演变
事件溯源的构造分为三个档次:
- 由一个或多个聚合组成
- 定义每个聚合收回的事件
- 定义事件的构造
2.6 事件溯源的优劣
2.6.1 事件溯源的益处
牢靠的公布畛域事件
保留聚合的历史
最大水平的防止对象和关系的“阻抗失调”
为开发者提供一个时光机
2.6.2 事件溯源的弊病
编程模式有肯定的学习曲线
基于消息传递的应用程序的复杂性
处理事件的演变有肯定的难度
随着工夫的推移,畛域模型及构造都可能会有调整。
- 迁徙旧构造,以反对以后最新的畛域模型
- 代码中减少适配器,以兼容旧构造
删除数据有肯定的难度 - 事件溯源自身是要保留聚合的历史,永恒的保留数据,所以传统的做法是进行软删除
- 应用软删除应用多种数据,然而依据欧洲的数据保护和隐衷法规(GDPR), 应用程序必须彻底删除用户的个人信息。
做法是,通过用户设置 UUID,依据 UUID 关联敏感数据。删除数据时,删除关联即可。 - 查问事件存储库十分有挑战性
须要在事件存储库,找到没有间接搜寻条件的数据。
通过 CQRS 可实现该查问
2.7 通过快照来进步溯源的性能
正文完