在第二部分的结尾,我们引入了(微)服务的概念,它拥有对一组数据的独占访问权,以便管理应用程序不变量。一旦我们开始以这种方式分解,我们就需要开始考虑微服务之间的数据流。
    更好的范例?
    到目前为止,我们一直在讨论如何将传统的ORM样式模式适应云本地应用程序,保留基于寄存器的数据视图。通过引入负责自己数据的微服务,我们发现现在我们需要考虑微服务之间的数据流。这很有趣,因为基于数据流的方法比基于对象/实体的方法在抽象级别上运行。将其与不变性(这会改变所有内容)结合起来,可以考虑将仅附加存储机制和事件作为存储和服务之间流动的通用单位。因此,我们有一个事件存储(作为更一般的数据存储的专门化),和一个事件流作为更一般的数据流的专门化。事件是处理命令(事务)的结果。这种思维方式导致了CQRS体系结构的出现。

    随着存储成本的不断降低和数据科学的兴起,事件存储非常适合我们,因为它让我们可以对数据提出许多可追溯的问题。我们真诚地为企业保留更多的价值,因为我们有很多选择。这里有一个类比:register模型有点像一个银行应用程序,它只需维护一个账户的余额——我们只需要问一个账户当前有多少钱;event store模型就像保留一个交易分类账——它允许我们对账户行为进行各种历史分析,以及能够得到当前的平衡。
    在通常的术语中,面向外部世界的服务可以接收命令(执行某些操作的请求)和查询。处理命令可能会生成零个或多个事件,这些事件告诉我们有关已发生事件的信息。一个示例命令可以是“add item X to shopping basket”,假设添加成功,我们可能会生成一个事件“xaddtoshoppingbasket”。如果我们想知道购物篮的当前状态,我们可以重播它的事件日志。
    我们需要ALPS属性,因此我们将有多个可以处理命令的副本。如果我们是通过处理一系列事件来创建状态的,那么我们实际上有一个状态机,其中的事件表示操作。除非我们非常小心,否则事件的顺序通常很重要。这是个难题!事实上,一致性算法是用来解决这个问题的,而且它们以难以理解和难以纠正而臭名昭著。以Viewstamped Replication重访问为例,其中的并行关系非常清楚。
    如果我们试图通过使事件顺序不重要来解决问题,我们就回到了交换性和单调性。在“收敛和交换复制数据类型的综合研究”中,用观察到的删除集CRDT对同一购物篮示例进行了建模。
    事件溯源可以是一种有用的技术,有助于在系统中保持灵活性和敏捷性,但在对一致性和应用程序不变量进行推理时,它不是银弹。
    关于CQRS的一个简短的词,它是一种可选的架构样式,通常与事件源相关。在CQRS中,系统的一部分(服务)处理命令,以及作为结果流而产生的事件,这些事件流到其他服务,这些服务维护为回答查询而优化的物化视图。在典型的实施例中,我们只为这些视图提供最终一致的保证。但我们希望它们是因果一致的——这个观点应该代表一个因果切割。为了实现这一点,我们需要跟踪事件的因果依赖关系,因为它们来自命令,而这些命令可能会受到已查看的信息的影响,因果循环必须从明确说明发出命令时的原因开始,并且元数据需要在整个系统中流动。我们可能也想尊重因果交易的原子性。CQRS可能是一种有用的技术,但如果我们试图将标准提高到尽可能高的一致性,这也不是什么好办法。

    但我们不能回避这个问题:
    对由各种服务组成的应用程序的一致性属性进行推理需要对组件的语义属性以及如何在与其他组件的组合中保留这些属性进行推理。因此,它需要一个同时捕获组件语义和交互组件之间依赖关系的模型。一种方法是将分布式系统视为异步数据流,其中输入流通过过滤、转换并将其组合成输出流的组件图。

    合流分析可以应用于数据流级别,并且再次依赖于应用程序级别的注释。Blazes论文探讨了其中的一些想法,以及在构建基于微服务的数据流时的一些有趣的提示。例如,将复制放在合流组件的上游,并将缓存放在下游(在这个模型中,我们可以将CQRS样式的物化视图视为缓存的一种形式)。
    事件模型有很多优点,在Blazes的引领下,我们可以将微服务分类为合流或有序的sensitive,以及只读或写路径。这有助于我们与ADM研究的那种“仅仅足够的协调”方法。
    假设我们在有界上下文中有一个微服务集群。命令和查询从上下文外部到达,事件在上下文内部流动。微服务通过数据流连接在一起。从另一个角度看,这看起来像是一个无限的流处理问题!这是一个有趣的见解,因为我们在早报的前一版中研究了支持无限流数据流处理的系统。例如,请参见Google Cloud Dataflow模型和Apache Flink。
    继续遵循这个逻辑,微服务最终看起来就像是处理数据流图中节点上事件的函数。这也让人想起了AWS Lambda的设计。
    如果我们能够动态更新数据流图,我们就拥有了一个非常有趣的敏捷平台。并不是所有的应用程序(或应用程序的一部分)都将以这种方式构建,但对于那些可能适合的情况,它是工具箱中一个强大的新工具。

    摘要
    我们面临着数据危机——应用程序面临数据损坏(违反完整性)和数据丢失,通常是无声的。如今流行的机制似乎无法阻止这种情况,如果我们继续使用它们,朝着云本机风格的应用程序发展,情况只会变得更糟。
    现在是时候把应用程序的考虑放在中心位置了,从应用程序不变量开始,应用程序和数据存储之间的协作提供了足够的协调,达到因果+一致的程度,并在这一点之外提供了道歉机制。应用程序数据存储映射器(ADM)可以将其放在底层最终一致的存储之上。
    当我们开始研究微服务时,我们需要将微服务之间的事件数据流放在首位。这样就可以进行数据流分析和优化,并将设计用于无限流处理的数据流平台用作连接微服务的结构。(你自己的选择可能被描述为“激进的数据流协调”)。不过,事件本身并不是一成不变的银弹。