CQRS 和事件溯源系统的持续演进

  • Jan Stenberg
  • 盖磊

2018 年 2 月 10 日

话题:语言 & 开发架构

看新闻很累?看技术新闻更累?试试下载 InfoQ 手机客户端,每天上下班路上听新闻,有趣还有料!

在向听众介绍了如何升级CQRS事件溯源(event sourcing)系统后,Michiel Overeem提出了一个论点:不少与事件溯源系统打交道的人,对其中的挑战缺乏认知和理解,并不知道如何解决问题。近期在阿姆斯特丹召开的DDD 2018 欧洲大会上,Overeem 做演讲介绍了这一论点是如何促使他去开展一些探索性研究,实现此类系统的持续演进

Overeem 现任AFAS首席软件架构师。AFAS 是一家已有 20 年ERP系统开发历史的软件企业。Overeem 着手调研如何升级基于 CRQS 的系统的出发点,正是由于该企业正在对它们现有的系统做完全重建。新系统将基于 CQRS 和事件溯源。更重要的是,他们已决定使用一个模型涵盖所有的知识,并由模型生成 ERP 系统。企业已经看到该做法的一个优点,就是实现了业务逻辑和技术的分离。而其中挑战之一在于系统经一段时间运行并生成了大量事件后,如何处理模型的更改和升级。

为深入了解其他团队是如何处理 CQRS 和事件溯源系统升级,Overeen 和他的团队做了 24 次探访,所访问团队来自于多个不同的商业领域,涉及的事件量从五万到上百万不等。在探访期间,他们聚焦于事件模式的演讲,并从中发现了五个需考虑的方面,分别是抵制、技术、裁决、隐私和读取模型。

为了能让听众形成一个基本的认识,Overeem 强调指出,在事件溯源系统中总是存在着一些隐含的模式,模式的知识是嵌入在系统中的。但是与关系数据库不同,事件的存储并不强制使用给定的模式,对所有进入的数据来者不拒。

在抵制方面,要抵制(或着说最小化)对更改的需求,一种方法是采用 DDD。鉴于事件模拟了领域中的真实事件,而领域是不会做频繁更改的,因此更改的需求也会很少。另一种方法来自一家企业的做法。它成立了一个委员会,负责审查所有事件的变化及其影响情况。委员会有时会建议采用其它一些影响较小的更改。

在技术方面,人们最常提到的技术,就是永不更改事件或事件的模式,因为每次更改都会引入新的事件。尽管这种技术众所周知,但是 Overeem 发现很少有人实际使用它。技术本身十分简单,但风险是会使领域变得更加脆弱。虽然特定于领域的更改通常运行良好,但是如果引入事件的版本,就可能会对领域造成破坏。

弱模式是一种常用的技术。如果我们在反序列化为对象中使用了弱模式,那么我们只需关心当前正在使用的特性或属性。只要数据是可用的,或着存在默认值,即可满足模式。

另一种技术是更新,该技术类似于关系数据库中的更新操作。如果使用更新技术,那么就引入了一种同样带有模式信息的新工具,并将在带外(out of band)更新事件存储。在 Overeem 看来,这种技术很可怕。一旦犯了错误,对事件存储的影响就是毁灭性的。应考虑使用不具破坏性的重写技术。例如,我们可以根据一些数据存储新技术,将事件由 XML 重写为 JSON。

最常使用的技术是“复制 - 转换”。该技术从一个事件存储中读取,并写入到一个新的事件存储中,同时将事件转换为新模式。一个略有不同的方法,是从旧的事件流中创建新的事件流,并在同一存储中保存新的事件流。另一种使用微服务的方法,使用新的事件模式创建新的微服务,然后从旧的微服务中复制所有的事件。

在隐私方面,隐私正变得越来越重要。因此还应考虑一些数据保护规定,例如欧盟制定的通用数据保护条例(GDPR)。Overeem 给出了三种清除个人资料的策略:

  • 使用转换技术,将数据从事件存储中删除。
  • 使用分离事件方式。将主要事件与带有个人数据的事件分开存储,进而可以清除个人数据。
  • 使用不同的密钥,对每个人的事件加密。此后可以删除个人事件的密钥,从而防止对这些事件的读取。

在读取模型方面,一种明确的策略就是重建模型。该策略的缺点是可能需要很长的时间。Overeem 指出,解决该问题的关键在于并行运行各个映射器(projector)。另一种做法是跳过旧事件,或是过滤掉其它一些特性上的事件。Overeem 建议,在可能的情况下应维持原始存储的在用状态,并在另一个存储上运行映射器,直至新的存储准备就绪。

Overeem 最后总结指出,有很多种技术可用于 CQRS 和事件溯源系统的演进。在他们采访的团队中,通常都使用了多种技术。他强调,我们必须知道自己在做什么,并理解自身所处的具体场景。有不少简单的解决方案并未考虑具体场景。

Greg Young正在撰写一本介绍事件溯源系统中的版本控制的书,目前已完成了 70%。

DDD 2019 欧洲大会已经列上日程,但具体召开时间尚未发布。

查看英文原文: Evolving CQRS and Event Sourced Systems

语言 & 开发架构