Kafka个人总结

1 Kafka是什么?

简单来说,Kafka就是一个消息系统/消息中间件,虽然Kafka新增了流处理(统计分析计算)的新特性,但是我们一般还是使用Spark,Flink等作为流处理的软件.

2 Kafka的作用是什么?

1)应用解耦:多个应用可通过消息队列对消息进行处理,应用之间相互独立,互不影响.
图例:在这里插入图片描述

2)异步处理:相比于串行和井行处理,异步处理可以减少处理的时间.
在这里插入图片描述

3)流量削峰:流量高峰期,可通过消息队列来控制流量, 避免流量过大而引起应用系统崩溃.

4)消息通信:实现点对点消息队列,或者多对多的消息队列.

3 Kafka的生产,消息存储,消费流程细节

1) 生产者流程细节

1.生产者发送消息到Kafka集群使用的是推送模式

2.生产者发送消息到Kafka需要连接到任意一台Kafka节点

3.每一条消息会被封装为一个Record记录对象,里面可以包含主题、分区(可选)、key(可选)、value

4.分区规则:

  • 没有key,用的是轮询

  • 有key,没有指定分区用的默认的分区器defaultPartitioner,底层使用hash

  • 有key,指定分区,那么就是指定的分区号----优先级最高

  • 可以自定义分区器

    补充:

    key可以作为消息/记录的一个业务上的标识(但不是唯一的,也就是不同的value的key可以重复的)

    value才是消息的真正的内容

5.分区的作用:

  • 提高读写效率-------一个主题不同的分区落在不同的节点上,可以并行的生产/消费主题中的消息,否则将会生产/消费的请求到一个节点上.
  • 便于集群扩容(机器扩容时增加机器同时增加分区数)--------如果没有分区,我们一台机器磁盘空间满了之后,虽然可以再添加机器来进行扩容,但是原来的机器磁盘空间依然是满的,有了分区之后,我们可以将原来的机器中的主题分为2个分区,分别负载到2台不同的机器上,这样原来的机器也就腾出了一半的磁盘空间.
  • 方便消费者负载均衡(消费者数量==分区数)--------如果没有分区,一个消费者将会消费一个主题中所有的消息,有了分区之后,可以让消费者数量和分区数量一一对应实现负载均衡,即提升了效率,也不会让某个消费者没活干.

6.每一条消息/记录发送到Kafka的时候会先到缓冲区, 然后以batch的形式发送到Kafka,落入磁盘是以顺序写的方式追加到磁盘文件中的!-------Kafka写入消息只能追加!

7.每一条消息写到各个分区之后会有一个消息的唯一标识:offset

  • offset是区内有序, 全局无序的(区内有序,区间无序)----kafka消息的局部有序性

2) Broker存储流程细节

1.消息到底Kafka之后会根据分区规则进入到指定的分区(分区是分散各个节点)

2.分区在物理层面体现就是文件夹

3.分区中又会分为多个segment文件段,每个文件段由.log数据文件和.index索引文件组成

.index文件中存储了每个偏移量的消息对应.log文件中的第几行,当我们对消息进行查询,会首先用二分查找法查询对应偏移量的消息在.log文件中的位置,然后再根据查询到的位置直接去.log中查询消息.

图解:

在这里插入图片描述

二分查找法不管数据量多大,查询的次数都不会增加太多,效率非常高

4.查询的时候可以根据offset去.index中的索引找到.log中对于的消息位置

5.数据不是一直在kafka中存储,会有删除策略

  • 基于时间:log.retention.hours=168

  • 基于大小:log.retention.bytes=1073741824

    基于时间的删除:一个主题的每个分段中都有一个 timestamp 记录这个分段最后写入的消息的时间,当这个时间已经超过7天,就会将这个分段直接删除.

    基于大小的删除:当一个主题大小超过指定阈值后,就会将写入时间最早的分段删除.

6.数据越来越多其实也并不会对kafka的读写效率产生太大的影响,因为

  • 写是各分区顺序写/追加写
  • 读是各分区内根据offset对.index文件进行二分查找Olog(N)

3) 消费者流程细节

1.消费者从Kafka中消费消息使用的是拉取模式

2.消费者连接上Kafka集群任意一台节点之后,需要指定要订阅的主题或主题+分区

3.消费从哪个偏移量开始消费,由auto.offset.reset决定

  • earliest:如果有offset提交记录,就从记录位置开始消费,没有则从最早的位置开始消费
  • latest:如果有offset提交记录,就从记录位置开始消费,没有则从最后/新的位置开始消费
  • none:如果有offset提交记录,就从记录位置开始消费,没有则报错

4.消费者消费数据之后需要提交offset偏移量,可以有如下方式

  • 自动提交:按照固定的时间间隔进行提交(提交到默认主题__consumer_offsets)
  • 手动提交:按照自定义规则进行提交
  • 注意:提交的信息包括:哪个消费者组消费哪个主题的哪个分区的哪个偏移量了

5.消费者组内可以有多个消费者(如果没有设置消费者组会有默认的消费者组名称,但建议手动设置,方便维护),某一条消息只可以被同一个消费者组内的一个消费者消费,但可以被其他组的消费消费

6.消费者组中的消费者数量建议等于分区数,这样效率可以最大化.

Kafka原理图解:

在这里插入图片描述

4 关于Kafka中一些问题

1)同步推送消息和异步推送消息

无论是kafka内部是同步还是异步推送消息,使用kafka,都会将原来的流程从同步变为异步模式,只需要将消息传入kafka即可,不需要再等待数据库或者下个组件的响应.

当使用异步模式推送消息时,会先将消息写入缓冲区内,当缓冲区的大小超过一定阈值后,就不允许继续写入数据了,当缓冲区内的数据大小达到一个Batch或者写入后时间超过25ms后,就会将数据写入到磁盘中去.

2)为什么zookeeper不适合存储offset数据

因为zookeeper本身就是一个小文件存储系统,不适合进行大量读写操作,zookeeper本身所有节点都可以进行读,而只有主节点可以写,如果有同时间内有大量写操作的话,zookeeper需要将大量数据时时同步给从节点,造成zookeeper同步压力过大,而Kafka只有主副本可以读写,从副本只负责同步,就不存在这个问题了.

3)消费者API中的问题

1 poll()方法只是拉取消息,并不是消费消息.

2 ConsumerRecords<String, String> records = consumer.poll(1000)方法一次性可以拉取多条或者一条消息,因为我们编写的代码是单线程,所以只有初次拉取消息的时候会一次性拉取多条消息,后续都是我们每生产一条消息,poll方法就拉取一条,但是实际生产环境中,都是多线程一次性生产一个主题的多个分区的消息,所以poll方法都是一次性拉取多条消息.

3 无论是自动提交还是手动提交,都是先消费后提交,自动提交也是去确认消费完成之后,才会提交读到的偏移量,这样虽然可能会造成多读的情况发生,但是最起码可以保证数据不丢失,我们后续可以通过布隆过滤器或者redis等方式去重即可.

4)拦截器中的问题

onSend()方法 生产者每推送一次消息执行一次
onAcknowledgement()方法,消息每发送成功或者失败执行一次
close() 方法.当生产者停止生产消息(producer.close())时,执行一次

5)kafka和zookeeper的关系

kafka依赖于zookeeper进行集群管理,故障转移,kafka中有哪些主题,主题又分为哪些分区,这些分区都落在哪些节点上,都存在于zookeeper当中,但是新版本以后,offset偏移量不再存在zookeeper当中,而是存在Kafka的默认主题__consumer_offsets 当中,其中记录了哪些消费者组消费到哪个分区的哪个皮偏移量了

6)消费者组的作用

消费者组主要是方便对消费者进行分组管理的,我们往往只需要指定消费者组,至于里面的消费者数量和消费消息时每个消费者消费哪个分区,都由kafka自己分配决定.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章