【西瓜带你学Kafka | 第三期】Kafka从消息生产到集群管理的完整链路(文含图解)
Kafka 核心机制全解析生产者流程、消费模式与集群管理Kafka 的强大不仅在于能用更在于每个环节的设计都经过深思熟虑。这篇博客从一条消息的诞生到被消费再到集群如何自我管理带你完整走一遍 Kafka 的核心工作机制。文章目录Kafka 核心机制全解析生产者流程、消费模式与集群管理一、Kafka 中生产者运行流程完整流程二、Kafka 中的消息封装Batch 机制Batch 的控制维度效率与时效性的权衡三、Kafka 消息的消费模式Push 模式的问题Kafka 选择了 Pull 模式Pull 模式的缺点与解决方案四、Kafka 中消费者与消费者组的关系与负载均衡Consumer Group 机制消费者数量的最佳实践动态关系与 Rebalance心跳与协调者五、Kafka 如何实现负载均衡与故障转移负载均衡故障转移六、Kafka 中 Zookeeper 的作用七、Kafka 提供了哪些系统工具总结一、Kafka 中生产者运行流程一条消息从 Producer 发出到最终抵达 Broker中间经历了六个步骤。理解这个流程是掌握 Kafka 生产端调优的基础。完整流程1. 封装 ProducerRecord一条消息发过来首先会被封装成一个ProducerRecord对象。这个对象包含了目标 Topic、Partition可选、Key可选、Value消息体以及 Timestamp 等信息。// 构造一个 ProducerRecordProducerRecordString,StringrecordnewProducerRecord(order-topic,// 目标 TopicorderId-1001,// Key下单成功// Value);第一个 StringKey 的类型第二个 StringValue 的类型2. 序列化处理对 ProducerRecord 对象进行序列化将 Key 和 Value 转换为字节数组。可以使用 Kafka 内置的序列化器如 StringSerializer也可以自定义序列化逻辑。3. 分区处理序列化完成后对消息进行分区处理。这一步需要获取集群的元数据Metadata决定这条消息会被发送到哪个主题的哪个分区。分区策略就是上篇博客讲过的三级规则指定Partition → Key 哈希取余 → Round-Robin。点西瓜带你学Kafka跳转上期4. 写入缓存区分好区的消息不会直接发送到服务端而是放入生产者的缓存区RecordAccumulator。多条发往同一分区的消息会被封装成一个批次Batch默认一个批次的大小是16KB。5. Sender 线程获取批次Sender 线程是一个独立的后台线程启动以后会持续从缓存区里获取可以发送的批次。6. 发送到服务端Sender 线程把一个一个批次通过网络发送到对应的 Broker。【图片描述词】Kafka 生产者运行流程图从左到右依次为① 消息封装为 ProducerRecord → ② Serializer 序列化 → ③ Partitioner 分区旁边有一个虚线框标注获取集群 Metadata→ ④ 写入 RecordAccumulator 缓存区内部展示多个 Batch 按 Partition 分组排列→ ⑤ Sender 线程从缓存区取出 Batch → ⑥ 通过网络发送到 Kafka Broker。整体用流水线风格箭头连接各步骤主线程和 Sender 线程用不同颜色区分。// 完整的 Producer 发送示例PropertiespropsnewProperties();props.put(bootstrap.servers,localhost:9092);props.put(key.serializer,org.apache.kafka.common.serialization.StringSerializer);props.put(value.serializer,org.apache.kafka.common.serialization.StringSerializer);// 批次大小默认 16KBprops.put(batch.size,16384);//16*1024// 等待时间配合 batch.size 一起控制批次发送props.put(linger.ms,10);KafkaProducerString,StringproducernewKafkaProducer(props);producer.send(newProducerRecord(order-topic,orderId-1001,下单成功),(metadata,exception)-{if(exceptionnull){System.out.printf(发送成功: topic%s, partition%d, offset%d%n,metadata.topic(),metadata.partition(),metadata.offset());}else{exception.printStackTrace();}});producer.close();注意看代码中的两个关键参数batch.size和linger.ms它们直接影响批次的行为二、Kafka 中的消息封装Batch 机制Producer 并不是来一条消息就发一条而是通过 Batch 的方式批量推送数据以此提高效率。Batch 的控制维度Kafka Producer 可以将消息在内存中累积到一定程度后作为一个 Batch 发送请求。Batch 的触发条件可以从三个维度进行控制维度参数示例值说明累计消息数量batch.size间接控制500 条消息条数达到阈值时触发发送累计时间间隔linger.ms100ms即使 Batch 未满超过等待时间也会发送累计数据大小batch.size64KBBatch 的字节数达到阈值时触发发送三个条件是或的关系——任何一个先满足Batch 就会被发送。效率与时效性的权衡通过增加 Batch 的大小可以减少网络请求和磁盘 I/O 的频次吞吐量会显著提升。但代价是单条消息的延迟会增加因为要等 Batch 凑够。追求高吞吐调大batch.size调大linger.ms追求低延迟调小batch.size将linger.ms设为 0来一条发一条具体参数配置需要根据业务场景在效率和时效性之间做权衡。三、Kafka 消息的消费模式Kafka 采用大部分消息系统遵循的传统模式Producer 将消息推送到 BrokerConsumer 从 Broker 获取消息。但 Consumer 从 Broker 获取消息这一步到底是 Push 还是 Pull这个选择直接影响系统的灵活性。Push 模式的问题如果采用 Push 模式Broker 主动推送消息给 ConsumerConsumer 难以处理不同速率的上游推送。快的 Producer 会把慢的 Consumer 压垮而 Broker 很难感知每个 Consumer 的实际处理能力。Kafka 选择了 Pull 模式Kafka 的 Consumer 采用 Pull 模式主动从 Broker 拉取数据。好处是Consumer 可以自主决定消费速率根据自身处理能力按需拉取Consumer 可以自主决定是否批量拉取灵活控制每次拉取的数据量Pull 模式的缺点与解决方案Pull 模式有一个天然缺点如果 Broker 没有可供消费的消息Consumer 会不断在循环中轮询直到新消息到达造成 CPU 空转。Kafka 的解决方案提供一个fetch.min.bytes参数让 Consumer 在没有新消息时阻塞等待直到有足够的新消息到达后才返回避免无意义的空轮询。PropertiespropsnewProperties();props.put(bootstrap.servers,localhost:9092);props.put(group.id,order-consumer-group);props.put(key.deserializer,org.apache.kafka.common.serialization.StringDeserializer);props.put(value.deserializer,org.apache.kafka.common.serialization.StringDeserializer);// 最少拉取 1 字节数据没有数据时阻塞等待props.put(fetch.min.bytes,1);// 最长阻塞等待时间 500msprops.put(fetch.max.wait.ms,500);KafkaConsumerString,StringconsumernewKafkaConsumer(props);consumer.subscribe(Collections.singletonList(order-topic));while(true){// poll 内部实现了 Pull 模式 阻塞等待ConsumerRecordsString,Stringrecordsconsumer.poll(Duration.ofMillis(1000));for(ConsumerRecordString,Stringrecord:records){System.out.printf(offset%d, key%s, value%s%n,record.offset(),record.key(),record.value());}}四、Kafka 中消费者与消费者组的关系与负载均衡Consumer Group 机制Consumer Group 是 Kafka 独有的可扩展且具有容错性的消费者机制。核心规则一个组内可以有多个 Consumer它们共享一个全局唯一的Group ID组内所有 Consumer 协调在一起消费订阅 Topic 内的所有 Partition每个 Partition 只能由同一个 Consumer Group 内的一个 Consumer 来消费Consumer订阅的是 Topic 的 Partition而不是 Message所以在同一时间点上订阅到同一个分区的 Consumer 必然属于不同的 Consumer Group。消费者数量的最佳实践消费者的数量通常不超过分区的数量且二者最好保持整数倍的关系。原因很简单如果 Consumer 数量超过 Partition 数量多出来的 Consumer 会处于空闲状态白白浪费资源。Partition 数Consumer 数效果33每个 Consumer 消费 1 个 Partition完美均衡32一个 Consumer 消费 2 个 Partition另一个消费 1 个343 个 Consumer 各消费 1 个 Partition1 个空闲动态关系与 RebalanceConsumer Group 与 Consumer 的关系是动态维护的当一个 Consumer 进程挂掉或卡住时该 Consumer 所订阅的 Partition 会被重新分配到该组内的其他 Consumer 上当一个新的 Consumer 加入到 Consumer Group 中时会从其他 Consumer 中分配出一个或多个 Partition 给这个新成员心跳与协调者为了维持 Consumer 与 Consumer Group 之间的关系Consumer 会周期性地发送heartbeat到Coordinator协调者。如果 heartbeat 超时或未收到 heartbeatCoordinator 会认为该 Consumer 已经退出该 Consumer 所订阅的 Partition 会被分配到同一组内的其他 Consumer 上这个过程称为Rebalance再平衡PropertiespropsnewProperties();props.put(bootstrap.servers,localhost:9092);// 指定 Consumer Groupprops.put(group.id,order-consumer-group);// 心跳间隔默认 3 秒props.put(heartbeat.interval.ms,3000);// 会话超时时间超过此时间未收到心跳则触发 Rebalanceprops.put(session.timeout.ms,30000);props.put(key.deserializer,org.apache.kafka.common.serialization.StringDeserializer);props.put(value.deserializer,org.apache.kafka.common.serialization.StringDeserializer);KafkaConsumerString,StringconsumernewKafkaConsumer(props);consumer.subscribe(Collections.singletonList(order-topic));五、Kafka 如何实现负载均衡与故障转移负载均衡负载均衡是指让系统的负载根据一定的规则均衡地分配在所有参与工作的服务器上从而最大限度保证系统整体运行效率与稳定性。Kafka 的负载均衡就是让每个 Broker 都有均等的机会为客户端生产者与消费者提供服务将负载分散到集群中的所有机器上。实现方式Kafka 通过智能化的分区领导者选举来实现负载均衡。它提供智能化的 Leader 选举算法可在集群的所有机器上均匀分散各个 Partition 的 Leader从而整体上实现负载均衡。因为所有的读写请求都由 Leader 处理所以 Leader 的分布是否均匀直接决定了集群负载是否均衡。故障转移Kafka 的故障转移是通过会话机制实现的每台 Kafka 服务器启动后会以会话的形式把自己注册到 Zookeeper 服务器上一旦服务器运转出现问题就会导致与 Zookeeper 的会话不能维持从而超时断连此时 Kafka 集群会选举出另一台服务器来完全替代这台服务器继续提供服务【图片描述词】分为上下两部分。上半部分标注正常状态3 个 Broker 都与 Zookeeper 保持会话连接用绿色实线表示各自持有不同 Partition 的 Leader。下半部分标注故障转移Broker 1 宕机用红色叉号标记与 Zookeeper 的连接断开用红色虚线表示Broker 1 上的 Partition Leader 被转移到 Broker 2 上用箭头标注Leader 重新选举Broker 2 变为新的 Leader 继续提供服务。六、Kafka 中 Zookeeper 的作用Kafka 是一个使用 Zookeeper 构建的分布式系统。Zookeeper 在 Kafka 中扮演着大管家的角色职责说明Broker 注册管理各 Broker 启动时在 Zookeeper 上注册由 Zookeeper 统一协调管理分区信息维护同一 Topic 的消息被分成多个分区并分布在多个 Broker 上这些分区信息及与 Broker 的对应关系由 Zookeeper 维护故障恢复如果任何节点失败可通过 Zookeeper 从先前提交的偏移量中恢复因为 Zookeeper 会做周期性提交偏移量工作Controller 选举集群中的 Controller 角色通过 Zookeeper 选举产生值得一提的是从 Kafka 2.8 开始引入了KRaft 模式目标是去除对 Zookeeper 的依赖让 Kafka 自己管理元数据。Kafka 3.3 已经将 KRaft 标记为生产可用这是 Kafka 架构演进的重要方向。七、Kafka 提供了哪些系统工具Kafka 自带了一些实用的系统工具虽然不算丰富但覆盖了运维中的关键场景工具用途Kafka 迁移工具有助于将代理从一个版本迁移到另一个版本降低版本升级的风险MirrorMaker将一个 Kafka 集群的镜像提供给另一个集群常用于跨数据中心的数据同步和灾备消费者检查工具对于指定的主题集和消费者组可显示主题、分区、所有者等信息方便排查消费进度和分配情况总结生产者流程消息经历封装 → 序列化 → 分区 → 缓存 → Sender 线程批量发送六步完成从 Producer 到 Broker 的旅程Batch 机制通过消息数量、时间间隔、数据大小三个维度控制批次在吞吐量和延迟之间做权衡消费模式Kafka 选择 Pull 模式Consumer 自主控制消费速率通过阻塞参数解决空轮询问题消费者组Partition 与 Consumer 的动态绑定通过 heartbeat Coordinator 实现 Rebalance负载均衡与故障转移Leader 均匀分散实现负载均衡Zookeeper 会话机制实现故障自动转移Zookeeper集群的元数据管家管理 Broker 注册、分区分配、故障恢复等核心信息Kafka 的每一个环节都在追求一个目标用最少的资源开销实现最高的吞吐和最强的可靠性。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2568961.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!