HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

使用 Kafka Streams 构建事件溯源系统的经验分享

  • 2018-07-09
  • 本文字数:1546 字

    阅读完需:约 5 分钟

近期在乌克兰基辅举行的 JEEConf 大会上, Amitay Horwitz 介绍了他的团队是如何实现一个事件溯源的发票系统、系统两年半生产环境运行期间所遇到的挑战,以及团队是如何使用 Kafka Streams 实现新的设计。

Horwitz 是 Wix 的一位软件工程师,他与团队一起在 2015 年着手实现一种新的发票服务,帮助客户在线管理发票并接收付款。在设计新服务时,他们设想能创建一种小规模的简单软件库,具有非侵入式的、能维护数据的完整性、易于添加客户视图等能力。为实现上述目标,团队决定使用事件溯源架构实现服务。

尽管团队努力实现一种简单的设计,但最终软件库还是变得相当庞大。团队在此过程中也碰上了问题,由于读写最终一致性的问题,客户时常无法看到新建立的发票。虽然创建发票的请求更新写模型加入了新发票信息,但此后的请求是从尚未更新的写模型中读取的,因此并未包括新发票信息。

其中最主要的问题在于如何重构视图。在添加新事件处理器时,需确保对传递而来数据的处理要先于对新事件的处理,并在没有事件进入的情况下触发重构。该机制的实现已被证实要比团队先前的设想更为复杂,尤其对于团队所面对的分布式环境,其中的事件来自于各个服务器。这些问题促使Horwitz 考虑寻求采用另一种能保持事件溯源优点的替代架构。

在Horwitz 看来, Kafka 是一种有副本的、容错的、分布式的只添加日志,常用于“发布者 - 订阅者”模式,或是作为队列使用,他指出 Kafka 还可以实现更多的功能。Kafka 的基本结构称为主题(Topic),它是一种分区的逻辑队列。发布者根据消息中的键值将消息推送到各个分区,进而消费者可以消费这些消息。事件溯源系统具有两个重要关键特性,分别是使用单一分区维护消息的顺序,以及消息可在被消费后得到存储。

Kafka Streams 为 Kafka 添加了流处理能力。它提供了两种抽象:

  • 数据流( Streams ):Horwitz 认为数据流是流动的数据,是一种无限有序并可重放的不可变数据序列,适用于事件源系统。
  • 表( Tables ):Horwitz 认为表是静止的数据。表存储了聚合数据在某个时间点的视图,并在接收到新消息时更新。

在使用 Kafka 的发票系统新设计中,团队实现了一个快照状态存储,用于保存每个聚合的当前状态。当从命令流中接收到一个命令后,命令处理器从状态存储中读取相应聚合的当前状态。进而处理器可以决定命令状态是成功还是失败,并通过结果流返回结果。如果命令处理成功,那么系统将创建事件,推送到事件存储并读取新事件的数据流,然后更新状态存储中的聚合状态为新状态。Horwitz 指出,可以使用非常精确和声明式方式编写命令处理器逻辑。在他给出的例子中,仅使用了 60 行的 Scala 代码。

Kafka 是新架构的核心,其中微服务与 Kafka 通信,而且微服务间也是通过 Kafka 通信的。系统还可推送信息到 Kafka,或是在创建分析报告实例时从 Kafka 获取信息。Horwitz 总结了新设计的多个优点:

  • 简单的声明式系统;
  • 考虑并很好地实现了最终一致性;
  • 易于添加或更改视图;
  • 通过使用 Kafka,增强了系统的扩展性和容错性。

InfoQ 的一次采访中,Horwitz 提及尽管他们已在生产中大量地使用了 Kafka,但是新设计依然处于评估阶段。他指出,有人认为 Kafka 并不适用于 CQRS 和事件溯源系统,但是他认为可在明确权衡考虑的情况下充分使用 Kafka。如果用户希望能保存具有客户各种属性的页面浏览事件,那么就可以轻易地根据这些信息创建聚合。Horwitz 认为这符合事件溯源的形式,Kafka 非常适用于此。

如果以聚合标识作为分区键值,那么同一聚合的所有命令最终将位于同一命令主题分区中,并将使用单线程按序处理。这种方式确保了在如果没有处理生成所有下游(downstream)事件的前一个命令,当前命令不会得到处理。Horwitz 指出,该方式建立了强一致性保证。

查看英文原文: Experiences from Building an Event-Sourced System with Kafka Streams

2018-07-09 08:523276
用户头像

发布了 391 篇内容, 共 135.2 次阅读, 收获喜欢 256 次。

关注

评论

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

OpenTiny 邀你一起参与线下技术交流茶话会!

OpenTiny社区

低代码 OpenTiny Vue组件库 前端开源

Spring 实现 3 种异步流式接口,干掉接口超时烦恼

不在线第一只蜗牛

Java spring 后端

查找大量时序遥感文件缺失、不连贯的成像日期:Python代码

快乐非自愿限量之名

Python GIS

第三届OpenHarmony技术大会开发框架分论坛成功举行

科技热闻

php的html实体和字符之间的转换

百度搜索:蓝易云

深入探索阿里巴巴关键字搜索商品API的返回值

技术冰糖葫芦

API 接口 API 文档 API 测试 API 性能测试

《使用Gin框架构建分布式应用》阅读笔记:p32-p51

codists

gin 编程人

WSL中ubuntu安装mysql数据库

百度搜索:蓝易云

体育直播系统开发方案:从架构到功能,一次性搞懂!

软件开发-梦幻运营部

这个Offer开不开门?

王磊

详解sudo usermod -aG docker majn

百度搜索:蓝易云

Ubuntu22.04如何调试ROS2_humble的源代码

百度搜索:蓝易云

独占鳌头!望繁信科技三大流程挖掘项目入选中国信通院优秀案例

望繁信科技

数字化转型 流程挖掘 流程资产 流程智能 望繁信科技

第三届OpenHarmony技术大会通信互联分论坛圆满举行

科技热闻

使用 Rust(替代 C 语言)扩展 NGINX

NGINX开源社区

读书笔记 rust 编程语言

QCA9880 3x3 MIMO Wi-Fi Solution: Backward Compatible, High Power Output, and RoHS Compliant

wallyslilly

QCA9880 QCA9882

【IoTDB 线上小课 08】时序数据库融合 AI,带来的效果竟然是?

Apache IoTDB

PIRF 412   – Penny for your thoughts

EchoZhou

English

2个比较经典的PHP加密解密函数分享

百度搜索:蓝易云

第二届OpenHarmony竞赛训练营颁奖 ——创新驱动,培育未来科技人才

科技热闻

深入理解Java并发读写锁——ReentrantReadWriteLock

EquatorCoco

Java spring 开发语言

Docker使用中没人注意的小细节

LLLibra146

Docker 容器 运维

程序员失业没offer、空窗期长!掌握Java架构核心宝典就能逆袭!分布式+中间件+大数据与高并发+数据库+设计模式与实践+数据结构与算法!

程序员高级码农

Java 面试 Java’ 程序员‘ Java 面试题 #编程

ComfyUI现已上线Neolink.AI,AI 绘画从此轻松驾驭!

MatrixOrigin

GPU算力 AI绘画

跨境1688代采案例:探索提供1688代采集运系统的公司

代码忍者

pinduoduo API API 性能测试

Mac动作冒险游戏:侠盗猎车手:罪恶都市 for Mac 下载

你的猪会飞吗

Mac游戏下载 Mac游戏推荐 mac破解软件下载

PostgreSQL 可观测性最佳实践

观测云

postgresql

上海交大开源超逼真声音克隆 TTS;微软探索音生图 AI 模型丨 RTE 开发者日报

声网

呼兰:从程序员到脱口秀演员的双面人生

陆通

MatrixOne助力江铜集团打造炉前智慧作业AIoT大数据系统

MatrixOrigin

大数据 AIOT

使用Kafka Streams构建事件溯源系统的经验分享_语言 & 开发_Jan Stenberg_InfoQ精选文章