写点什么

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:002961
用户头像

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

关注

评论

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

【写作训练营打卡|07】你知道文章的配图哪来的吗?

群晖(Synology)新建存储池使用 Home 服务

HoneyMoose

Caché/M 数据库上面的那个 é 怎么打

HoneyMoose

Kyligence 荣登甲子光年 2023 AIGC 技术应用领域最具商业潜力榜

Kyligence

数据分析 智能决策

实时数据推送应用

玄兴梦影

消息推送 实时数据

高校刮起元宇宙风!3DCAT实时云渲染助力川轻化元校园建设

3DCAT实时渲染

实时云渲染 元宇宙解决方案

大模型助力科技革命:2023年的里程碑与大模型的未来展望

屿小夏

年度总结 大模型

法语 Alt 代码表

HoneyMoose

西班牙语 Alt 代码表

HoneyMoose

Apache IoTDB PMC Chair 黄向东主办 2023 开放原子开发者大会开源工业物联网大数据分论坛,诚邀您的参加!

Apache IoTDB

深入了解埋点分析:Clklog助你优化用户体验

ClkLog

马斯克回应聊天机器人 Grok 抄 ChatGPT 作业;Figma 推出宏编程键盘丨 RTE 开发者日报 Vol.105

声网

技术写作及技术作者的概述和重要性 - 了解技术写

小万哥

技术 程序人生 写作 软件开发 作者

重磅发布!!!蚂蚁图团队开源高性能原生图存储系统CStore

TuGraphAnalytics

数据库 分布式 图计算 图存储 图原生

大模型扫盲问题集

小判

大模型

极狐GitLab 镜像仓库使用技巧

极狐GitLab

DevOps gitlab 镜像 CI/CD 镜像仓库

2023-12-13:用go语言,密码是一串长度为n的小写字母,一则关于密码的线索纸条, 首先将字母a到z编号为0到25编号, 纸条上共有n个整数ai,其中a1表示密码里第一个字母的编号, 若i>1的

福大大架构师每日一题

福大大架构师每日一题

天谋科技荣获国家高新技术企业认证

Apache IoTDB

从Rustup出发看Rust语言的编译生态

程序饲养员

编译器 rust语言

第31期 | GPTSecurity周报

云起无垠

场场爆满的昇腾 AI 开发者创享日:照见产业数智化的涓涓动力

Alter

一起学Elasticsearch系列-搜索推荐

Java随想录

Java 大数据 elastic 搜索

让艺术触手可及!3DCAT实时云渲染赋能真浪数字艺术馆首展

3DCAT实时渲染

实时云渲染 元宇宙解决方案

物联网与低代码:构建智能化的连接世界

快乐非自愿限量之名

低代码 物联网 IoT

Trace 在多线程异步体系下传递

观测云

Trace 链路

德语 Alt 代码表

HoneyMoose

想突破转化瓶颈?安排上 AI ,比漏斗图更高效、更实用!

Kyligence

数据分析 转化分析

多链铭文聚合协议20Exchange将为Ordi、SATS持仓用户快照空投

股市老人

1.5万字 + 25张图盘点RocketMQ 11种消息类型,你知道几种?

快乐非自愿限量之名

RocketMQ 事务管理

下一站 Gen AI 城市巡展指南来了!“码”上出发,Let's 构!

亚马逊云科技 (Amazon Web Services)

AIGC

内置功率 MOSFET 的高频同步整流降压开关变换器

芯动大师

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