首页 > 编程知识 正文

kafka原理详解,kafka底层原理解析

时间:2023-05-05 23:22:28 阅读:33210 作者:222

1.kafka基础设施

Producer :消息生产者,向Kafka发布消息的作用。

消费者:从消息消费者(即Kafka )中提取消息消费的客户端。

Consumer Group :消费群体、消费群体在群体中存在多个消费者,消费者消费中介当前主题的不同细分信息在消费群体之间互不影响,所有消费者都属于某个消费群体。 也就是说,消费者群体是有逻辑的订阅者。 一个分区的消息只能由一个消费群体中的一个消费者消费

Broker :高金毛,一台Kafka服务器是一个Broker,一个集群由多个Broker组成,一个Broker可以容纳多个Topic。

主题:主题可以理解为一个队列,生产者和消费者都面向一个主题

分区:分区。 为了实现可扩展性,可以将非常大的主题分散在多个中介中。 一个主题可以分为多个分区,每个分区都是有序队列。 (分区有序,并不能保证全球秩序。 )

复制副本—复制副本。 Kafka工作正常,以防止群集中的某个节点出现故障,导致节点上的分区数据丢失。 Kafka提供了复制副本机制,每个主题分区都有多个复制副本、一个Leader和多个Follower

Leader—每个分区的多个副本的主要作用、生产者发送数据的对象以及消费者消费数据的对象是leader。

Follower :每个分区有多个副本的从属角色。 实时从Leader同步数据,并保持与Leader数据的同步。 Leader发生故障时,一个Follower成为新的Leader。

2 .工作流程

主题是逻辑变化,分区是物理概念,每个分区对应一个包含producer数据的日志文件。 topic=N*partition; partition=log

Producer生产的数据不断添加到该log文件的末端,而且每个数据都有自己的offset,consumer组的每个consumer实时记录自己消耗了哪个offset,所以错误得到了恢复过程: producer=topic(logwithoffset )=Consumer。

3 .文件存储

Kafka文件存储也存储在本地下拉列表中,主要以相应的日志和索引等文件存储特定的消息文件。

生产者不断向log文件中添加消息文件,以防止log文件过大导致定位效率低下,Kafka的log文件以1G为界, log文件大小超过1G时,新的. log文件

kafka日志的存储位置(即文件位置)包括消耗偏移和特定的分区信息,分区信息主要包括. index和. log文件

由于分区用于备份,因此同一分区存储在不同的broker中。 也就是说,third-2存在于当前计算机kafka01上,实际上kafka03也包含此分区的文件(副本)。 分区包含副本。 这意味着一个分区可以有多个副本,其中一个分区是leader,其他分区是follower。

4 .生产者ISR

为了确保从producer发送的数据发送到指定的topic,topic中的每个分区都必须在收到producer发送的数据后向producer发送确认http://ww瓦时

发送确认的时机

确认follower和leader同步完成,leader重新发送ack; 这样可以确保leader锁定后,可以从follower中选择新的leader

否则重新发送数据

的所有follower同步完成后,才能发送ack

4.1 .同步副本集(ISR ) )。

预想的

采用这种方式进行同步ack后,如果leader接收到数据,并且所有follower都开始同步数据,但某个follower由于某种故障导致与leader的同步延迟,则leader必须等待同步完成,然后发送ack 在这种情况下,怎样才能解决这个问题呢?

解决

leader维护了动态同步(ISR )。 也就是说,与leader同步的follower的集合。 ISR中的follower完成数据同步后,向leader发送ack。 如果follower长时间未将数据同步到leader,则如果leader出现故障,ISR将选择新的leader。

br>  

5 生产者ack机制
对于某些不太重要的数据,对数据的可靠性要求不是很高,能够容忍数据的少量丢失,所以没有必要等到ISR中所有的follower全部接受成功。

Kafka为用户提供了三种可靠性级别,用户根据可靠性和延迟的要求进行权衡选择不同的配置。

ack参数配置

0:producer不等待broker的ack,这一操作提供了最低的延迟,broker接收到还没有写入磁盘就已经返回,当broker故障时有可能丢失数据

1:producer等待broker的ack,partition的leader落盘成功后返回ack,如果在follower同步成功之前leader故障,那么将丢失数据。(只是leader落盘)

-1(all):producer等待broker的ack,partition的leader和ISR的follower全部落盘成功才返回ack,但是如果在follower同步完成后,broker发送ack之前,如果leader发生故障,会造成数据重复。(这里的数据重复是因为没有收到,所以继续重发导致的数据重复)

6 数据一致性问题

LEO(Log End Offset):每个副本最后的一个offset
HW(High Watermark):高水位,指代消费者能见到的最大的offset,ISR队列中最小的LEO。
follower故障和leader故障

follower故障:follower发生故障后会被临时提出ISR,等待该follower恢复后,follower会读取本地磁盘记录的上次的HW,并将log文件高于HW的部分截取掉,从HW开始向leader进行同步,等待该follower的LEO大于等于该partition的HW,即follower追上leader之后,就可以重新加入ISR了。
leader故障:leader发生故障之后,会从ISR中选出一个新的leader,为了保证多个副本之间的数据的一致性,其余的follower会先将各自的log文件高于HW的部分截掉,然后从新的leader中同步数据。
这只能保证副本之间的数据一致性,并不能保证数据不丢失或者不重复
 

7. ExactlyOnce
将服务器的ACK级别设置为-1(all),可以保证producer到Server之间不会丢失数据,即At Least Once至少一次语义。将服务器ACK级别设置为0,可以保证生产者每条消息只会被发送一次,即At Most Once至多一次。

At Least Once可以保证数据不丢失,但是不能保证数据不重复,而At Most Once可以保证数据不重复,但是不能保证数据不丢失,对于重要的数据,则要求数据不重复也不丢失,即Exactly Once即精确的一次。

在0.11版本的Kafka之前,只能保证数据不丢失,在下游对数据的重复进行去重操作,多余多个下游应用的情况,则分别进行全局去重,对性能有很大影响。

0.11版本的kafka,引入了一项重大特性:幂等性,幂等性指代Producer不论向Server发送了多少次重复数据,Server端都只会持久化一条数据。幂等性结合At Least Once语义就构成了Kafka的Exactly Once语义。

启用幂等性,即在Producer的参数中设置enable.idempotence=true即可,Kafka的幂等性实现实际是将之前的去重操作放在了数据上游来做,开启幂等性的Producer在初始化的时候会被分配一个PID,发往同一个Partition的消息会附带Sequence Number,而Broker端会对<PID,Partition,SeqNumber>做缓存,当具有相同主键的消息的时候,Broker只会持久化一条。

但PID在重启之后会发生变化,同时不同的Partition也具有不同的主键,所以幂等性无法保证跨分区跨会话的Exactly Once。
 

8.消费者分区分配策略
消费方式

consumer采用pull拉的方式来从broker中读取数据。

push推的模式很难适应消费速率不同的消费者,因为消息发送率是由broker决定的,它的目标是尽可能以最快的速度传递消息,但是这样容易造成consumer来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。而pull方式则可以让consumer根据自己的消费处理能力以适当的速度消费消息。
pull模式不足在于如果Kafka中没有数据,消费者可能会陷入循环之中 (因为消费者类似监听状态获取数据消费的),一直返回空数据,针对这一点,Kafka的消费者在消费数据时会传入一个时长参数timeout,如果当前没有数据可供消费,consumer会等待一段时间之后再返回,时长为timeout。
 

8.1 分区分配策略

一个consumer group中有多个consumer,一个topic有多个partition,所以必然会涉及到partition的分配问题,即确定那个partition由那个consumer消费的问题。

Kafka的两种分配策略:

round-robin循环
range
Round-Robin

主要采用轮询的方式分配所有的分区,该策略主要实现的步骤:

假设存在三个topic:t0/t1/t2,分别拥有1/2/3个分区,共有6个分区,分别为t0-0/t1-0/t1-1/t2-0/t2-1/t2-2,这里假设我们有三个Consumer,C0、C1、C2,订阅情况为C0:t0,C1:t0、t1,C2:t0/t1/t2。

此时round-robin采取的分配方式,则是按照分区的字典对分区和消费者进行排序,然后对分区进行循环遍历,遇到自己订阅的则消费,否则向下轮询下一个消费者。即按照分区轮询消费者,继而消息被消费。

分区在循环遍历消费者,自己被当前消费者订阅,则消息与消费者共同向下(消息被消费),否则消费者向下消息继续遍历(消息没有被消费)。轮询的方式会导致每个Consumer所承载的分区数量不一致,从而导致各个Consumer压力不均。上面的C2因为订阅的比较多,导致承受的压力也相对较大。

Range

Range的重分配策略,首先计算各个Consumer将会承载的分区数量,然后将指定数量的分区分配给该Consumer。假设存在两个Consumer,C0和C1,两个Topic,t0和t1,这两个Topic分别都有三个分区,那么总共的分区有6个,t0-0,t0-1,t0-2,t1-0,t1-1,t1-2。分配方式如下:

range按照topic一次进行分配,即消费者遍历topic,t0,含有三个分区,同时有两个订阅了该topic的消费者,将这些分区和消费者按照字典序排列。
按照平均分配的方式计算每个Consumer会得到多少个分区,如果没有除尽,多出来的分区则按照字典序挨个分配给消费者。按照此方式以此分配每一个topic给订阅的消费者,最后完成topic分区的分配。

按照range的方式进行分配,本质上是以此遍历每个topic,然后将这些topic按照其订阅的consumer数进行平均分配,多出来的则按照consumer的字典序挨个分配,这种方式会导致在前面的consumer得到更多的分区,导致各个consumer的压力不均衡。

8.2 消费者offset的存储

由于Consumer在消费过程中可能会出现断电宕机等故障,Consumer恢复以后,需要从故障前的位置继续消费,所以Consumer需要实时记录自己消费到了那个offset,以便故障恢复后继续消费

Kafka0.9版本之前,consumer默认将offset保存在zookeeper中,从0.9版本之后,consumer默认将offset保存在kafka一个内置的topic中,该topic为__consumer_offsets

 9. Kafka中zookeeper的作用

Kafka集群中有一个broker会被选举为Controller,负责管理集群broker的上下线、所有topic的分区副本分配和leader的选举等工作。Controller的工作管理是依赖于zookeeper的。

Partition的Leader的选举过程

10. API生产者流程
Kafka的Producer发送消息采用的是异步发送的方式,在消息发送的过程中,设计到了两个线程main线程和Sender线程,以及一个线程共享变量RecordAccumulator,main线程将消息发送给RecordAccumulator,Sender线程不断从RecordAccumulator中拉取消息发送到Kafka broker中。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。