Kafka介绍

一、Kafka介绍

Kafka是一款开源的、轻量级的、分布式的、可分区和具有复制备份的(Replicated)、基于ZooKeeper协调管理的分布式流平台的功能强大的消息系统。与传统的消息系统相比,Kafka能够很好地处理活跃的流数据,使得数据在各个子系统中高性能、低延迟地不停流转。据Kafka官方网站介绍,Kafka定位就是一个分布式流处理平台。在官方看来,作为一个流式处理平台,必须具备以下3个关键特性。

(1)能够允许发布和订阅流数据。从这个角度来讲,平台更像一个消息队列(MQ)或者企业级消息系统。
(2)存储流数据时提供相应的容错机制。
(3)当流数据到达时能够被及时处理。

Kafka能够很好地满足以上3个特性,通过Kafka能够很好地建立实时流式数据通道,由该通道可靠地获取系统或应用程序的数据,也可以通过Kafka方便地构建实时流数据应用来转换或对流式数据进行响应处理。特别是在0.10版本之后,Kafka推出了Kafka Streams,这让Kafka对流数据处理变得更加方便。
Kafka消息系统基本的体系结构如图16-71所示。

生产者:负责生产消息,将消息写入Kafka集群

消费者:从Kafka集群中拉取消息。

在对Kafka基本体系结构有了一定了解之后,我们对Kafka的基本概念进行详细阐述。
(1)主题
Kafka将一组消息抽象归纳为一个主题(Topic),一个主题就是对消息的一个分类。生产者将消息发送到特定主题,消费者订阅主题或主题的某些分区进行消费。
(2)消息
消息是Kafka通信的基本单位,由一个固定长度的消息头和一个可变长度的消息体构成。在老版本中,每一条消息称为Message,在由Java重新实现的客户端中,每一条消息称为Record。
(3)分区和副本

Kafka将一组消息归纳为一个主题,而每个主题又被分成一个或多个分区(Partition)。每个分区由一系列有序、不可变的消息组成,是一个有序队列。每个分区在物理上对应为一个文件夹,分区的命名规则为主题名称后接“-”连接符,之后接分区编号,分区编号从0开始,编号最大值为分区的总数减l。每个分区又有一至多个副本(Replica),分区的副本分布在集群的不同代理上,以提高可用性。从存储角度上分析,分区的每个副本在逻辑上抽象为一个日志(Log)对象,即分区的副本与日志对象是一一对应的。每个主题对应的分区数可以在Kafka启动时所加载的配置文件中配置,也可以在创建主题时指定。当然,客户端还可以在主题创建后修改主题的分区数。分区使得Kafka在并发处理上变得更加容易。理论上来说,分区数越多,吞吐量越高,但这要根据集群的实际环境及业务场景而定。同时,分区也是Kafka保证消息被顺序消费以及对消息进行负载均衡的基础。Kafka只能保证一个分区之内消息的有序性,并不能保证跨分区消息的有序性。每条消息被追加到相应的分区中,是按顺序写入磁盘的,因此效率高。同时与传统消息系统不同的是,Kafka并不会立即删除已被消费的消息,由于磁盘的限制,消息不会一直被存储(事实上这是没有必要的),因此Kafka提供两种删除老数据的策略:
基于消息已存储的时间长度。
基于分区的大小。

(4)Leader副本和Follower副本
由于Kafka副本的存在,因此需要保证一个分区的多个副本之间数据的一致性,Kafka会选择该分区的一个副本作为Leader副本,而该分区其他副本作为Follower副本,只有Leader副本才负责处理客户端的读/写请求,Follower副本从Leader副本同步数据。如果没有Leader副本,就需要所有的副本同时负责读/写请求处理,同时还得保证这些副本之间数据的一致性。假设有n个副本,就需要有n×n条通路来同步数据,这样数据的一致性和有序性就很难保证。引入Leader副本后,客户端只需要与Leader副本进行交互,这样数据的一致性及顺序性就有了保证。Follower副本从Leader副本同步消息,对于n个副本只需n-1条通路即可,这样就使得系统更加简单而高效。Follower副本与Leader副本的角色并不是固定不变的,如果Leader副本失效,那么将通过相应的选举算法从其他Follower副本中选出新的Leader副本。

(5)偏移量
任何发布到分区的消息会被直接追加到日志文件(分区目录下以“.log”为文件名后缀的数据文件)的尾部,而每条消息在日志文件中的位置都会对应一个按序递增的偏移量。偏移量是一个分区下严格有序的逻辑值,它并不表示消息在磁盘上的物理位置。由于Kafka几乎不允许对消息进行随机读写,因此Kafka并没有提供额外索引机制存储偏移量,也就是说并不会给偏移量再提供索引。

消费者可以通过控制消息偏移量来对消息进行消费,如消费者可以指定消费的起始偏移量。为了保证消息被顺序消费,消费者已消费的消息对应的偏移量也需要保存。需要说明的是,消费者对消息偏移量的操作并不会影响消息本身的偏移量。旧版消费者将消费偏移量保存到ZooKeeper中,而新版消费者将消费偏移量保存到Kafka内部的一个主题中。当然,消费者也可以自己在外部系统保存消费偏移量,而无须保存到Kafka中。

(6)日志段
一个日志又被划分为多个日志段(Log Segment),日志段是Kafka日志对象分片的最小单位。与日志对象一样,日志段也是一个逻辑概念,一个日志段对应磁盘上一个具体日志文件和两个索引文件。日志文件是以“.log”为文件名后缀的数据文件,用于保存消息实际数据。两个索引文件分别以“.index”和“.timeindex”作为文件名后缀,分别表示消息偏移量索引文件和消息时间戳索引文件。
(7)代理
在Kafka基本体系结构中,我们提到了Kafka集群。Kafka集群是由一个或多个Kafka实例构成的,我们将每一个Kafka实例称为代理(Broker),通常也称代理为Kafka服务器(Kafka Server)。在生产环境中,Kafka集群一般包括一台或多台服务器,我们可以在一台服务器上配置一个或多个代理。每一个代理都有唯一的标识ID,这个ID是一个非负整数。在一个Kafka集群中,每增加一个代理就需要为这个代理配置一个与该集群中其他代理不同的ID,ID值可以选择任意非负整数,只要保证它在整个Kafka集群中唯一,这个ID就是代理的名字,也就是在启动代理时配置的broker.id对应的值。

(8)生产者
生产者(Producer)负责将消息发送给代理,也就是向Kafka代理发送消息的客户端。
(9)消费者和消费组
消费者(Consumer)以拉取方式获取数据,它是消费的客户端。在Kafka中,每一个消费者都属于一个特定的消费组(Consumer Group),我们可以为每个消费者指定一个消费组,以groupId代表消费组名称,通过group.id配置项设置。如果不指定消费组,该消费者就属于默认消费组test-consumer-group。同时,每个消费者也有一个全局唯一的ID,通过配置项client.id指定,如果客户端没有指定消费者的ID,Kafka就会自动为该消费者生成一个全局唯一的ID,格式为${groupId}-${hostName}-$
{timestamp}-${UUID前8位字符}。同一个主题的一条消息只能被同一个消费组下某一个消费者消费,但不同消费组的消费者可同时消费该消息。消费组是Kafka用来实现对一个主题消息进行广播和单播的手段,实现消息广播只需指定各消费者均属于不同的消费组,消息单播则只需让各消费者属于同一个消费组。

(10)ISR
Kafka在ZooKeeper中动态维护了一个ISR(In-Sync Replica),即保存同步的副本列表,该列表中保存的是与Leader副本保持消息同步的所有副本对应的代理节点ID。若一个Follower副本宕机或落后太多,则该Follower副本节点将从ISR列表中移除。
通过以上Kafka基本概念的介绍,我们可以对Kafka基本结构图进行完善,如图16-72所示。

原文地址:https://www.cnblogs.com/callbin/p/14621201.html