kafka是用于构建实时数据管道和数据流的应用程序。具有实时横向扩展、高吞吐量、支持大量堆积具有容错性和速度快等特点。它是一个高性能分布式消息系统。通常一个分布式流数据平台它具有三个特点:
发布和订阅功能,类似于消息系统
以容错的方式记录流
处理流
Kafka通常用于构建在系统或应用之间的实时数据流管道、构建实时流应用程序用于转换和响应数据流。
基本概念
主题:就是消息的分类,生产者将消息发送到特定主题,消费者订阅该主题或者主题的分区来进行消费。
消息:就是数据,一个固定长度的消息头和一个可变长度的消息体组成。
分区和副本:一个主题可以分成多个分区,每个分区由一系列有序、不可变的消息组成,是一个有序队列。每个分区在物理上对应一个文件夹,分区的命名规则为主题名称后接“-”连接符,之后再接分区编号,分区编号从0开始,表示第一个分区。如下图主题test6666有3个分区,编号0、1、2
每个分区有一个或多个副本并且分布在集群不同的代理商以提高可用性。看下图:
test6666主题有3个分区,但是副本只有1个。而下面的BBB主题也有3个分区,但是副本数量有3个。分区的每个副本在逻辑上抽象为一个日志对象。也就是分区副本与日志对象是一一对应的。以BBB主题为例,3个分区,每个分区3个副本,那么集群中有3个服务器,那么每个服务器都有BBB主题这三个分区的日志,但是如果都有到底哪一个副本对外提供服务呢?当然每个分区中只有一个副本对外提供服务,可以看到上图的Leader标示的那样。我们通过zookeeper查看,如下图:
BBB主题的分区0,它的leader是2,与上图相符。下面说一下这个字段的含义
字段 | 含义 |
controller_epoch | 用于记录控制器发送变更次数。每一个代理实例化的时候都会启动一个KafkaController,并将代理的brokerId注册到zookeeper上,控制器主要负责主题的创建、删除、分区和副本的变化以及代理的故障转移。该值初始值为0,每变化一次增加1,客户端向控制器发送请求要带上这个值,如果小于该值表示请求时过期的,如果大于则说明以及有了新的控制器,这个值是为了保证机器控制器的唯一性。 |
leader | 该主题的这个分区的当前Leader是谁,这里记录的是brokerId,也就是代理的ID。 |
version | |
leader_epoch | 分区Leader更新次数,这个是相对分区而言。 |
isr | 表示该分区有几个副本,这里显示一个列表,列表元素个数表示副本个数,元素值表示它的副本分布在哪些brokerId的代理上 |
分区使得Kafka在并发处理上变得容易,分区越多吞吐量就越高,但这样要根据实际场景而定。分区也是Kafka保证消息被顺序消费以及对消息进行负载均衡的基础。Kafka只能保证一个分区只内的消息有序性,无法保证跨分区消息的有序性。每条消息是通过追加且顺序写入磁盘所以效率很高。而且kafka并不会立刻删除已经消费的消息,但是也不会一直保存,他提供两种策略一个是时间一个是分区大小。
Leader副本和Follower副本:同一个分区的多个副本目的就是为了冗余提高可用性,所以就必须保证副本的一致性,那么Kafka会选择分区内的一个副本作为Leader副本,而其他副本作为Follower副本,只有Leader副本处理读写请求。Follower副本只是从Leader上复制数据。
偏移量:发布到分区的消息会追加到日志文件的尾部,每条消息在日志文件中的位置都会对应一个按序递增的偏移量。不过偏移量不表示消息在磁盘上的位置,而且kafka几乎不允许对消息进行随机读写,消费者可以指定偏移量的的起始位置进行消费。旧版消费者将偏移量保存到Zookeeper中,新版则保存到Kafka内部的一个主题中,消费者也可以保存偏移量到其他地方。
日志段:日志又被划分为多个日志段,日志段是kafka日志对象分片的最小单位。与日志对象一样,日志段也是逻辑概念。一个日志段对应磁盘上一个具体日志文件和两个索引文件,日志以.log结尾,两个索引以.index和.timeindex结尾,表示消息偏移量索引文件和消息时间戳索引文件。
代理:其实就是Kafka服务,一个Kafka服务叫做一个实例,也就是一个代理。一个集群通常包含多台代理,每个代理有一个非负整数的id,且在整个集群中id值是唯一的。
生产者:也就是发送消息的客户端
消费者和消费者组:消费者通过拉的方式获取数据,每一个消费者都属于一个消费者组,我们可以为每个消费者指定一个组。如果不指定则属于默认消费者组test-consumer-group。同时每个消费者也有一个唯一id,如果没有指定则kafka会为其自动生成一个。同一个主题的消息只能被消费者组中的一个消费者消息,但不同消费者组中的消费者可以消费这条消息。
ISR:Kafka在Zookeeper中动态维护一个ISR,也就是保存同步的副本列表,该列表中保存的是与Leader副本保持消息同步的所有副本对应的代理节点id。如果一个Follower宕机或者其落后太多,则该Follower副本节点将从ISR列表中移除。
Kafka的特性
它的设计初衷就是成为统一、实时处理大数据的平台,所以它必须支持几个场景:
高吞吐量的日志事件流
能承受大量积压
低延迟处理消息
能支持分区、分布式,实时处理且容错能力。
持久化,消息系统一般不同提供持久化,因为消息被消费了也就没有意义了,它不像数据库。不过kafka收到消息会顺序写入日志一旦数据落盘也就实现了持久化。Kafka在设计上采用O1的磁盘结构,也就是数据访问性能不随数据量增大而增加。用户可以自己设置Kafka把消息保存多久,这样重启后已经存储的消息可以继续恢复使用。
高吞吐量,它设计的目的就是高吞吐,充分利用顺序读写。同时在数据写入和数据同步时采用了零拷贝技术,采用sendFile()函数。所谓零拷贝就是用户空间到内核空间的拷贝,这个过程省去了,而是sendFile,也就是从内核空间直接存储数据到硬盘。
扩展性,有良好的横向扩展能力,它依赖Zookeeper来做集群协调者,使用普通PC服务器就可以搭建大规模集群。
多客户端支持,JAVA、C、PYTHON、Node.js等主流语言都支持。
丰富的安全机制
数据备份,副本机制
轻量级,Kafka代理是无状态的,代理不记录消息是否被消费,消费者偏移量的管理由消费者自己或者组协调器来维护,集群本身也不需要生产者和消费者的状态信息。
支持压缩,GZIP、SNAPPY、LZ4这三种压缩方式。通常把多条消息放到一个消息集合中,然后再把消息集合放到一条消息里,从而提高压缩率。
应用场景
通常用来解耦、异步通信、流量控制。从而构建一个高效、灵活、消息同步和异步传输处理、存储转发、可伸缩和最终一致性的系统平台。目前流行的消息系统有Kafka、RocketMQ、RabbitMQ、ZeroMQ、ActivieMQ、MetaMQ、Redis(属于NoSQL但是具有发布订阅功能),各有所长。不过Kafka常用在高吞吐量和支持大量积压的环境中、应用系统监控、网站用户行为跟踪(将用户行为信息发送到Kafka上在通过其他大数据平台进行分析梳理)、流处理、持久性日志。