01-认识Kafka

认识Kafka

每个应用程序都会产生数据:日志消息、度量指标、用户活动记录、响应消息等。数据为企业发展提供动力,从数据中获取信息,对它们进行分析处理,然后生成更多的数据。

我们把数据从源头移动到可以对它们进行分析处理的地方,然后把得到的结果应用到实际场景中,这样才能确切地知道这些数据要告诉我们什么。例如,我们在网站上浏览的商品、看过的视频,这些浏览信息被推荐系统转化成商品推荐,并在稍后展示给我们。

虽然有很多数据库和系统可以用来存储数据,但是缺少一个可以帮助处理持续数据流的组件。Kafka是一个流平台:在这个平台上,可以发布和订阅数据流,并把它们保存起来进行处理。

Kafka经常会和其它技术对比,例如:消息队列(MQ)、大数据系统(Hadoop)、数据集成、ETL工具。

Kafka和其它技术的对比

Kafka和MQ

Kafka允许发布和订阅消息,从这点来看,它类似消息队列。但是下列差异使它不同于消息队列:

  • Kafka作为一个现代的分布式系统,以集群的方式运行,可以自由伸缩,可以处理整个公司所有的数据流
  • Kafka可以按照要求存储数据,保存多久都可以
  • Kafka的流式处理能力将数据处理的层次提升到新的高度,让你只用很少的代码就能够动态地处理派生流和数据集

Kafka和Hadoop

从另一个角度,可以将Kafka看做是实时版的Hadoop,这也是Kafka设计团队的原始动机之一。

  • Hadoop可以存储和定期处理大量的数据文件,而Kafka可以存储和持续处理大型的数据流。流处理和批处理的最大不同体现在延迟上。
  • Hadoop主要应用在大数据分析上,而Kafka因其低延迟的特点更适合用于核心的业务应用上。业务事件时刻在发生,Kafka能够及时对这些事件做出响应,提升用户体验。

Kafka和ETL

Kafka和ETL都擅长移动数据,但Kafka并非只是把数据从一个系统拆解出来,然后塞进另一个系统。

  • Kafka可以将现有的应用程序和数据系统连接起来
  • Kafka可以用于加强这些触发相同数据流的应用
  • 以数据流为中心的架构

发布与订阅消息系统

消息(数据)的发布者不会直接把消息发送给接收者。

发布者以某种方式对消息进行分类;接收者(订阅者)订阅某一类或某几类消息,以便接收特定类型的消息。

发布与订阅系统一般会有一个broker,也就是发布消息的中心点。

多个重复的消息系统

Kafka相关术语(重点)

消息和批次

Kafka的数据单元被称为消息,可以把消息看成是数据库里的一条记录。消息由字节数组组成,所以对于Kafka而言,消息里面的数据没有特别的格式和含义。消息可以有一个可选的元数据,也就是键key,键也是一个字节数组,对Kafka而言也没有特殊含义。当消息以一种可控的方式写入不同的分区时,会用到键。例如,对消息的键进行一致性hash,取模,然后确定消息所属分区。

为了提高效率,消息被分批次写入Kafka。批次是一组属于同一个主题和分区的消息。如果每一个消息都要单独传输,那会导致大量的网络开销。批次数据还可以进一步通过压缩数据来提升数据的传输和存储能力,但是这意味着要做更多的计算处理(压缩耗时)。要处理批次和时延之间的关系,暂时认为:批次越大,效率虽然越高(吞吐量),但是时延也越大。

模式(schema)

对于Kafka而言,消息不过是晦涩难懂的字节数组,所以有人建议用一些额外结构来定义消息内容,使其更易于理解。

消息模式,包括json、xml等,这两者简单、易用、可读性好,但是缺乏强类型处理能力,不同版本之间的兼容性也不是很好。因此Kafka开发者喜欢使用Avro。

数据格式的一致性对Kafka来说很重要,它消除了消息读写操作之间的耦合性。假设读写操作紧密地耦合在一起,那么会产生如下问题:

  • 消息订阅者需要升级应用程序才能同时处理新旧两种数据格式。
  • 在消息订阅者升级后,消息发布者才能跟着升级,以便使用新的数据格式。(这是什么道理?为什么有新格式的数据?为什么升级?)

主题(topic)和分区

Kafka的消息通过主题进行分类。主题和消息的关系,就像文件类型对于文件的关系一样。

主题可以被分为若干个分区,一个分区就是一个提交日志,消息以追加的方式写入分区,然后以FIFO的顺序读取。一个主题一般包含多个分区,只能保证一个分区内数据的顺序性,无法保证一个主题的数据的顺序性。

一个主题的多个分区可以分布在不同的服务器上,也就是说,一个主题可以横跨多个服务器。

生产者和消费者

Kafka的客户端就是Kafka系统的用户,客户端被分为两种类型:生产者和消费者。(用于数据集成的Kafka Connect API和用于流处理的Kafka Stream)

生产者创建消息。一般情况下,一个消息会被发布到一个特定的主题上。在默认情况下,生产者会把消息均衡地分布到主题的所有分区上,而并不关心特定消息会被写到哪个分区上。(默认:通过对消息的键进行hash取模来确定分区)生产者也可以使用自定义的分区器,自定义消息到分区的映射规则。

消费者读取消息。消费者订阅一个或多个主题,并按照消息生成的顺序来读取它们。消费者通过检查消息的偏移量来区分已经读取过的消息。偏移量是一个不断递增的整数值,和键一样属于消息的元数据,在创建消息时,Kafka会把它添加到消息里。在给定的分区里,每个消息的偏移量都是唯一的。消费者会把每个分区最后读取的消息偏移量保存在Zookeeper或Kafka上,如果消费者关闭或重启,它的读取状态不会丢失。(消费者记录偏移量可以类比看书的书签,下次可以继续看)

消费者是消费者群组的一部分,也就是说,会有一个或多个消费者共同读取一个主题。但是一个分区只能由群组中的一个消费者使用,即分区被消费者所有,称为消费者对分区的所有权关系。如果一个消费者失效,那么消费者群组里面的其他消费者可以接管失效消费者的工作和分区。例如下图中,消费者0只能从分区0中读取消息。

Kafka中的多消费者并不一定要构成消费者组的模式,可以实现一个主题多个消费者互不影响的读取,即每个消费者都可以处理一次(这和一般的消息队列不同),也可以通过消费者组让同组的多个消费者总共只处理一次消息。

消费者群组

元数据可以认为是一个类的field字段,例如String类中除了保存实际的数据char[] data,还有 int length,那么length就可以认为是data的元数据。

broker(首领)和集群(控制器)

一个独立的Kafka服务器被称为broker,单个broker可以轻松处理数千个分区以及每秒百万的消息量,broker的作用:

  • broker接收来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存。
  • broker为消费者提供服务,对读取分区的请求作出响应,返回已经提交到磁盘上的消息。

每个Kafka集群都有一个broker同时充当集群控制器的角色,这是通过从集群中的活跃成员中选举出来的。控制器负责管理工作,包括将分区分配给broker和监控broker。

在Kafka集群中,一个分区可以分配给多个broker(分区复制),但是同一时刻只会有一个broker对该分区负责,该broker称为分区的首领。如果分区的首领broker失效,那么分配该分区的其他broker可以接管领导权,称为新的首领。

从下图中,目前的猜测是:生产者只会将消息发送给分区的首领,由首领来复制消息到该分区的其他broker中。相当于一主多从架构,主服务器负责写,从服务器从主服务器中拷贝数据。

Kafka集群的分区复制

多集群

如果是多数据中心(不同地理位置),就需要在它们之间复制消息。例如,一个用户修改了数据资料,不管哪个数据中心都应该能够看到这个改动。但是Kafka的消息复制机制只能在单个集群进行,不能在多个Kafka集群之间进行。Kafka提供一个叫做MirrorMaker的工具,可以用它来实现在多个集群之间的消息复制。但是这种方式在创建复杂的数据管道方面有点力不从心。

多Kafka集群

保留消息

在一定期限内,Kafka能够保留消息。默认的保留策略是:

  1. 设定阈值,时间阈值或文件大小阈值,例如:保留一段时间(比如7天),保留到消息达到一定大小的字节数(比如1GB)
  2. 当触发阈值时,这些保存的消息就会被当做旧消息删除。

主题topic可以配置自己的保留策略

使用场景(有待理解完善)

活动跟踪

Kafka最初的使用场景是跟踪用户的活动。网站用户和前端应用程序之间发生交互,应用程序生成用户活动相关的信息,这些信息可以是一些静态的信息:页面访问次数或点击量,也可以是一些复杂的操作:添加用户资料等。这些消息被发布到一个或多个主题上,由后端应用程序负责读取。这样,我们就可以生成报表,为机器学习系统提供数据,更新搜索结果等功能。

传递消息

Kafka的另一个基本用户是传递消息。应用程序向用户发送通知(比如二维码)就是通过传递消息来实现的。

度量指标和日志记录

Kafka也可以用于收集应用程序和系统度量指标以及日志。这和Kafka支持多个生产者的特性有关。

应用程序定期把度量指标发布到Kafka主题上,监控系统或报告系统读取这些主题上的消息。

日志消息也可以发布到Kafka主题上,然后被路由到专门的日志搜索系统(Elasticsearch)或安全分析应用程序。

提交日志

Kafka的基本概念来源于提交日志。

我们可以把数据库的更新发布到Kafka上,应用程序通过监控事件流来接收数据库的实时更新。这种变更日志流也可以用于把数据库的更新复制到远程系统上,或者合并多个应用程序的更新到一个单独的数据库视图上。

流处理

Hadoop需要离线处理数据,花费的时间可能是几小时或几天。而Kafka可以作为流处理平台,简单的流处理操作。

似乎流处理并不用Kafka,一般会使用Spark这类的

Kafka 性质

幂等性(处理重复消息)

以 HTTP 为例,无论是一次或是多次请求,得到的响应结果是一致的(不考虑网络问题)。换句话说,幂等性就是执行多次操作与执行一次操作的影响是一样的。类似 JavaEE 开发中需要考虑的重复提交问题

实现原理

为了实现 Kafka 生产者的幂等性,Kafka 引入了 PID 和 Sequence Number 的概念

  • PID:Producer ID,每个生产者在初始化时,都会分配一个唯一的 PID,这个 PID 对于用户而言是透明的
  • Sequence Number:可以认为是一个三维数组int[][][]的元素,由生产者PID、主题topic、分区partition共同决定,SequenceNumber是从0开始递增的。

image-20230604215134481

本质上就是在消息添加两个字段,一个PID用于区分生产者,另一个Sequence Number用于区分同一个生产者发送的不同的消息。如果Sequence Number不大于该生产者之前消息中的Sequence Number,则认为该消息是触发了生产者的重试机制发送的,直接丢弃即可。


   转载规则


《01-认识Kafka》 熊水斌 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
03-Kafka生产者 03-Kafka生产者
Kafka生产者案例场景,信用卡事务处理系统: 有一个客户端应用程序,可能是一个在线商店(淘宝) 每当有支付行为发生时,负责将事务发送到Kafka上 另一个应用程序(支付宝)根据规则引擎检查这个事务,决定响应批准还是拒绝,并将响应消息写回
2023-05-27
下一篇 
2023-05-26
  目录