Event-Souring模式

Event-Sourcing模式使用仅附加存储来记录或描写叙述域中数据所採取的动作,从而记录完整的一系列系列事件,而不是仅存储实体的当前状态。由于存储包括全部的事件,能够用来具体化域对象。

Event-Sourcing模式能够简化复杂的域中的任务,避免了数据模型和业务领域的同步和引发的争用问题;增强性能,扩展性,以及响应;为事物数据提供一致性。保留全部的事件运行历史,能够跟踪和实现回滚之类的补偿操作。

问题

大多数的应用都会涉及到数据的处理,而通常的方法是由应用来保证数据的状态,当用户请求数据的时候。就会更新数据的状态。举个样例。在传统的CRUD模型中,典型的数据处理过程是,从数据仓库读取数据。做出一些改动。使用新的数据更新(通常通过事务来保护数据)当前数据的状态。CRUD的方式会有例如以下的一些限制:

  • 其实,CRUD系统直接针对数据存储运行更新操作,可能会受到数据仓库的处理开销而影响系统的性能和响应时间,和限制的可扩展性。
  • 在很多并发用户的协作域中,数据更新有非常大的可能发生冲突,由于更新操作都是发生在单个数据项上。
  • 除非有一个额外的检查跟踪机制,它记录在一个单独的日志中的每一个操作的具体信息。否则,数据项的操作历史会丢失。

想要更深入的了解CRUD架构的一些限制,能够參考微软的CRUD, Only When You Can Afford It一文。

解决方式

Event-Sourcing模式定义了一种处理由一系列事件来驱动的数据操作的方法。每一事件都记录在一个仅能追加的存储中。应用将生成一系列事件来描写叙述每一个动作,每一个事件相应存储数据发生的变更,然后将这些事件持久化。每一个事件都表示一组数据的变化(比方在订单中添加数据项)。

事件能够持久化到事件存储仓库中。事件存储仓库作为对当前数据的状态的数据源或记录系统(数据源或信息的权威数据源)。事件存储一般会公布这些事件,以便能够通知消费者,并在消费者有须要的时候处理它们。比如。消费者能够初始化一些任务将事件中的操作应用于其它系统来运行,或运行完毕该操作所需的不论什么其它相关操作。

注意,生成事件的应用程序代码与订阅事件的系统是解耦的。

通常来说,事件存储所公布的事件是用来在应用程序对实体进行改动的时候,更新实体的Materialized视图,并与外部系统集成。比如,系统能够维护全部客户订单的Materialized视图。这些订单信息用于填充UI的部分。当应用程序加入新的订单,加入或删除项目的顺序,并加入航运信息,消费者将处理描写叙述这些变化的事件,并更Materialized视图。

參考Materialized-View模式来了解很多其它的具体信息。

此外,事件存储能够让应用在不论什么时候读取事件的历史,并通过对事件历史进行有效地“回放”和消耗有关该实体的全部事件来计算实体的当前状态。非常多时候,可能会由于client请求,或通过一个预定的定时任务,来又一次计算实体的当前状态。

当中。定时任务能够将计算的状态生成Materialized视图。并存储起来来提高查询效率。

图1展示了Event-Sourcing模式逻辑的概览图。当中也包括了使用事件流来创建一个Materialized视图,并与其它外部应用和系统集成,以及通过反复事件流来展示某些实体的当前状态。

图1. 关于Event-Sourcing模式的样例和概览

Event-Sourcing模式有非常多的长处,包括:

  • 事件都是不可变对象,而且存储在一个仅支持追加的队列中。不论什么用户界面。workflow。或者程序触发了产生事件的行动,都能够以非堵塞任务继续运行,而且这些任务能够都在后台持续运行。

    这一点,能够令结合事务运行过程中不会产生不论什么争用,能够极大地提高应用程序的性能和可扩展性,特别是对于用户界面的展示。

  • 事件是描写叙述事件发生的简单对象,以及描写叙述事件所代表的动作所需的相关数据。事件不会直接更新数据存储区,它们仅仅是在适当的时候进行记录的生产者。这些方面都能够简化系统的实现和管理。
  • 事件通常在某些领域都有各自的特殊含义,相对而言,对象可能仅仅是和数据库的表相相应的,是无法表示其在领域中的真实意义的。表仅仅能表示系统的当前状态,而表现不了发生的事件。
  • Event-Sourcing能够有效降低并发更新所引起的冲突,由于Event-Sourcing避免了直接更新数据存储区中对象状态的要求。

    当然,域模型仍然须要设计来保护其自身的一致性。

  • 仅追加的时间存储能够提供Trace的线索,用来监測对数据存储区所採取的行动,并在不论什么时间计算当前实体状态的Materialized视图或运行事件的回放,协助測试和系统调试。

    此外。使用补偿事件取消更改的要求提供了一个逆转状态的历史记录,假设模型仅仅存储当前状态,补偿回滚是无法实现的。事件列表也可用于分析应用程序性能和检測用户的行为趋势。以获得其它实用的业务信息。

  • Event-Sourcing的事件存储解耦了其生产者(产生事件的任务)和消费者(生成Materialized视图的任务等)。为系统的提供了更好灵活性和可扩展性。比如。处理事件存储所公布的事件仅仅知道事件的性质和包括的数据。运行任务的方式与触发事件的操作是解耦的。此外。能够使用多个任务能够处理事件。这一特点使得事件仓库能够非常easy的配合其它服务和系统进行集成,仅仅须要侦听由事件存储引发的新事件就可以。然而,Event-Sourcing往往是非常低的level,假设有必要的话。能够对基础事件进行简单的聚合再来配合其它系统进行集成。

Event-Sourcing通常都是配合CQRS模式来运行数据管理任务的。

实现Event-Sourcing模式的问题和顾虑

当在考虑实现Event-Sourcing模式的时候,须要考虑例如以下一些问题:

  • 整个系统在创建Materialized视图或通过回放事件数据生成预測的时候都是不一致的,仅仅能满足终于一致性的。应用程序将事件加入到事件存储区的过程与处理请求的结果、正在公布的事件以及处理它们的事件的消费者之间存在一些延迟。

    在此期间,描写叙述实体的新的更新的新事件可能才到达事件存储区。

    能够參考Data Consistency Primer来了解终于一致性方面的信息

  • 事件存储是不可变的信息源,因此事件数据不应该被更新的。更新实体以撤消更改的唯一方法是向事件存储加入补偿事件。就像在交易系统中使用负事务一样。假设持久化事件的格式(而不是数据)须要更改,比方在迁移过程中。将存储中的现有事件与新版本号事件相结合非常难。可能须要遍历全部事件的变化使事件符合新的格式。考虑在事件结构中定义版本号,并对每一个版本号上使用版本号标记,以维护新旧事件的不同格式。
  • 多线程应用程序和多个应用程序实例都可能在事件存储区中存储事件。事件存储中事件的一致性是至关重要的。由于这将影响特定实体的事件顺序(实体发生变化的顺序影响其当前状态)。

    在每一个事件中都加入一个时间戳,能够帮助避免问题。

    还有一个常见的做法是每一个产生的事件都标记一个增量标识符。假设两个操作试图同一时候为同一实体加入事件时。则事件存储能够拒绝与现有实体标识符和事件标识符相匹配的事件。

  • 在遍历事件来获取信息这方面,是没有标准的方法或者一些诸如SQL查询的內建机制的。数据的提取仅仅能通过标识符,获取事件流的方式来。事件ID通常映射到单个实体。一个实体的当前状态。仅仅能通过回放全部涉及对该单位的原始状态的事件来计算出来。
  • 事件流的长度也会影响管理和更新系统。假设事件流非常大,计算负载高。能够考虑每隔一定的时间间隔创建快照,比如指定的事件数。

    这样,实体的当前状态能够从快照和重放那个时间点之后发生的不论什么事件中获得。

想了解针对数据建立快照方面很多其它的信息。能够參考Martin Fowler的Enterprise Application Architecture website以及Master-Subordinate Snapshot Replication on MSDN.

  • 即使事件获取将数据冲突更新的可能性降到最低,应用程序仍然必须能够处理可能通过终于一致性和事务缺乏而出现的不一致。比如,表示库存降低的事件可能到达数据存储区,而该项目的还在进行下单,从而导致协调两个操作的出现冲突,就须要应用能够处理这样的相似的冲突。可能须要通知客户撤单或创建回订单。
  • 事件公布可能发生多次,所以事件的消费操作必须是幂等的。

    事件的消费者必须能够处理反复的通知操作。比如,假设一个实体的某一个属性由多个应用实例维护,比方订单总数,那么,当下订单的时候。必须仅仅有一个成功添加订单总数的事件的发生。尽管这不是Event-Sourcing的固有特性,可是通常来说。实现Event-Sourcing都要考虑这一点。

何时使用Event-Sourcing模式

Event-Sourcing模式非常适合下面场景:

  • 当开发人员希望捕获数据中的“意图”、“目的”或“原因”时。非常适合使用Event-Sourcing。

    比如,对客户实体的更改能够记录为一系列特定的事件,如搬家、关闭账户等。

  • 当尽量降低更新数据的发生争用的时候。使用Event-Sourcing是非常合适的。
  • 当开发人员希望记录发生的事件,并能够重放它们以恢复系统的状态;使用事件来回滚系统变更;或简单地将事件作为历史和审计日志等情况下,均适合使用Event-Sourcing模式。

    比如,当任务涉及多个步骤时。您可能须要运行回滚某个更新的操作,然后又一次运行一些步骤,使数据又一次恢复到一致状态。

  • 当使用事件是应用程序运行的一个自然特性,而且不须要太多的额外开发或实现工作的时候,使用Event-Sourcing模式非常合适。

  • 当开发人员须要将输入或更新数据的过程与应用这些操作所需的任务解耦时,适合使用Event-Sourcing模式。

    这样的方式也能够用来改善UI性能,或者将事件分发给其它监听器,如其它应用程序或服务,来进行集成。

  • 当开发人员想能够依据需求灵活改变Materialized模型和实体数据的格式的情况下。当开发人员须要在使用CQRS模式的时候,适配读模型或者视图的时候。
  • 当配合CQRS模式共同使用时,接受终于一致性的延迟,以及同意依据事件又一次计算读模型或者Materialized视图的状态的情况下。也能够使用Event-Sourcing模式

Event-Sourcing模式在例如以下的情况下不太适用:

  • 领域模型非常小,或者业务较为简单,系统仅仅有非常少或没有业务逻辑,或非域系统。与CRUD架构就能非常好满足需求的情况下,不适合使用Event-Sourcing。
  • 系统对一致性和实时更新的数据视图要求较高的时候,不适合使用Event-Sourcing模式。

  • 系统不须要审计跟踪、历史和回滚和重放操作的功能的时候,由于复杂性的原因,不适合使用Event-Sourcing模式。
  • 数据更新冲突非常少的情况下,并不适用于使用Event-Sourcing。比如,系统的主要工作是加入数据而不是更新数据的情况。

使用举例

某个会议管理系统须要跟踪完毕预订的会议,该系统能够在某个希望參加会议的人尝试申请參加的时候,检查是否还有空暇座位。该系统能够以至少两种方式来存储预定库存的总数:

  • 该系统能够将预订库存总量的信息作为一个单独的实体在存储在数据库中。

    能够预订或取消,系统能够适当的添加或降低这个数字。这样的方法在理论上是非常简单,可是假设大量的预定的人在非常多的时间内试图预订的座位的话,可能导致扩展性问题。比如,在预订期结束之前的最后一天内,可能有大量的预定请求。

  • 该系统能够将预订和取消的事件存储到数据仓库中。库存总量能够通过遍历这些事件的来计算。

    由于事件的不变性,这样的方法的可扩展性更好。

    系统仅仅须要能够从事件存储区读取数据,或将数据加入到事件存储区。关于预订和取消事件的信息不会改动的。

图2显示了怎样使用Event-Sourcing来实现会议管理系统的座席预订子系统。

图2在会议管理系统中使用Event-Sourcing获取座位预订信息

保留两个座位的动作顺序例如以下:

1. 用户界面发出一个命令,为两位与会者预留座位。

该命令由一个单独的命令处理程序处理(一个与用户界面解耦的应用逻辑,负责处理作为命令发送的请求)。

2. 通过请求全部的预定和取消会议的事件,来获取一个包括全部预定信息的数据集合。

这个数据集合叫SeatAvailability,并支持查询当中的库存信息。

能够使用快照来做一些优化(因此开发人员不须要查询和重放事件的完整列表以获取的SeatAvailability的当前状态),并在内存中维护聚合的缓存副本。

3. CommandHandler调用由域模型的方法来预定或取消。

4. SeatAvailability记录包括座位库存。

下一次计算库存数时,将遍历全部的预订时间来计算还有多少库存。

5. 该系统添加的新事件会存储在事件仓库中。

假设用户希望取消座位,该系统遵循相似的过程,由命令处理程序产生一个取消座位的事件并将其加入到事件存储中。

除了提供了更好的扩展性外,事件仓库为全部的预定和取消操作都保留了操作历史。不管是为了跟踪。或者分析挖掘,都提供了良好的支持。由于事件仓库中记录的事件是真实的唯一来源。系统没有必要持久化其它的状态信息。由于能够非常easy地又一次遍历事件并计算不论什么时间点实体状态。

开发人员能够在Introducing Event Sourcing中更具体的了解这个样例。

相关的其它模式

当考虑实现Event-Sourcing模式的时候,也能够參考例如以下相关模式:

  • CQRS模式.CQRS实现中所提供的不可变信息源的写存储通常就是基于Event-Sourcing模式的一种实现。

    CQRS模式描写叙述了怎样将操作。读取数据和应用程序的操作,通过使用单独的更新数据的接口来分离职能。

  • Materialized-View模式.在Event-Sourcing模式中所使用的数据仓库,通常来说是不利于查询的。

    通常提高查询效率的方式,就是每隔一定的时间,依据数据仓库生成预填充的视图来提高查询效率。Materialized-View模式描写叙述了改功能是怎样实现的。

  • Compensating-Transaction模式. 在实现Event-Sourcing模式中的数据仓库中的数据是不会运行更新操作的。通常,都会通过添加额外的事件来运行回滚等操作,来恢复实体的状态。Compensating-Transaction模式描写叙述怎样撤消由前一个操作运行的工作。

  • Data Consistency Primer. 当使用Event-Sourcing时,读数据仓库或者Materialized视图是不会保证实时一致的。相对来说,他们会保证终于一致性。Data Consistency Primer中讲述了分布式数据保证一致性的诸多问题。
  • Data Partitioning Guidance. 在使用Event-Sourcing的时候。为了提升扩展性,优化性能,降低争用。会考虑对事件存储进行分区。Data Partitioning Guidance中描写叙述了怎样将数据进行分区,以及分区中可能产生的问题等。
时间: 2024-10-12 13:03:39

Event-Souring模式的相关文章

Centos7部署lamp: httpd2.4(event)+module模式

系统: Centos7 httpd版本: 2.4 使用event工作模式 安装方法: 使用yum安装httpd和mariadb 编译安装php,启用多线程支持 一.安装httpd和mariadb: yum install -y httpd httpd-devel php-mysql mariadb-server systemctl start mariadb      //启动mariadb systemctl start httpd         //启动httpd     二.安装PHP:

Apache 工作的三种模式:Prefork、Worker、Event

Apache 的三种工作模式(Prefork.Worker.Event) Web服务器Apache目前一共有三种稳定的MPM(Multi-Processing Module,多进程处理模块)模式. 它们分别是prefork,worker.event,它们同时也代表这Apache的演变和发展. 本文原文转自米扑博客:Apache 工作的三种模式:Prefork.Worker.Event 如何查看我们的Apache的工作模式呢?可以使用httpd -V 命令查看,如我安装的Apache 2.4版本.

Apache的三种工作模式

Web服务器Apache目前一共有三种稳定的MPM(Multi-Processing Module,多进程处理模块)模式. 它们分别是prefork,worker和event,它们同时也代表这Apache的演变和发展. 如何查看我们的Apache的工作模式呢?可以使用httpd -V 命令查看,如我安装的Apache 2.4版本. $ /usr/local/apache24/bin/httpd -V Server version: Apache/2.4.18 (Unix) Server buil

apache工作模式介绍

apache作为现今web服务器用的最广泛也是最稳定的开源服务器软件,其工作模式有许多中,目前主要有两种模式:prefork模式和worker模式 . prefork模式:这个多路处理模块(MPM)实现了一个非线程型的.预派生的web服务器,它的工作式类似于Apache 1.3.它适合于没有线程安全库,需要避免线程兼容性问题的系统.它要求将每个请求相互独立的情况下最好的MPM,这样若一个请求出现问题就不会影响到其他请求. 这个MPM具有很强的自我调节能力,只需要很少的配置指令调整.最重要的是将M

Apache优化配置——工作模式

Apache所运行的硬件环境都是对性能影响最大的因素 各个硬件指标中,对性能影响最大的是内存,其次是硬盘的速度 ●Apache的工作模式 1.prefork模式(一个 非线程型的) ⑴.主要工作方式:当Apache服务器启动后,mpm_prefork模块会预先创建多个子进程(默认为5个),每个子进程只有一个线程,当接收到客户端的请求后,mpm_prefork模块再将请求转交给子进程处理,并且每个子进程同时只能用于处理单个请求.如果当前的请求数将超过预先创建的子进程数时,mpm_prefork模块

Apache Prefork、Worker和Event三种工作模式分析

一,Apache三种MPM介绍 Apache 2.X 支持插入式并行处理模块,称为多路处理模块(MPM).在编译apache时必须选择也只能选择一个MPM,对类UNIX系统,有几个不同的MPM可供选择,它们会影响到apache的速度和可伸缩性.这三种MPM记录于conf/extra/httpd-mpm.conf文件中. Prefork MPM:这个多路处理模块(MPM)实现了一个非线程型的.预派生的web服务器,它的工作方式类似于Apache 1.3.它适合于没有线程安全库,需要避免线程兼容性问

Centos6部署lamp: httpd2.4+module模式

系统: Centos6 httpd版本: 2.4 使用event工作模式 php版本: 5.4.26 mariadb版本: 5.5.46 xcache版本: 3.0.3 安装顺序: php最后安装 一.准备源码包: 二.安装httpd: 1.安装所需环境 yum groupinstall -y"Development tools" "Server Platform Development" yum install -y pcre-devel     2.    安装

Centos6部署lamp: httpd2.4+fpm模式

系统: Centos6 httpd版本: 2.4 使用event工作模式 php版本: 5.4.26 mariadb版本: 5.5.46 xcache版本: 3.0.3 httpd:     192.168.1.101 mariadb:  192.168.1.102 php:      192.168.1.103 安装顺序: php最后安装 注意事项: 1.在httpd2.2上使用fcgi功能,需要额外打补丁 一.安装httpd2.4: 在192.168.1.101上操作   1.    准备源

apache的mpm工作模式

查看Apache工作模式的命令是: [[email protected] httpd-2.2.32]# /usr/local/apache2/bin/apachectl -M [[email protected] ~]# /usr/local/apache2/bin/apachectl -M Loaded Modules: core_module (static) authn_file_module (static) authn_default_module (static) authz_hos

Command and Query Responsibility分离模式

CQRS模式,就是命令和查询责任分离模式. CQRS模式通过使用不同的接口来分离读取数据和更新数据的操作.CQRS模式可以最大化性能,扩展性以及安全性,还会为系统的持续演化提供更多的弹性,防止Update命令在域模型Level发生冲突. 问题 在传统的数据管理系统中,更新数据以及请求数据的命令是通过数据仓库中的同一类型的实体来执行操作的.这些实体属于关系数据中的表的一列或者几列. 通常,在这些系统中,所有的创建,读取,更新以及删除(CRUD)操作都是应用到相同的实体的.举例来说,一个数据传输对象