这是探索Kafka存储层和处理层核心基础系列文章的第一篇。在这篇文章中,我们将总体介绍事件、流、表以及流和表之间的二元性关系。后续的文章将着重探索Kafka的存储层,也就是流和表的分布式“文件系统”,然后再介绍位于存储层之上的处理层。
我与很多Kafka用户有过交流,他们当中有开发人员、运维人员和架构师,有一些有流式处理或Kafka使用经验,有一些精通关系型数据库(如Oracle和MySQL),有一些则两者都不熟悉。不过,他们会问我相同的问题,比如:“事件流和数据库表之间有什么区别?Kafka的主题跟流是同一种东西吗?如果把数据放在Kafka里,如何最大程度地利用它们?”
我们先从最基本的开始:Kafka是什么?Kafka是一个事件流平台,它提供了这三个关键特性:
那么这里所说的事件是什么东西?
事件记录了真实世界“发生了某件事情”。从概念上讲,一个事件包含一个键、一个值和时间戳。事件可以是一个普通的通知,可能不包含额外的信息,也可能包含所有可用于后续处理的细节。例如:
事件还可能是这样的:
事件流平台捕捉事件,将事件形成事件流。事件流按照事件的顺序记录了真实世界发生的历史,例如销售账簿或者象棋比赛时记录的棋子移动顺序。Kafka的流可以记录几百年的业务历史事件。它们是按顺序排列的事件链,我们可以知道哪个事件是在哪个事件之前或之后发生的。所以,流代表了过去和现在:当时间从今天走向明天,或者从这一毫秒走到下一毫秒,新的事件会持续不断地被追加到历史中。
与事件流不一样,数据库的表代表的是世界在某个时间点的状态,通常是“现在”。例如,商品的总销量或者象棋比赛中棋盘的当前布局。表是事件流的一个视图,在捕捉到新事件时就会更新这个视图。
流记录了历史,表代表的是状态
在Kafka里,流和表有很多不一样的地方,其中最突出的一点是它们的内容是否可变(我所说的表是指Kafka Streams里的KTable)。
虽然流和表之间有所区别,但也存在非常紧密的联系。我们把它们之间的这种关系叫作流和表的二元性:
实际上,表的底层就是变更流。如果你有使用过Oracle或MySQL,就应该知道,这些关系型数据库也存在变更流,只是实现细节被隐藏起来了,它们的名字叫重做日志(redo log)或二进制日志(binary log)。在事件流中,重做日志是一等实体,也就是流。我们可以将流转成表,也可以将表转成流。
因为流和表的二元性,我们可以很容易地将流转成表,或者反过来。
下面的例子使用COUNT()将流聚合成一个表。为了方便展示,图中没有显示时间戳。随着新的事件不断被加入流中,表被持续更新,与关系型数据库的物化视图类似,只是它每秒钟可以支持数百万个事件。我们可以把这个想象成是对一个表进行CDC,然后生成一个输出变更流。对一个事件流进行聚合操作则是反过来的:流成了表的输入变更流。
在这个例子中,事件流中事件的键为用户名,值为用户所在位置,事件被持续地聚合成表,并根据键来跟踪用户访问过的位置次数。
将事件流聚合成表
下面是这个例子对应的代码:
我们也可以看到表的输出变更流。变更流对表的变更做出实时响应,以此来生成警报。它也可以被用在运维中,比如将一个表从机器A迁移到机器B上。
每张表都自己的变更流(也叫变更日志)
在后续的文章中,我们将会继续讨论流和表的二元性,它是Kafka弹性伸缩和容错能力的基础!
在这篇文章中,我们了解了事件流平台的基本元素:事件、流和表。我们还介绍了流和表的二元性,以及为什么说二元性是事件流平台(如Kafka)的核心。当然,这篇文章只是一个开始,在下一篇文章中,我们将深入了解Kafka的主题、分区和存储。
原文链接:
https://www.confluent.io/blog/kafka-streams-tables-part-1-event-streaming/
领取专属 10元无门槛券
私享最新 技术干货