- kafka属于消息引擎系统, 主要用于系统间传输消息, 可以做到系统业务上的解耦, 缓冲系统上下游瞬时突发流量,使其更平滑(削峰填谷)。
kafka系统里各种概念
- 消息:Record。Kafka 是消息引擎嘛,这里的消息就是指 Kafka 处理的主要对象。
- 主题:Topic。主题是承载消息的逻辑容器,在实际使用中多用来区分具体的业务。
- 分区:Partition。一个有序不变的消息序列。每个主题下可以有多个分区。
- 消息位移:Offset。表示分区中每条消息的位置信息,是一个单调递增且不变的值。
- 副本:Replica。Kafka 中同一条消息能够被拷贝到多个地方以提供数据冗余,这些地方就是所谓的副本。副本还分为领导者副本和追随者副本,各自有不同的角色划分。副本是在分区层级下的,即每个分区可配置多个副本实现高可用。
- 生产者:Producer。向主题发布新消息的应用程序。
- 消费者:Consumer。从主题订阅新消息的应用程序。
- 消费者位移:Consumer Offset。表征消费者消费进度,每个消费者都有自己的消费者位移。
- 消费者组:Consumer Group。多个消费者实例共同组成的一个组,同时消费多个分区以实现高吞吐。
- 重平衡:Rebalance。消费者组内某个消费者实例挂掉后,其他消费者实例自动重新分配订阅主题分区的过程。Rebalance 是 Kafka 消费者端实现高可用的重要手段。
-
kafka相关概念图
重点: kafka里的副本针对的是分区来做的, 副本不提供对外的服务,只记录消息数据,kafka通过对topic分区来实现消息系统的负载。
其他
![](https://i-blog.csdnimg.cn/blog_migrate/bafceedc16f2087fb2ff5cef6bb33870.png)
kafka版本
生产者
![](https://i-blog.csdnimg.cn/blog_migrate/986d9c383b26be5fd806b483659d097d.png)
生产者发送数据流程
- 如果想指定生产者发消息的分区策略, 可以在生产端配置参数: partitioner.class, 对应的class需要实现: org.apache.kafka.clients.producer.Partitioner 这个接口。
- 生产者默认的分区策略是根据消息指定的key发送到指定的分区(这也是生产者保证消息有序性的要点),如果消息没有指定key, 采用的是轮询策略。具体可以看 DefaultPartitioner这个类的实现
- 为了提高生产者的发送效率, 在发送消息的时候, 可以对要发送的消息做压缩处理。配置参数为: "compression.type"。 启用压缩需要在生产端的cpu资源有多余的情况下(一般业务系统都是I/O密集型的)。
- kafka发送的消息, 在发送的时候, 会把多条消息放在一起, 组成消息集合,在Broker端存的消息是发送端发送的"消息集合"
- 避免在Broker配置compression.type, 防止Broker端配置的compression.type跟生产端配置的不一样, 如果配置的不一样, Broker需要对消息集合做解压缩, 让后用Broker配置的压缩算法重新压缩消息, 对Broker的性能有极大的影响。
- 解压缩发生在Consumer端, 压缩算法在消息集合里。
- 压缩算法的对吧吞吐量方面:LZ4 > Snappy > zstd 和 GZIP;而在压缩比方面,zstd > LZ4 > GZIP > Snappy。
- 发送消息的时候, 一定要用通过回调方法验证消息是否发送成功, 不然发送端有可能会有丢消息的风险。
- 设置 retries 为一个较大的值,当出现网络的瞬时抖动时,消息发送可能会失败,此时配置了 retries > 0 的 Producer 能够自动重试消息发送,避免消息丢失。
生产端TCP连接相关
- KafkaProducer 实例创建时启动 Sender 线程,从而创建与 bootstrap.servers 中所有 Broker 的 TCP 连接。
- KafkaProducer 实例首次更新元数据信息之后,还会再次创建与集群中所有 Broker 的 TCP 连接。
- 如果 Producer 端发送消息到某台 Broker 时发现没有与该 Broker 的 TCP 连接,那么也会立即创建连接。
- 如果设置 Producer 端 connections.max.idle.ms 参数大于 0,则步骤 1 中创建的 TCP 连接会被自动关闭;如果设置该参数 =-1,那么步骤 1 中创建的 TCP 连接将无法被关闭,从而成为“僵尸”连接。
消费者
![](https://i-blog.csdnimg.cn/blog_migrate/c67d87e1665447fc060e97fd8d44fb04.png)
消费者总体工作流程
![](https://i-blog.csdnimg.cn/blog_migrate/7ee512dc3cb85a82b8ef99914b368545.png)
消费者初始化流程
![](https://i-blog.csdnimg.cn/blog_migrate/f4672925044d7e8c98a98ce4c20b2609.png)
消费者组消费详细流程
- Consumer分区的分配策略是在消费端来处理的, 并非在Broker端做的分配方案,
- kafka中消费者组是一个很重要的概念, 消费者通过Group_Id来标识自己属于那一个消费者组, 消费者组整体消费某一个Topic, 每个分区只会有一个消费者组的消费者来消费。
- Consumer端有个参数enable.auto.commit,把它设置成false,并采用手动提交位移的方式。
- partition.assignment.strategy:消费者分区分配策略,默认策略Range+CooperativeSticky。Kafka可以同时使用多个分区分配策略。可以选择的策略包括:Range、RoundRobin、Sticky、CooperativeSticky
- 注意消费端如果掉线了, 或者执行的任务过程, 会导致消费端触发“重平衡”, 重平衡是很重的操作, 需要尽量避免
- __consumer_offsets 主题里面采用 key 和 value 的方式存储数据。key 是group.id+topic+分区号,value 就是当前 offset 的值。每隔一段时间,kafka 内部会对这个 topic 进行compact,也就是每个 group.id+topic+分区号就保留最新数据。
- Consumer offset是很重要的, 可以参考这篇文章: https://blog.csdn.net/warybee/article/details/121990020
Broker端
![](https://i-blog.csdnimg.cn/blog_migrate/c735956d0b2bffc6f3c39a7793b8713a.png)
Zookeeper中存储的Kafka 信息
- 设置 unclean.leader.election.enable = false,它控制的是哪些 Broker 有资格竞选分区的 Leader。如果一个 Broker 落后原先的 Leader 太多,那么它一旦成为新的 Leader,必然会造成消息的丢失。故一般都要将该参数设置成 false,即不允许这种情况的发生。
- 设置 replication.factor >= 3, 最好将消息多保存几份,毕竟目前防止消息丢失的主要机制就是冗余
- 设置 min.insync.replicas > 1, 控制的是消息至少要被写入到多少个副本才算是“已提交”。设置成大于 1 可以提升消息持久性。在实际环境中千万不要使用默认值 1。
- 确保 replication.factor > min.insync.replicas。如果两者相等,那么只要有一个副本挂机,整个分区就无法正常工作了。我们不仅要改善消息的持久性,防止数据丢失,还要在不降低可用性的基础上完成。推荐设置成 replication.factor = min.insync.replicas + 1。