Kafka

Kafka

一、 消息队列概述

1. 消息队列

目前企业中比较常见的消息队列产品主要有Kafka、ActiveMQ、RabbitMQ、RocketMQ等。消息队列的在生产过程中的作用包括:缓冲/消峰、解耦、异步通信

  1. 缓冲/消峰:控制数据流经过系统的速度,能够有效解决生产消息和消费消息速度不一致的情况。
  2. 解耦:确保生产者和消费者具有同样的接口约束的前提下,允许生产者和消费者扩展、修改两边的处理过程。不同数据源的数据可以发送到任意的存储系统。[外链图片转存中…(img-L1lNFPYq-1664344404726)]
  3. 异步通信:将消息存放到队列中,不需要立即对他进行处理,可以等到需要的时候再处理。

同步通信和异步通信的区别

同步通信:就像快递员给发送快递,要求接收方必须当面签收。只有双方同时在场,并且完成签收,才会结束本次任务;如果任何一方没有在场,就会造成另一方变成阻塞状态。

异步通信:就像快递员将快递放到快递驿站,放到驿站之后快递员就会继续执行下次任务,接收方会自行选择时间到驿站取快递,取完快递后才算完成本次的任务。

2. 消息队列的模式

  1. 点对点模式:消费者主动从队列中拉取数据,传输完成后清楚队列中的消息。
  2. 发布/订阅模式:
    • 队列中存在多个主题(topic)的消息,消费者消费之后,不会清理队列中的消息。
    • 存在多个消费者,并且消费者之间都是相互独立的,都可以从队列中消费消息。
    • 队列中的消息清理工作,由消息队列本身决定。

二、 Kafka

1. Kafka定义

Kafka是分布式的、基于发布/订阅模式的消息队列,是一个开源的分布式事件流平台。

2. Kafka基础架构

Kafka由:Kafka Producer(生产者)、Topic、Kafka Consumer(消费者)组成。生产者负责将数据推送到Topic中存储,消费者将消息消费到对应的系统中。[外链图片转存中…(img-6d6fO9tF-1664344404727)]

1. Topic

Kafka是一个村粗多个topic的框架。一个Topic中存储着多个Partition,每个Partition中存储着不同的主题消息。不同的Partition可以存储在Kafka集群的不同节点。

2. Kafka Consumer
  • Kafka中的消费者是以消费者组的形式存在,消费者组之间是相互独立的,但是同组中的消费者不是相互独立的。
  • 同一个消费者组内的消费者共同消费一个Topic的消息,并且一个消费者消费过的Partition,组内其他消费者不能再次消费
  • 消费者组中的消费者数量与分区数无关,但是最好与分区数对应。
  • 虽然一个分区只能被一个消费者消费,但是同一个消费者可以消费多个分区的消息。
3. Kafka Producer

Kafka的生产者在推送消息时产生了两个线程:main线程和sender线程。这两个线程是相互独立的,互不影响。

1. main线程

main线程中创建了一个双端队列RecordAccumulator。main线程将消息发送到队列,会经过拦截器、序列化器、分区器对消息进行处理,按批次推送到队列中。之后由sender线程将消息推送到Kafka Broker。

  • RecordAccumulator队列的默认大小是32MB
  • 每一个批次(batch size)的大小默认是16KB
2. sender线程
  • sender将消息临时存放到缓存空间(NetworkClient),每个分区的数据默认有5个缓存请求。
  • sender线程负责将队列中的数据按批次推送到Broker。
  • 如果队列中的消息累积到batch size大小,就直接发送。
  • 如果迟迟没有满足,则达到linger.ms(时间延迟)后将数据发送到Broker。
  • 消息发送成功后,队列中的对应消息会被清理,如果发送失败则触发重试机制。
  • 重试机制的默认值是int的最大值2147483647。默认重试间隔是100ms。
4. 架构的特点
  1. 一个topic中存在多个partition,便于进行扩展、提高数据的吞吐量。
  2. 消费者以消费者组的形式存在,组内的消费者并行消费,消费者组之间相互独立。
  3. 每个partition存在多个消息副本,副本存放在不同的kafka节点(broker),提高了数据的可用性。
    • 副本机制:副本分为一个leader和多个follower,follower只负责数据的备份工作,leader负责数据的写入和读出
5. 分区的优点
  1. 合理利用存储资源:将数据按照分区存放在不同的Broker,降低了单台节点的传输压力,实现负载均衡。
  2. 提高了数据传输的并行度。

三、 数据可靠性

1. ack应答等级

生产者传输的消息分为三个等级:0、1、-1(all)

  • ack=0:生产者不等待broker落盘数据的应答。
  • ack=1:生产者只等待leader落盘的数据应答。
  • ack=-1:生产者等待所有leader和follower落盘的数据应答。
2. 数据可靠性分析

如果分区中的数据副本数设置为1,或者isr队列中应答的最小副本数为1,这跟ack等级设置为1的效果相同,存在丢数据的风险。

3. 幂等性

无论生产者向broker发送多少次重复的数据,broker只会持久化的保存一条。

数据写入Kafka时,会有全局主键(Pid,Partition,SeqNumber)。具有相同逐渐的消息提交时只会持久化的保存一条。

每次重启Kafka集群,Pid都会重新分配,Partition是分区编号,SeqNumber的值单调自增。

由此可见,幂等性只能保证单分区内的单会话的数据不重复

4. 数据去重
1.至少一次(at least once)
  • ack=1,分区副本数设置大于等于2,isr队列应答最小副本数大于等于2
  • 至少一次能够保证数据不丢失,但是不能保证数据不重复。
2. 至多一次(at most once)
  • ack=0
  • 至多一次可以保证数据不重复,但是不能保证数据不丢失。
3. 精确一次(exactly once)
  • 幂等性 + 至少一次
  • 精确一次可以保证数据不丢失也不重复,需要配合幂等性和事务使用。
  • 跟钱相关的业务需要使用精确一次。
  • 开启Kafka事务的前提是提前开启幂等性。

四、 Kafka Broker工作机制

Kafka集群启动后,集群中的Broker节点会经过选举机制,选出Leader和Follower,Leader负责数据的写入和读取,Follower只负责备份数据。

  • AR:Kafka集群中所有的副本数。
  • ISR:Kafka集群中与Leader同步信息的follower。
  • OSR:已经挂掉的follower。

所以,集群中的 AR = ISR + OSR

1. Controller选举规则

Kafka启动之后,向集群中的Broker会向Zookeeper中注册节点信息,哪一个节点抢先注册成功,该节点的Controller就会辅助选举。第一次启动后,抢先注册成功的Broker就是Leader

如果由broker挂了,Controller会先检查挂掉的节点中有没有Leader,如果没有就不会重新选举,如果有再进行选举。

选举规则:按照Broker在AR中的排名顺序,仍然存活在ISR中为前提,哪个节点的排名靠前,谁就是新的Leader,如果再次出现节点挂掉,按照 isr 中存活的,AR 中排序顺序选举。

2. 故障处理机制

数据写入broker时,有两个参数标记每个节点上的数据传输进度。

  • HW(High Watermark):所有副本中,最小的LEO的位置。
  • LEO(Log End Offset):每一个副本中最后一个offset,即副本最后一个数据的位置。
1. Follower故障
  • 一个follower挂掉之后,会被临时踢出ISR队列。其他正常工作的Leader和Follower继续传输数据。
  • 挂掉的Follower恢复之后,会读取本地的挂掉之前记录的HW,并将log文件中高于HW的数据全部截掉,重新从本地的HW位置开始,从Leader备份数据。
  • 当Follower的LEO高于该分区的HW后,重新加入ISR队列。
2. Leader故障
  • Leader挂掉之后,会被临时踢出ISR队列,通过Controller选举出新的Leader。
  • 数据会从新Leader的LEO处还是接收数据,其余的follower会将高于新Leader的LEO的数据截掉,重新弄从Leader处同步数据。

注意:这种副本机制,只能保证数据的一致性,不能保证数据不丢失、不重复。数据不丢失、不重复跟ACK的等级设置有关。

五、 文件存储机制

1. 文件存储格式

数据由生产者推送到Topic中存储,由Leader和Follower进行接收和备份。文件以Log文件的形式存储,并且将每个partition的数据又分为多个Segment,每个Segment存储1GB的数据。Segment中的log文件存储真实数据,生产者产生的数据被不断地追加到log文件末端;index文件存储索引。这种机制叫做分片和索引机制。

Segment= .log文件 + .index文件 + timeIndex文件 + 其他文件

2. 如何定位目标文件的位置

  • 同一个Segment中的index文件和log文件的文件名时一一对应的

  • index文件中记录两个值:offset(相对数据偏移量)、position(偏移量所处的位置)

    ​ index中存储的偏移量是相对偏移量,只是针对当前Segment中。绝对便宜量 = 相对偏移量 + index文件名中的数字索引

    ​ index存储的是稀疏索引,大约每向log文件中写入4KB的数据,才向index中写入一条。

index文件和log文件中的查找算法都是二分法。在index中找到目标数据的范围之后,会到log文件中查找目标索引的起点的position位置,再通过log文件中的baseoffset和lastoffset判断出目标数据的位置。

为什么index中存储的是相对的offset?

因为存储相对offset,每个文件中的数据量不会很大,节约磁盘空间。如果存储绝对offset,假设index中记录了上亿条数据,那么offset的值会累加到很大,不便于存储和快速检索。

4. 文件清理策略

  • kafka默认保留最近7天的日志文件,超过7天的就会被删除。
  • 检查日志是否过期的周期,默认是5分钟
1. delete删除

直接删除数据可以设置为是基于时间删除还是基于文件大小删除。默认情况下,开启基于时间删除文件,关闭基于文件大小删除文件

只有当一个Segment中的文件全部过期,才会将该Segment删除,只有一部分过期数据,不会立即删除。

2. compact压缩

数据存储时按照K-V键值对形式存储,将相同Key的值压缩,并只保留最后一条Key对应的数据,将数据量变少。

例子:k1-1;k2-1,k3-1,最后只保留k3-1

5. Kafka如何实现高效读写

  1. Kafka是分布式的集群,可以实现分布式读写数据;
  2. 读数据采用稀疏索引机制,可以快速定位要消费的数据;
  3. Kafka写入数据是顺序写磁盘
  4. 零拷贝技术:Kafka的数据加工处理操作,全部由Kafka生产者执行,broker不需要关心如何存储数据。
  5. 页缓存技术:类似于电脑的页缓存技术,Kafka提前将数据写入操作系统底层的PageCache中,查找数据时先从缓存中查找,缓存中没有再去集群中查找。

六、 Kafka的消费者组

1. Kafka消费者组的消费方式

  • Kafka消费者的消费方式是Pull(拉取)模式,根据消费者的性能,自行从队列中拉取数据。

  • topic中有多个分区时,会按照消费者和分区的数量进行平均分配

    ​ 例子:topic有四个分区,组内两个消费者,则组内一号消费者消费前两个,二号消费后两个。

    topic有5个分区,组内两个消费者,一号消费前三个,二号消费后两个。

  • 消费者组进行消费时,_consumer_offsets中记录每一个消费者组的断点续传位置。如果某个消费者挂了,重启之后会继续从断点续传的位置开始读数据。这样不会丢失数据,但是如果消费者组的ID改变,数据也会发生改变。

2. 消费者组初始化流程

  • 消费者组启动时会选出coordinator辅助组的初始化和分区分配。
  • coordinator = groupid的hashcode值 % _consumer_offsets的分区数量。
  • coordinator的值对应是哪个_consumer_offset的分区号,该分区在哪个broker上,就选择哪个节点作为这个消费者组的老大。该消费者组下的所有消费者提交offset时,都向该分区提交。
1. 消费者组工作流程
  1. 每个消费者都向coordinator发送JoinGroup请求。之后选出一个消费者组的Leader。
  2. coordinator将要消费的topic的情况发送给leader消费者,Leader消费者定制消费方案,并将方案返回给coordinator。
  3. coordinator得到方案后再将消费方案发送给各个组内消费者。
  4. 每个消费者跟coordinator默认3秒保持一次心跳,如果心跳时长超过45秒,或者消费数据时间超过5分钟,会触发消费再平衡。
2. 消费者工作原理

消费者组消费数据时,每个消费者都会创建自己的ConsumerNetworkClient客户端。消费者向客户端发送send请求,客户端又向Broker Leader发送send请求拉取数据。抓取数据后,数据会先存放到客户端内的消息队列中,消费者从队列中拉取数据进行消费。

  • 消费者拉取数据时按批次进行拉取。
  • 每批次拉取最小1字节的数据。
  • 每批次默认最多拉取50MB数据。
  • 如果始终没有满足拉取数据的最小值,默认每过500MS拉去一次数据。
  • 消费者从自己队列中,每次拉取数据默认是500条。
3. 分区分配策略

Range分配策略

将topic中的分区按照分区号进行排序,消费者也按照字母进行排序。通过分区数/消费者数的结果来决定每个消费者应该消费几个分区的数据。如果除不尽,那么余数是N,那么前N个消费者每个都会多消费1个分区的数据。

此种策略适合topic数量较少时使用,topic数量过多容易造成数据倾斜。

RoundRobin策略

针对集群中的所有topic和消费者,将所有的都罗列出来按照hashCode值进行排序。通过轮询算法为每个消费者分配消费数据的分区。

Sticky:粘性分区及再平衡

进行一次分区之前,会考虑到上一次的分配结果,会尽量少的调整分配资源。如果组内的消费者出现问题,会尽量保证原有的分配策略不改变。

真实场景中,不会单独的使用某一种分区分配策略,会组合进行使用。

3. 数据积压

怎样会造成数据积压问题

消费者的消费能力不足,或者下游的数据处理不及时(拉取数据/处理时间 < 生产速度),都会造成数据积压问题。

怎样解决数据积压问题?

消费者能力不足时,可以考虑增加topic的分区数,并同时增加消费者组内的消费者数量。将topic分区数和消费者数设置相同。必须同时满足上述两种条件。

如果是下游处理不及时:提高下游每批次拉取数据的数量。

如何提高Kafka的数据吞吐量?

生产者角度:增大仓库的默认大小,增大batch.size(批数据大小)和linger.ms(默认等待时间),将数据进行压缩传输。

消费者角度:增加消费者组内的消费者数量,提高每批次拉取数据的数量。

Broker集群角度:增加topic的分区数,提高并行生产、消费的效率。
题?**

消费者能力不足时,可以考虑增加topic的分区数,并同时增加消费者组内的消费者数量。将topic分区数和消费者数设置相同。必须同时满足上述两种条件。

如果是下游处理不及时:提高下游每批次拉取数据的数量。

如何提高Kafka的数据吞吐量?

生产者角度:增大仓库的默认大小,增大batch.size(批数据大小)和linger.ms(默认等待时间),将数据进行压缩传输。

消费者角度:增加消费者组内的消费者数量,提高每批次拉取数据的数量。

Broker集群角度:增加topic的分区数,提高并行生产、消费的效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值