OceaBase开发者大会落地上海!4月20日共同探索数据库前沿趋势!报名戳 了解详情
写点什么

如何理解事件溯源

  • 2017-09-07
  • 本文字数:3519 字

    阅读完需:约 12 分钟

在近期举行的 PHPDublin 见面会上,来自 DynamicRes 的架构师 Barry Sullivan 被问到“什么是事件溯源”,作为对这个问题的回答,他在博客上写下了这篇文章,详细解释了什么是事件溯源以及事件溯源有哪些好处。以下内容翻译自 Barry 的博客,已获得作者授权。

Web 开发的现状

在详细解释事件溯源之前,先让我们来看看 Web 开发的现状。

当前的 Web 开发是以数据库作为驱动的,在设计 Web 应用的时候,我们会自然而然地将系统设计与数据库存储机制联系在一起。如果使用的是 MySQL,我们就会把数据结构设计成表,如果使用的是 MongoDB,就会把数据结构设计成文档。这样会强制我们只关注事物的当前状态,我们会想“怎样保存这些数据,以便将来可以再把它们拿出来(或者修改它们)”?

这种方式存在三个问题。

1. 有悖于我们的思维

人类的思考和交流并不是以状态为中心。如果我们在咖啡店相遇,我会问你“最近可好”?如果你只是告诉我一堆状态却指望我从中猜出发生了什么事情,这是非常不合情理的。

“我有一幢房子、一辆汽车、一个冰箱、三个社交媒体账号、一只猫咪,我的右脚有点痛,我不擅长聊天,我还有另一只猫咪……”

看到没有?这样我会疯掉的。你应该告诉我,从上次见面之后都发生了哪些事情,这样我才能知道你现在的状况是什么样子的。简单地说,你应该告诉我一个故事,这个故事是由一连串事件组成的。

2. 单一的数据模型

在上图中,读写操作使用了相同的模型。我们从写数据的角度来设计表,然后基于这样的结构查询数据。这对于小型的应用来说是没有问题的,但用在大型的应用里就会有问题。随着系统的增长,查询会变得越来越复杂,总有一天,一个查询可能会包含 10 个连接操作,代码有 100 行那么多。系统很快就会变得脆弱无比,难以维护和变更。

3. 关键业务信息的丢失

这是一个大问题。在以表作为驱动的系统里,你只保存了系统的当前状态,你根本就无法知道系统是如何达到当前状态的。如果我问你“这个用户修改了几次邮件地址”,你有办法回答吗?或者我再问“有多少人把一件商品添加到购物车里,然后又移除掉,直到一个月之后才买了那件商品”,你就更没法回答了。你存储数据的方式丢掉了很多有用的业务信息!

事件溯源

事件溯源与上述的情况恰好相反,它并不关心当前状态,而是关注持续不断的变化事件。

举个例子,假设我们有一个“购物车”,我们可以创建购物车,往里面添加商品或移除商品,然后结账。

购物车的生命周期可以包含如下一系列事件:

  1. 创建购物车
  2. 往购物车里添加商品
  3. 再次往购物车里添加商品
  4. 从购物车里移除商品
  5. 结账

这些就是一个购物车的生命周期,包含了一系列事件。这就是事件溯源,非常简单吧?

几乎所有的流程都可以被看成一系列事件。在与领域专家交谈时,他们不会提及“表”和“连接”,他们会将流程描述成一系列事件以及可以应用在这些事件上的规则。

如何实施业务规则?

大部分的业务操作都有硬性约束。对于购物车来说,它的约束就是“一件商品必须先被放进购物车后才能被移除”。如果一件商品没有被添加到购物车里,又怎么能够移除它?这种事件顺序是不可能发生的。在没有状态的情况下,你怎样才能知道“购物车里是否有这件商品”?

很简单,你只要检查之前是否发生过“商品被添加到购物车里”这个事件,这样你就可以知道购物车里是否存在这件商品,然后移除它。

这样不会浪费时间吗?

一点也不。一般来说,要执行约束,只需要获得事件的一个很小子集。通过简单的数据库查询就可以获得有用的历史事件,在加载完这些事件后重放它们,把它们“投射”出来,以此构建你的数据集。这样的操作其实是很快的,因为你使用的是本地的处理器,而不是执行一系列 SQL 查询(跨域网络的调用要比本地操作慢得多,至少会相差两个数量等级)。

如何展示数据?

如果说每一个状态都是通过重放事件来获得的,那么该如何抓取数据并把它们展示给用户看?每次都需要抓取所有的数据然后再构建这些数据集吗?

答案是你没必要这样做,这样做其实是很荒唐的。

你可以在后台构建数据集,然后把中间结果保存在数据库里。这样,用户就可以在很短的时间内查询到这些数据。

有了事件溯源,你就不再局限于当前的表结构。需要做其他的查询?只要设计一个新的结构就可以了。你可以自由地实现各种读取模型,在不需要它们的时候再把它们抛弃掉。

事件溯源的好处

1. 临时的数据结构

因为所有的状态都可以通过重放事件获得,所以就没有必要把当前“状态”与应用程序绑在一起。如果需要以新的方式查看数据,直接创建新的数据视图即可。不再需要繁杂的数据迁移脚本,要做的只是创建新视图,抛弃旧视图。我现在几乎离不开事件溯源了。

2. 与领域专家的沟通变得更简单

正如之前所述,领域专家通常将业务流程描述成一系列事件,而不是状态。基于事件溯源的系统与领域专家的描述不谋而合,所以就没有必要把他们的描述转换成技术概念,这样也避免了信息丢失。与领域专家的沟通因此变得更加顺畅,因为我们正在使用他们能够理解的语言与他们沟通,这也让软件开发变得很不一样。

3. 极具表现力的模型

在事件溯源模型里,事件是一等对象,事件模型更加接近于实际的业务流程。这让很多东西都变得清晰明了,你就不会陷入存储技术的泥潭。

4. 生成报告更轻松

在事件溯源系统里,生成复杂的报告是一件轻而易举的事情。你拥有完整的历史事件,它们按照时间排序,你可以尽情地使用这些历史数据。

以之前的例子为例,假设你想知道有多少个用户从他们的购物车里移除了商品,却在一周后购买了这些商品。按照一般的开发方式,通常需要几周的时间才能开发出这个功能,而在发布之后,需要等上一段时间,等计算完所有数据之后才能生成报告。而在事件溯源系统里,你可以马上得到报告。你还可以得到之前任何一个时间点的报告,仿佛拥有了一台时光机。

5. 服务集成唾手可得

在标准的 Web 开发流程里,集成两个系统通常会导致他们之间的耦合,而事件溯源系统通过事件来解耦被集成的系统。当一个系统发生某系事件需要触发另一个系统的某个流程时,只需要写一个事件监听器即可。这种机制可以让你在不修改已有领域代码的情况下增加新的集成逻辑或特性。

例如,你想要在用户注册的时候发送一封欢迎邮件给他们,你只需要创建一个事件监听器,监听“用户注册”事件,而不需要去修改注册逻辑代码。

6. 在一般的数据库上也能健步如飞

你不需要使用多么奇特的数据库来存储事件,一般的 MySQL 数据库就足以。数据库都针对追加操作进行过优化,所以存储数据的速度是很快的。这也就是为什么事件溯源在当前的技术条件下能够良好运作,保存事件都是追加操作。

7. 可以随意更换数据库

基于事件溯源的数据结构都是临时性的,所以你可以使用你喜欢的数据库来存储状态,也就是说你完全可以选择最好的工具来完成你的工作。如果你发现了更好的工具,可以在任何时候把旧工具替换掉。我们目前正在从 MySQL 迁移到 OrientDB,可以说是轻而易举。

事件溯源的不足

天下没有完美的东西,事件溯源给我们带来了诸多好处,但也存在一些不足。

1. 最终一致性

事件溯源只能保证最终一致性。也就是说,在一个事件发生了之后,其他系统不会立即感知到它,在它们收到事件之前会有一定的延迟(比如 100 毫秒),所以你所投射的数据可能不是最新的。这看起来似乎是一个大问题,但其实不是的。例如,基于 ReactJS 构建的 Web 应用会基于用户的操作事件构建状态,查询端出现几毫秒的延迟并不会有什么问题。

老实讲,这可以说是塞翁失马,焉知非福。最终一致性的系统具有容错能力,可以解决服务中断问题。如果使用微服务架构或无服务器架构来构建分布式系统,就需要通过最终一致性来保证稳定性。

2. 事件结构发生变化

事件结构会发生变化,如果事先没有考虑到这个问题,后续处理起来会有些麻烦。如果事件结构发生变化,需要写一个更新器来转换新旧事件。转换过程可以在将数据从数据存储中读取出来之后进行。这个没有它看起来那么难,只需要准备好应对策略就可以了。

3. 开发人员需要改变思维

目前的 Web 开发主要还是以状态作为驱动,所以开发者习惯了从表的角度看待问题,而不是事件。我发现要让开发者改变思维需要一些时间,因为他们需要时间来改变习惯。最好的解决办法是让有经验的事件溯源开发者与传统的开发者结对。

总结

我很喜欢事件溯源,在构建大规模分布式系统时,它帮助我们解决了很多问题。我们可以使用领域专家能够了解的语言与他们进行沟通,我们可以自由地改变和适配系统。尽管事件溯源有一定的学习曲线,但一旦你进入到这个领域,就不会想要回头。

查看英文原文: Event Sourcing: What it is and why it’s awesome


感谢郭蕾对本文的审校。

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

2017-09-07 19:005034
用户头像

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

关注

评论

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

texifier mac LaTeX编辑工具下载安装(原Texpad)

Rose

Mac软件 LaTeX 编辑器 Texpad Texifier激活码

面试官:Redis持久化能关吗?怎么关?

王磊

Java 面试题

Rainbond v5.17 版本发布,统一管理离线镜像和私有仓库

北京好雨科技有限公司

Kubernetes 云原生 容器云 离线

Nacos 在云原生架构下的演进

阿里巴巴云原生

阿里云 云原生 nacos

可观测实践丨如何利用 AI 算法解决告警配置三大难题?

阿里巴巴云原生

阿里云 云原生 可观测

弹性调度助力企业灵活应对业务变化,高效管理云上资源

阿里巴巴云原生

阿里云 云原生 弹性计算

秒速出图!体验 TensorRT 加速 Stable Diffusion 图像创作

阿里巴巴云原生

阿里云 云原生

Jira 母公司全面停服 Server 产品,用户如何迁移至极狐GitLab

极狐GitLab

推荐收藏 | 【Git实战专题】「必坑宝典」带你深入剖析Git操作指令下的奥秘原理和运作机制

洛神灬殇

Java git 原理分析 后端处理 2024年第十八篇文章

一些无人不知的命名规范

小魏写代码

文心一言 VS 讯飞星火 VS chatgpt (184)-- 算法导论13.5 1题

福大大架构师每日一题

福大大架构师每日一题

FlagData 2.0:全面、高效的大模型训练数据治理工具集

mr.well

NLP 大模型 LLM模型 #大模型

随想2024.01.21

hackstoic

精力管理

数字人直播软件源码需要多少钱?

青否数字人

从内核的视角观测容器——SysOM 容器监控

阿里巴巴云原生

阿里云 云原生 容器服务

云消息队列 Kafka 版阿里云 SAE 2.0 正式商用:极简易用、百毫秒弹性效率,降本 40%生态谈第一期:无代码转储能力介绍

阿里巴巴云原生

阿里云 Serverless 云原生

画眉(京东科技设计稿转代码平台)介绍

京东科技开发者

Spark SQL五大关联策略

京东科技开发者

魔搭×函数计算:一键部署,缩短大模型选型到生产的距离

阿里巴巴云原生

阿里云 云原生

恭喜 Nacos 和 Sentinel 荣获 2023 开源创新榜“优秀开源项目”

阿里巴巴云原生

阿里云 云原生

Linux 中常见目录的作用

emanjusaka

Linux 目录

DvD刻录软件DVD Cloner 2024 for Mac,现已支持最新的蓝光电影复制

Rose

mac软件下载 DVD克隆 DVD Cloner 2024下载 DVD Cloner 2024 Mac

2023启示录丨我的大模型创业这一年

自象限

创业 #大模型

为什么人工智能与软件测试的结合话题开始火爆

测试人

软件测试 自动化测试 测试开发

【Mac&win】datagrip2023安装教程与激活码分享 亲测有效

Rose

ide DataGrip2023激活 DataGrip2023安装

十家传统企业数字化转型的心得体会:10大关键方面、拆解74 小点

天津汇柏科技有限公司

数字化转型

顺丰科技LaaS实现产品化,数字生态战略提速

新消费日报

CentOS 8上使用NVM安装特定版本的Node.js教程

百度搜索:蓝易云

Linux centos 运维 Node 云服务器

活动回顾丨阿里云云原生 Serverless 技术实践营西安站 PPT 下载

阿里巴巴云原生

阿里云 Serverless 云原生

阿里云 ACK One Serverless Argo 助力深势科技构建高效任务平台

阿里巴巴云原生

阿里云 云原生

【2024开年必备】最全面的Macbook/苹果电脑必备实用软件推荐

Rose

苹果软件 装机必备 Mac应用

如何理解事件溯源_语言 & 开发_Barry Sullivan_InfoQ精选文章