基础概念
Broker:kafka集群中的服务器
Topic:消息存储的目录,一个broker可以容纳多个topic
Partition:Topic物理上的分组,一个topic可以分为多个partition
Message:传递的数据对象
Producer:生产message发送到topic,同一个Topic下的不同分区包含的消息是不同的。每一个消息在被添加到分区的时候,都会被分配一个offset,他是消息在此分区中的唯一编号,此外,Kafka通过offset保证消息在分区中的顺序,offset的顺序性不跨分区,也就是说在Kafka的同一个分区中的消息是有序的,不同分区的消息可能不是有序的
Cnsumer:订阅topic消费message
副本:Kafka对消息进行了冗余备份,每一个分区都可以有多个副本,每一个副本中包含的消息是相同的(但不保证同一时刻下完全相同)。副本的类型分为Leader和Follower,当分区只有一个副本的时候,该副本属于Leader,没有 Follower。Kafka的副本具有一定的同步机制,在每个副本集合中,都会选举出一个副本作为Leader副本,Kafka在不同的场景中会采用不同的选举策略。Kafka中所有的读写请求都由选举出的Leader副本处理,其他的都作为Follower副本,Follower副本仅仅是从Leader副本中把数据拉取到本地之后,同步更新到自己的Log中
ISR:ISR集合表示的是目前可用(alive)且消息量与Leader相差不多的副本集合,即整个副本集合的子集。ISR集合中副本所在的节点都与ZK保持着连接,此外,副本的最后一条消息的offset与Leader副本的最后一条消息的offset之间的差值不能超出指定的阈值。每一个分区的Leader副本都维护此分区的ISR集合。如上面所述,Leader副本进行了消息的写请求,Follower副本会从Leader上拉取写入的消息,第二个过程中会存在Follower副本中的消息数量少于Leader副本的状态,只要差值少于指定的阈值,那么此时的副本集合就是ISR集合。
kafka通过zookeeper管理集群配置,选举leader
kafka多个分区之间做不到全局有序,但是每个分区中的数据是有序的
kafka中的Replication指的是partition的复制
消息被提交到磁盘,根据设置保留规则进行保存。每个主题可以设置单独的保留规则,以便满足不同消费者的需求。持久化数据可以保证数据不丢失
生产者
发送方式
发送并忘记:发消息发送服务器,但不关心是否正常达到。大多数情况下,消息都会正常到达。
同步发送:返回一个结果对象,调用get等待,就可以知道消息是否发送成功
异步发送:发送后指定一个回调函数,服务器在返回响应时调用该函数
消息先被放入缓冲区,然后使用单独的线程发送到服务器
生产者配置:
acks:
指定了必须要有多少个分区副本收到消息,生产者才会认为消息写入是成功的
- acks=0 生产者在成功写入消息之前不会等待任何来自服务器的响应。如果当服务器出现了问题,导致服务器没有收到消息,那么生产者就无从得知,消息也就丢失了。
- ack=1 只要集群首领节点收到消息,生产者就会收到一个来自服务器的成功响应,如果消息无法到达首领节点(首领节点崩溃,新的首领还没被选举出来),生产者会收到一个错误的响应,生产者会重发消息。不过一个没有收到消息的节点称为新首领,消息还是会丢失(这种情况是在旧的首领收到消息后还没有同步非其他节点,然后崩溃了,发生首领选举,一个没有收到过这条消息的节点胜出,充当了新的首领)
- acks=all 只有当所有参与复制的节点全部收到消息时,生产者才会收到一个来自服务器的成功响应
消费者
kafka消费者从属于消费者群组。一个群组里面的消费者订阅同一个主题,每个消费者接受主题一部分分区的消息
如果添加群组更多的消费者,超过主题分区的数量,那么有一部分消费者就会被闲置,不会接受任何消息
有必要为主题创建大量的分区,在负载增长时可以加入更多的消费者,注意,不要让消费者的数量超过主题分区的数量,多余的消费者只会被闲置
分区的所属权从一个消费者转移到另一个消费者,这样的行为被称为再均衡,为消费者群组带来了高可用性和伸缩性。再均衡期间,消费者无法读取消息,造成整个群组一小段时间的不可用
消费者通过向指派为群组协调器的broker发送心跳来维持他们和群组的从属关系以及他们对分区的所有权关系。如果消费者停止发送心跳的时间足够长,回话就会过期,群组协调器认为他已经死亡吗,就会触发一次再均衡
当消费者要加入群组时,会向群组协调器发送一个请求,第一个加入群组的消费者成为群主,群主从协调器那里获得群组的成员列表(列表中包含了所有最近发送心跳的消费者,他们被认为是活跃的)并负责给每一个消费者分配分区,分配分区完毕后,群主把分配情况列表发送给群组协调器,协调器再把这些信息发送给所有消费者
线程安全
在同一个群组里,我们无法让一个线程运行多个消费者,也无法让多个线程安全地共享一个消费者,按照规则,一个消费者使用一个线程,如果要在同一个消费者群组里运行对个消费者,需要让每个人消费者运行在自己的线程里
提交和偏移量
消费者可以使用kafka来追踪消息在分区里的位置(偏移量)
消费者往一个叫_consumer_offset的特殊主题发送消息,消息里包含每个分区的偏移量,如果发生类似再均衡的操作后,每个消费者可能分配到新的分区,而不是之前处理的那个,消费者需要读取每个分区最后一次提交的偏移量,然后从偏移量指定的地方继续处理
自动提交
enable.auto.commit = true 消费者会自动把接收的最大偏移量提交上去。提交时间间隔有auto.commit.intercal.ms控制,自动提交也是在轮询里进行的。消费者每次在进行轮询时会检查是否该提交偏移量了。这方方式会导致出现消息重复,出了一些消息,但是还没有到提交的时机,然后发生再均衡
提交当前偏移量
通过API手动提交,会不断重试
异步提交
手动提交的不足是在broker对提交请求作出回应之前,应用程序会一直阻塞,导致影响吞吐量,使用异步提交,提交最后一个偏移量,然后继续做其他事情。但是不会重试,原因是收到服务器响应的时候,可能有一个更大的偏移量已经提交成功
可以用一个单调递增的序列号来维护异步提交的顺序。在每次提交偏移量之后递增序列号,进行重试之前,先检查回调的序列号和即将提交的偏移量是否相等
同步和异步组合提交
针对偶尔出现的提交失败,不进行重试不会有问题,因为如果提交失败是因为临时问题导致的,那么后续的提交总会成功的,但如果这是发生在关闭消费者或者再均衡前的最后一次提交,就要确保能够提交成功。
集群关系
kafka使用zookeeper来维护集群成员的信息。每个broker都有一个唯一的标识符。broker在启动的时候,通过创建临时节点吧自己的id注册到zookeeper上。当broker接入集群或退出集群时,这些组件就会获得通知
控制器
控制器是一个broker,除了具有broker的功能之外,还负责分区首领的选举。集群里的第一个启动的broker通过在zookeeper里创建一个临时节点让自己成为控制器。
当控制器发现一个broker已经离开集群,需要选举其中缺失的分区首领。控制器遍历这些分区吗,并确定谁应该成为新首领,然后向所有包含该首领或者跟随者的broker发送请求。该请求消息包含了谁是新首领以及·谁是分区的跟随者信息
复制
首领副本:每个分球都有一个首领副本。为了保证一致性,所有生产者请求和消费者都会经过这个副本
跟随者副本:首领以外的副本都是跟随副本。跟随者副本不处理来自客户端的请求,唯一的任务就是从首领那里复制消息,保持与首领一致的状态。如果首领发生崩溃,其中一个跟随者会被提升为新首领。
为了有首领保持同步,跟随者向首领发送获取数据的请求,这种请求与消费者为了读取消息而发送的请求一致。通过查看跟随者请求的最新偏移量,首领就会知道每个跟随者复制的进度。如果跟随者在10s内没有请求或者虽然有请求,但在10s内没有请求最新的数据,则会被认为是不同步的。如果一个副本无法与首领保持一致,在首领发生失效时,就不可能成为新首领
处理请求
生产请求和获取请求都必须发送给分区的首领副本
客户使用另一种请求类型,这种请求包含了客户端的主题列表,服务端响应的消息里指明了这些主题所包含的分区,每个分区都有哪些副本,以及哪个副本是首领,元数据请求可有发送给任何一个broker,所有broker都缓存了这些信息。
一般情况,客户端会把这些信息缓存起来,并直接往目标broker发送请求和获取请求。他们需要时不时的通过发送元数据请求来刷新这些信息(meta.max.age.ms配置)。客户端收到非首领错误,会尝试重发请求之前刷新元数据
获取请求
不是所有保存在分区首领上的互数据都可以被客户端读取。大部分客户端只能读取已经被写入所有同步副本的消息。在消息还没有被写入所有同步副本之前,是不会发送给消费者的,尝试获取这些消息会得到空的响应
可靠性
kafka的复制机制和分区的多副本架构是kafka可靠性保证的核心。把消息写入多个副本可以使kafka在发生崩溃时仍能保证消息的持久性、
分区首领是同步副本,对于追随者副本来说,需要满足如下条件
- 与zookeeper之间有一个活跃的会话
- 在过去的10s内从首领那里获取过消息
- 在过去的10s内从首领那里获取过最新的消息
一个滞后的副本会导致生产者和消费者变慢,因为在消息被认为已提交之前,客户端会等待所有同步副本接受消息。而如果一个副本不再同步了,就不需要关心她是否已经收到消息。虽然非同步副本同样滞后,但是不会对性能产生任何影响
参考资料
初谈Kafka - 掘金juejin.im Kafka权威指南 (豆瓣)book.douban.com