Kafka基本概念
Kafka是什么?
Kafka是一个由Scala和Java编写的企业级的消息发布和订阅系统。最早由LinkedIn公司开发,最终开源到Apache软件基金会的项目。Kafka是一个分布式的,支持分区的,多副本,多订阅者且基于zookeeper协调的高吞吐量的分布式消息系统,也是一个分布式流式处理平台。它以高吞吐、可持久化、可水平扩展、支持流数据处理等多种特性而被广泛应用在应用解耦、异步处理、限流削峰和消息驱动等场景。
Kafka基本概念
Producer:生产者,负责将消息发送至Kafka中,支持消息的异步发送和批量发送。
Consumer:消费者,消费者连接到Kafka上并接收消息;
Consumer Group(CG):消费者组,由多个consumer组成。同一个消费者组内只会有一个消费者消费到消息;不同消费者组的消费者可以消费到同一条消息。
消费者组之间互不影响。所有的消费者都属于某个消费者组,即消费者组是逻辑上的一个订阅者。
Broker:服务代理节点。对于Kafka而言,Broker可以简单看做一个独立的Kafka服务节点或Kafka服务实例。一个Kafka集群由多个broker组成。一个broker可以容纳多个topic。
Message:通过Kafka集群进行传递的对象实体,存储需要传输的信息。
Topic:消息的类别,主要用于对消息进行逻辑上的区分。Kafka的消息以主题为单位进行归类,生产者负责将消息发送到特定的主题(发送到Kafka集群中的每一条消息都要指定一个主题),而消费者负责订阅主题并进行消费。
Partition:主题是一个逻辑上的概念,它可以细分为多个分区,一个分区只属于单个主题。同一个主题下的不同分区的消息是不同的,分区在存储层面可以看做一个可追加的日志文件,消息在被追加到分区日志文件的时候都会分配一个特定的偏移量(offset)。
offset是消息在分区中的唯一标识,Kafka通过它来保证消息在分区内的顺序性。不过offset并不跨越分区,也就是说,Kafka保证的是分区内有序而不是主题有序。
旧版消费者将消费偏移量信息保存在zookeeper中,新版消费者保存在Kafka内部的一个主题中。
每一条消息被发送到broker之前,会根据分区规则选择存储到哪个具体的分区。如果一个主题只对应一个文件,那么这个文件所在的机器I/O将会成为这个主题的性能瓶颈,而分区解决了这个问题;
分区使得Kafka在并发处理上变得更加容易,理论上分区越多吞吐量越高。但是这要根据集群实际环境和业务场景而定;
分区是Kafka保证消息顺序消费以及对消息进行负载均衡的基础。
Segment:一个分区中存在多个segment文件段(分段存储),每个Segment分为两部分:.log日志文件和.index索引文件,两个文件文件名一样,且一一对应。
.index是索引文件,主要用于快速查询.log文件当中数据的偏移量位置,使用稀疏索引方式存储;
.log是日志文件,存放Message的数据文件,在Kafka中把数据文件叫做日志文件。一个分区默认有n多个.log文件。一个.log文件大小默认1G,消息会不断追加到.log文件中,当.log文件的大小超过1G时,会自动新建一个新的.log文件。
Replica:副本,Kafka为分区引入了多副本机制,通过增加副本数量,提升容灾能力。同一分区的不同副本中保存的相同的消息(在同一时刻,副本之间并非完全一样);副本之间是“一主多从”的关系,其中,leader副本负责处理读写请求,follower副本只负责与leader副本的消息同步。副本处于不同的broker中,当leader副本出现故障时,从follower副本中重新选举新的leader副本对外提供服务。Kafka通过多副本机制,实现故障的自动转移,当Kafka集群中,某个broker失效时,仍然能保证服务可用。
Kafka消息端也具备一定的容灾能力。Consumer使用拉(pull)模式从服务端拉取消息,并且保存消费的具体位置,当消费者宕机后恢复上线时,可以根据之前保存的消费位置重新拉取需要的消息进行消费,这样就不会造成消息丢失。
AR(Assigned Replicas)分区中的所有副本;
ISR(In-Sync Replicas)所有与leader副本保持同步的副本(包括leader副本);
ISR集合是AR集合的一个子集,消息会先发送到leader副本,然后follower副本才能从leader副本中拉取消息进行同步,同步期内,follower副本相对leader副本会有一定程度的滞后。
OSR(Out-of-Sync Replicas)与leader副本同步滞后过多的副本(不含leader副本)
AR = ISR + OSR
leader副本负责维护和跟踪ISR集合中所有副本的滞后状态,
当follower副本落后太多或失效时,leader副本会把它从ISR集合中剔除。
如果OSR集合中有follower副本“追上”了leader副本,那么leader副本会把它从OSR集合转移到ISR集合。
默认情况下,当leader副本发生故障时,只有在ISR集合中的副本才有资格被选举为新的leader,而在OSR集合中的副本则没有任何机会(不过这个原则也可以通过修改响应的参数配置来改变);
HW(High Watermark),俗称高水位,它标识了一个特定的消息偏移量(offset),消费者只能拉取到这个offset之前的消息;
LEO(Log End Offset),它标识当前日志文件中下一条待写入消息的offset,分区ISR集合中每个副本都会维护自身的LEO
Kafka系统架构
一个典型的Kafka集群包括Producer、Broker、Consumer等角色,以及一个Zookeeper集群。Kafka系统架构图如下:
Kafka消息ACK确认机制
ack=-1:
表示消息发送到集群的leader并且同步ISR中的所有follower成功后,才表示消息发送成功;
ack=0:
表示生产者发送完消息后,无论kafka接收成功与否都视为发送成功;
ack=1:
表示消息发送到leader且磁盘持久化成功后表示消息发送成功,至于是否同步到集群中的其他follower并不关注;
kafka默认的ack的值为1
Kafka特性
消息持久化
- kafka依赖文件系统(磁盘)存储消息;
- 大家普遍认为磁盘速度远小于内存,但是磁盘的快慢取决于我们如何去使用磁盘,线性(顺序)读写磁盘的速度要大于内存随机读写;
- 并且现代操作系统提供了预读(read-ahead)和延迟写(write-behind)技术;
- kafka是基于JVM的,如果采用内存存储,java对象的内存消耗非常高,且随着java对象的增加GC也会越来越频繁;
- 传统的消息系统数据持久化一般会提供一个类似于B树的随机访问数据结构来维护消息的元数据,B树的时间复杂度为O(log n),B树虽然有一定的优势,但会随着数据的增长性能会下降。而kafka的数据持久化是顺序追加,时间复杂度为O(1),性能和数据大小没有关系。
高吞吐量
- 充分利用磁盘的顺序读写的特性;
- Kafka在数据写入和数据同步采用零拷贝技术,采用sendFile()函数,sendFile()是在两个文件描述符之间直接传递数据,完成在内核中操作;
- 支持数据压缩和批量发送;
- 一个主题分为多个分区;
- kafka每秒支持数百万级别的消息;
集群扩展
- kafka依赖zookeeper对集群进行协调管理,水平扩展时集群自动感知,重新进行负载均衡及数据复制;
(完)