2025上半年,最新 AI实践都在这!20+ 应用案例,任听一场议题就值回票价 了解详情
写点什么

Martin Fowler 谈如何理解事件驱动

  • 2017-03-13
  • 本文字数:1877 字

    阅读完需:约 6 分钟

去年年底,ThoughtWorks 内部开展了一个研讨会,讨论“事件驱动”应用程序的性质。在过去的几年里,他们建立了许多基于事件的系统,有被称赞,也有被吐槽。ThoughtWorks 的北美办公室组织了一次峰会,来自世界各地的 ThoughtWorks 高级开发人员在会上分享了他们的想法。 峰会的最大结果是得出这样的一个结论:当人们谈论“事件”时,他们实际上意味着一些完全不同的事情。 所以 Martin Fowler 花了很多时间试图从中挑出一些有用的模式, 本文就是对这些内容的简要总结。

事件通知(Event Notification)

事件通知是最基本也是最简单的模型。当一个系统发生了变更,它会通过发送事件消息的形式通知其他系统。发送消息的系统不要求接收消息的系统返回任何响应,即使有响应返回,它也不对其进行任何处理。这也就是所谓的“fire and forget”模式。

事件通知的好处在于它的简单性,并且有助于降低系统间的耦合性。不过,如果在一个复杂的生态系统里使用了太多的事件通知,可能会带来一些问题。太多的事件难以跟踪,发生问题难以调试,除非借助完善的实时监控系统。消息流错综复杂,当其规模开始膨胀开来,就会造成隐患。

通知事件不会包含太多的数据,一般只包含了一些 ID 或者链接之类的信息。对于接收消息的系统来说,如果它们想得到进一步的信息,或者要基于当前事件做出一些变更,那么它们就需要向源系统发起请求,以便获取更多的数据。那么问题来了,额外的请求不仅会造成延迟,而且一旦源系统宕机,后续的流程就无法继续进行。

事件传递状态转移(Event-Carried State Transfer)

事件传递状态转移模型比事件通知更进一步,可以看作是对事件通知的改进。这个模型最大的特点是,事件里包含了发生变更的数据。对于接收事件的系统来说,如果想要采取进一步措施,可以直接使用事件里的数据,而无需再次向源系统发起请求,从而降低了延迟。而且就算源系统宕机,也不会影响到后续的流程。

不过,既然把变更数据放在事件里进行传输,那么占用更多的带宽是不可避免的了。而且,如果有多个系统接收事件,那么这些数据就会有多个拷贝。

除此之外,接收事件的系统需要维护事件的状态,从而将原本存在于源系统的复杂性转移到了接收事件的系统上。

事件溯源(Event-Sourcing)

事件溯源的核心理念是说,在对系统的状态做出变更时,把每次变更记录为一个事件,在未来的任何时刻,都可以通过重新处理这些事件来重建系统的状态。事件存储是主要的事件来源,可以从事件存储中重建系统的状态。对于程序员来说,版本控制系统是一个最好的例子。提交日志就是事件存储,而代码工作副本就是系统状态。在某个指定的工作副本上重播提交日志就可以创建另一个工作副本,也就是重建了某个时刻的系统状态。

使用事件溯源的系统有哪些好处?首先,事件存储结构简单,易于存储,它们可以被存储在数据库里、文件系统或者其他任意的存储引擎里。因为记录事件是插入操作,没有修改也没有删除,就不需要用到事务控制,这也意味着可以避免使用锁。所以,使用事件溯源可以提升系统的性能。其次,事件本身可以充当审计日志的作用。如果不使用事件溯源,那么就需要为系统维护单独的审计日志。使用单独的审计日志就意味着有存在两个“真相源”,如果审计日志发生丢失,那么通过审计日志重建的状态与真实的系统状态会不一致。

不过,事件溯源也存在一些不足。如果事件很多,重放事件是一个耗时的过程,而且在重放过程中可能会涉及与第三方外部系统发生交互,所以需要做一些额外的操作。查询某个时刻的状态会变得很麻烦,因为需要通过重播事件来重建当时的状态。解决办法是使用快照。不过,系统没有必要为每次变更都创建快照,而是阶段性地创建快照。在查询状态时,通过在临近的快照上重放少量的事件就可以获得想要查询的状态。

CQRS

CQRS 是 Command Query Resposibility Segregation(命令查询职责分离)的缩写,它将读操作(查询)和写操作(增、删、改命令)进行分离,不仅让逻辑更清晰,而且可以各自进行优化。对于读多写少的系统来说,就特别适合使用 CQRS,因为可以针对读性能和写性能进行优化,而且可以进行横向扩展。

不过 CQRS 的概念虽然简单,但是实现起来相对复杂,而且涉及到很多领域驱动设计的(DDD)概念,最好结合事件溯源一起使用。

更多资料


感谢郭蕾对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2017-03-13 19:003148
用户头像

发布了 322 篇内容, 共 150.2 次阅读, 收获喜欢 148 次。

关注

评论

发布
暂无评论
发现更多内容

[架构实战] 课后作业二

爱学习的麦子

Python应用之计算阶乘

芯动大师

函数 10月月更 阶乘计算

大数据ELK(十一):Elasticsearch架构原理

Lansonli

elasticsearch 10月月更

【LeetCode】在LR字符串中交换相邻字符Java题解

Albert

LeetCode 10月月更

如何在 Linux 中删除超过 30 天的文件

wljslmz

Linux 10月月更

Taurus: 面向机器学习的数据面架构

俞凡

人工智能 网络 自智网络

MyBatis 学习笔记之MyBatis入门开发

薛定谔的猫

mybatis 10月月更 mybatis入门

MyBatis 学习笔记之配置文件

薛定谔的猫

mybatis 10月月更 mybatis配置文件

2022-10-02:以下go语言代码能否通过编译?A: 能;B: 不能;C: 不知道。 package main import ( “fmt“ ) type worker interfa

福大大架构师每日一题

golang 福大大 选择题

业务实时监控服务

穿过生命散发芬芳

10月月更 业务监控

react的jsx和React.createElement是什么关系?面试常问

beifeng1996

React

乐观锁和悲观锁

潜水员

并发

Docker下,两分钟极速体验Nacos

程序员欣宸

Docker Spring Cloud 10月月更

架构师的十八般武艺:风险管理

agnostic

风险管理

Qt中读取json文件以及总结

中国好公民st

c++ qt 10月月更

Vue3入门指北(六)列表渲染

Augus

Vue3 10月月更

【牛客刷题-算法】NC4 判断链表中是否有环

清风莫追

算法 10月月更

【从0到1学算法】2.递归

Geek_65222d

10月月更

Linux操作系统——用户管理、实用指令

胖虎不秃头

Linux 10月月更

Linux操作系统——组管理和权限管理

胖虎不秃头

Linux 操作系统 10月月更

计算机网络——以太网交换机学习和转发帧

StackOverflow

编程 计算机网络 10月月更

匿名网络追踪溯源机制及方法

郑州埃文科技

IP地址 追踪溯源 匿名网络

架构师的十八般武艺:变更管理

agnostic

需求变更

Linux操作系统——定时任务调度、磁盘分区与挂载、网络配置

胖虎不秃头

Linux 操作系统 10月月更

Python基础(六) | 面向对象类定义及特性详解

timerring

实例 10月月更

Python基础(七) | 文件、异常以及模块详解

timerring

异常 模块 10月月更

【愚公系列】2022年10月 Go教学课程 016-运算符之逻辑运算符和其他运算符

愚公搬代码

10月月更

【一Go到底】第二天---你好,Go and GOROOT&GOPATH

指剑

golang Go入门 10月月更

用30分钟相中10倍工程师

愚夫一得

面试 技术管理 招聘 文化 & 方法

js事件循环与macro&micro任务队列-前端面试进阶

loveX001

JavaScript

【牛客刷题-算法】3-第一篇-斐波拉契数列-C实现

清风莫追

递归 数据结构与算法、 10月月更

Martin Fowler谈如何理解事件驱动_语言 & 开发_ Martin Fowler_InfoQ精选文章