Kafka核心原理之生产端

【kubeEdge】离线部署 根据k8s的这个规则,可以将节点通过 label 的方式进行分组,比如将某几个节点都打上标签为 name=edge,当调度应用到 edge 节点时,会找到 label 为 edge 的所有节点,根据设置的副本数,将应用启动起来,如果设置的副本数超过了设置 edge 标签的节点数,则多出的将会显示 pending 状态,从而无法启动。清除 keadm init 或 keadm join 造成的影响均可使用 keadm reset,这个操作会删除 /etc/kubeedge 下的文件,如有需要请提前备份。 阅读详情

生产端

生产端采用异步方式发送消息,消息发送过程主要涉及两个线程和一个消息缓冲区。

主线程

主线程包含消息格式(ProducerRecord)、拦截器、序列化器、分区器等组件。

获取Topic元数据信息

生产端获取元数据流程,如图所示:

主要步骤:

  • 1)生产端主线程调用KafkaProcduer.send()方法发送消息时,如果消息记录指定的Topic中分区数为空或者分区值不为空但大于Topic的分区总数,则触发拉取元数据标识并唤醒Sender线程调用元数据拉取请求进行元数据拉取,主线程同步阻塞等待元数据更新。
  • 2)Sender线程通过元数据更新组件(NetworkClient.DefaultMetadataUpdater)向集群中最空闲的Broker发送获取元数据请求拉取最新的元数据信息,获取成功(失败会一直重试直到成功)后更新元数据版本号,并唤醒主线程执行后续逻辑。

参数:

  • metadata.max.age.ms:生产者缓存元数据时长,默认为5分钟。

ProducerRecord

ProducerRecord对象可以声明主题(Topic)、分区(Partition)、键(Key)以及值(Value)等属性,其中主题和值必须声明,分区和键可以不用指定。

拦截器(可选)

Kafka拦截器分为生产者拦截器和消费者拦截器。

  • 生产者拦截器允许在消息发送前以及Producer回调逻辑前植入拦截器逻辑。
  • 消费者拦截器允许在消费消息前以及提交位移后植入拦截器逻辑。

这两种拦截器都支持拦截器链的方式,即:可以将一组拦截器组成一个拦截器链,按照添加顺序依次执行拦截器逻辑。

生产者拦截器接口为org.apache.kafka.clients.producer.ProducerInterceptor,其定义的方法包括:

  • onSend(ProducerRecord):该方法封装进KafkaProducer.send()方法中(即:运行在用户主线程中),Producer确保在消息被序列化和计算分区前调用该方法。用户可以在该方法中对消息做任何操作,但最好不要修改消息所属的Topic和分区,否则会影响目标分区的计算。
  • onAcknowledgement(RecordMetadata, Exception):该方法会在消息被应答之前或消息发送失败时调用,并且通常是在Producer回调逻辑触发之前。onAcknowledgement运行在Producer的IO线程中,因此不要在该方法中放入很重的逻辑,否则会拖慢Producer的消息发送效率。
  • close:关闭Interceptor,主要是执行一些资源清理工作。

序列化器

创建ProducerRecord时,必须指定序列化器,kafka默认提供了StringSerializer和IntegerSerializer、ByteArraySerializer(默认值)等序列化器,推荐使用序列化框架Avro(推荐)、Thrift、ProtoBuf等,不推荐自己创建序列化器。

分区器

Kafka中的每个Topic包含多个分区,发送消息时,如果在ProducerRecord对象中指定了partition参数值,则将消息发送到partition参数值对应的分区,否则需要按照分区器指定的策略将消息发送到目标分区,分区策略有:

  • 黏性分区策略(2.4.0版本后默认值):既没有partition值又没有key值的情况下,Kafka采用Sticky Partition(黏性分区器),会随机选择一个分区,并尽可能一直 使用该分区,待该分区的batch已满或者已完成,Kafka再随机选一个分区进行使用(和上一次的分区不同)。
  • 轮询(2.4.0版本前默认值):指的是在没有指明partition值也不存在Key值的情况下,通过先产生随机正数,之后在该数上自增的方式产生一个数,并使用该数与Topic的分区数进行取余返回一个分区值,即:轮询。
  • 按消息键保序:指的是在没有指明partition值但存在Key值的情况下,使用该Key的hash值与Topic的分区数进行取模返回一个分区值。

此外,用户可以根据需要自定义分区策略,自定义分区器需要实现org.apache.kafka.clients.producer.Partitioner接口。

Sender线程

Sender线程是一个守护线程,主要作用是从消息缓冲区抽取消息发送给Broker。Sender线程实现了Runnable接口,主要业务逻辑在run()方法中实现,处理流程如图所示:

处理步骤:

  • 1)从消息缓冲区(RecordAccumlator)中抽取达到发送条件的消息(若存在无路由信息的Topic,则会向Broker发送更新元数据请求),按照K-V格式存储到变量batches(Map<Integer, List<ProducerBatch>>:Key为BrokerId,Value为批次集合)中,注意:抽取后的ProducerBatch将不能再追加消息。
  • 2)将抽取后的消息放入待发送的消息批次inFlightBatches(Map<TopicPartition, List<ProducerBatch>>,Key为Topic+Patition,Value为批次集合)中,并从inFlightBatches和RecordAccumlator.batches(即:RecordAccumlator中所有批次)中筛选出已过期(超时)的批次,返回发送失败给生产端。
  • 3)将剩余待发送的消息批次inFlightBatches根据BrokerId构建发送请求(ClientRequest),调用NetworkClient#send(ClientRequest request, long now)方法构建inFlightRequest对象,将inFlightRequest对象加入到inFlightRequests集合中,并调用Selector.send()方法将Send和对应的KafkaChannel进行绑定,保存到NetworkSend中。
  • 4)调用NetworkClient#poll()方法将消息发送给Broker,并向生产端返回消息发送结果和元数据信息。

消息缓冲区(RecordAccumulator)

RecordAccumlator是记录收集器,收集记录到MemoryRecords(多个消息的集合)的队列中。它的主要作用是缓存消息以便Sender线程可以批量发送,从而减少网络传输的资源消耗,提升性能。

RecordAccumulator内存模型

RecordAccumlator通过一个ConcurrentMap(数据结构:CopyOnWriteMap)记录Topic、Partition、ProducerBatch(消息批次)之间的关系,其中每个分区对应一个双端队列(Deque),用于存储消息批次(ProducerBatch)。

ConcurrentMap<TopicPartition, Deque<ProducerBatch>> batches;

如图所示:

图中:

  • RecordAccumlator默认大小为32M,可以通过生产端参数buffer.memory进行设置。如果RecordAccumlator内存已满,调用append()追加新的消息时将被阻塞,除非显示的设置消除该限制。
  • RecordAccumlator内部有一个BytePool缓冲池,用于实现对ByteBuffer的复用,但只是针对特定大小的ByteBuffer进行管理。ByteBuffer的大小可以通过生产端参数batch.size进行设定,默认值为16K。

RecordAccumlator主要流程如图所示:

处理逻辑:

  • 1)生产端通过doSend()方法向消息缓冲区(RecordAccumlator)发送消息。
  • 2)消息经过拦截器处理后进行序列化,根据分区策略调用RecordAccumlator.append()方法向指定分区对应的双端队列尾部追加消息。
  • 3)追加消息时,先用synchronized对双端队列加锁,获取双端队列中最后一个批次数据,如果该批次数据不为空且该批次空间足够存储该消息,则追加该消息到批次中,如果该批次空间不足以存储该消息,则根据消息大小创建一个新的批次进行存储,即:如果消息大小未超过可复用批次大小(默认值16K),则复用BufferPool中闲置的批次进行存储,否则根据消息大小创建自定义批次进行存储,最后将该批次追加到双端队列的队尾(Sender线程从队首开时抽取)。
  • 4)返回消息追加结果。

消息发送流程

生产端消息发送流程,如图:

处理步骤:

  • 1)生产端通过配置的properties属性值获取Broker连接信息。
  • 2)生产端将消息封装为ProducerRecord对象,调用kafkaProducer.send()方法向指定的Topic发送消息,消息经过拦截器处理后进行序列化,根据分区策略发送到消息缓冲区(RecordAccumlator)中按批次进行存储。
  • 3)Sender线程从消息缓冲区中抽取已达到发送条件的消息批次,按格式组装成待发送消息批次。
  • 4)从待发送的消息批次和消息缓冲区中所有批次中筛选出已过期(超时)批次,返回发送失败给生产端。
  • 5)将剩余待发送的消息批次inFlightBatches根据BrokerId构建发送请求(ClientRequest),调用NetworkClient#send(ClientRequest request, long now)方法构建inFlightRequest对象,将inFlightRequest对象加入到inFlightRequests集合中,并调用Selector.send()方法将Send和对应的KafkaChannel进行绑定,保存到NetworkSend中。
  • 6)调用NetworkClient#poll()方法将消息发送给Broker,并向生产端返回响应结果。

注意:

  • NetworkSend是对NIO中写Buffer的封装,用来缓存发送的数据。
  • NetworkReceive是对NIO中读Buffer的封装,用来缓存接收的数据。

生产者线程安全问题

Kafka生产者是线程安全的,可以在多个线程中共享一个Kafka生产者实例。Kafka生产者内部使用了一些同步机制来保证线程安全,例如:生产端发送消息时,每个Topic分区在消息缓冲区中对应一个双端队列,多个线程向同一个Topic的同一个分区中追加消息时,通过synchronized(同步锁)对双端队列加锁,保证线程安全。

第一百三十九回 介绍三个BLE包 本章回中主要介绍了Flutter中BLE的概念和操作方法,主要介绍了三个BLE包的功能和差异,以方便大家在BLE操作中选择不同的包。 阅读详情

相关推荐

从零开始VCS+Verdi 安装过程

从零开始VCS+Verdi 安装及破解过程 主要参考:VCS+Verdi 安装及破解过程(CentOS7)-----FPGA开发 1. 安装文件结构 –vcs-mx_vL-2016.06 –verdi_vL-2016.06-1 –scl_v11.9 #此程序统一管理license等破解文件 –SynopsysInstaller.rar #此程序用于安装以上3个程序 –sc...

Ztrans的博客 2万+

探究:kafka生产者/消费者与多线程安全

Kafka生产者是线程安全的,可以在多个线程中共享一个Kafka生产者实例。这是因为Kafka生产者实例内部使用了一些同步机制来保证线程安全,例如使用了线程安全的队列来缓存消息,使用了同步锁来保护共享资源的访问等。同时,Kafka生产者的send()方法是非阻塞的,可以在多个线程中并发调用,不会阻塞线程。Kafka生产者还提供了异步发送和同步发送两种发送方式,可以根据实际需求选择不同的发送方式。

JaweG 5273

ADAS系统架构与核心功能解析:从感知到执行的智能驾驶方案

高级驾驶员辅助系统(ADAS)是现代汽车智能化的核心技术,其本质是通过传感器融合、算法决策与车辆控制,构建一个“感知-决策-执行”的闭环系统。在技术原理上,ADAS依赖摄像头、毫米波雷达、激光雷达等多源传感器进行环境感知,并通过深度学习模型与融合算法(如卡尔曼滤波)构建精准的环境模型。其技术价值在于提供主动安全冗余与驾驶舒适性,核心应用场景包括自动紧急制动(AEB)、自适应巡航(ACC)及车道保持辅助(LKA)等。随着传感器成本下降与域控制器算力提升,ADAS正从高端配置向主流车型快速普及,并逐步向高阶导航

weixin_31062533的博客 420

Kafka 深度详解

核心组件包括 Producer(生产者,发送消息)、Consumer(消费者,消费消息)、Broker(服务节点,存储和处理消息)、Topic(主题,消息逻辑分类)、Partition(分区,物理存储单元)、Replica(副本,保障高可用)、Controller(控制器,管理集群元数据)。:Topic 是消息的逻辑分类,Partition 是 Topic 的物理存储单元,一个 Topic 可分为多个 Partition;:Offset 是消息在 Partition 内的唯一标识,是一个自增整数;

xiaolyuh的专栏 4096

LaTeX双栏浮动结构实战:用dblfloatfix解决跨栏图表排版难题

本文深入探讨了LaTeX双栏浮动结构在学术论文排版中的常见问题,特别是IEEE会议论文中的跨栏图表定位难题。通过介绍dblfloatfix包的整合解决方案,帮助用户实现精准的底部定位和浮动顺序保持,提升排版效率与质量。

weixin_30872499的博客 444

C语言新手必练:10个实战小项目带你快速上手(附完整代码)

本文为C语言初学者精选10个实战项目,从基础的温度转换器到高级的迷宫求解算法,涵盖输入输出、条件判断、循环控制、数组操作等核心知识点。每个项目配有完整代码和详细解析,帮助新手通过实践掌握编程思维,特别适合刚学完语法但缺乏实战经验的学习者。

weixin_29208077的博客 750

Kafka优雅源码设计2-KafkaProducer如何实现线程安全

1. 背景知识 1.1 线程安全的定义 我们可以看下《Java并发编程实战》在2.1章节中的定义: 当多个线程访问某个类时,这个类始终都能表现出正确的行为,那么就称这个类是线程安全的。 我们常用synchronized或者Lock来实现线程安全的代码, 1.2 线程安全的级别 1.3 Java语言中如何实现线程安全 1.4 final关键字 2. KafkaProducer部分源码 public class KafkaProducer<K, V> implements Producer<

百里长庭的博客 3363

STM32CubeMX最新版下载安装全攻略(附官网访问问题解决方案)

本文提供了STM32CubeMX最新版的详细下载与安装指南,并针对国内开发者常见的官网访问缓慢、注册验证邮件延迟等问题,给出了实用的解决方案和备选策略。通过清晰的步骤解析,帮助用户快速部署这一强大的STM32图形化配置工具,从而高效启动嵌入式开发项目。

weixin_28256233的博客 196

Kafka生产者原理深度解析

本文深入解析Kafka生产者的核心原理,包括消息发送流程和关键组件。Kafka生产者通过主线程和Sender线程协同工作,消息经过拦截器预处理、序列化转换、分区器分配后,由消息累加器批量暂存,最终由Sender线程发送。文章详细介绍了拦截器的扩展机制、序列化实现方式、分区策略选择、消息批量处理原理以及ACK应答机制如何保障数据可靠性(0/1/all三种级别)。通过合理配置这些组件,开发者可以在性能和可靠性之间取得平衡,满足不同业务场景需求。

Nicky's blog 1694

把 ABAP SQL 窗口函数讲透:从 OVER 到 LEAD、RANK 与累计分析

ABAP SQL窗口函数在不丢失明细记录的前提下,为每行数据提供组内统计和排名功能。它通过OVER子句定义计算窗口,支持三类函数:聚合型(AVG/SUM等)、排名型(ROW_NUMBER/RANK等)和取值型(LEAD/LAG)。相比GROUP BY会合并多行数据,窗口函数保留原始记录同时附加计算结果,特别适合需要保留明细又要展示统计信息的业务场景,如销售排名、客户分层分析等。语法核心是OVER子句,通过PARTITION BY分组,ORDER BY排序,可灵活定义计算范围。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1274

C# MES通信从入门到精通(10)——C#使用HTTP的Post和Get方法和Mes系统通信

本文详细介绍了如何利用C#完成与HTTP协议的MES系统进行通信,通过POST和GET方法实现与MES系统的交互,由高级工程师的实战经验总结,实属C#与MES通信领域的葵花宝典!

qq_34059233的博客 3420

鉴权kafka生产端(SCRAM)

前言 kafka官网关于sasl_scram 鉴权Kafka消费端配置 创建SCRAM Credentials 依赖zk,需要先启动zk,然后在zk中创建存储SCRAM 凭证: cd kafkacluster/kafka_2.11-1.1.1 bin/kafka-configs.sh --zookeeper zkIP1:2181,zkIP2:2181,zkIP3:2181/lxgkafka --alter --add-config 'SCRAM-SHA-256=[password=admin-secr

长臂人猿的博客 2837

C++幂运算全解析:std::pow()函数详解与实战指南

本文详细介绍了C++标准库中的std::pow()函数,包括其基本用法、数学定义和多种重载形式。重点分析了该函数在科学计算、图形处理等领域的实际应用,并提供了性能优化方案如快速幂算法和预计算表。文章还探讨了精度控制、错误处理等关键问题,最后通过一个完整计算器实现展示了综合应用。std::pow()作为基础数学函数,合理使用能显著提升计算效率和代码可靠性。

专注现代C++实战,从核心语法到高性能编程,助力开发者深入掌握系统级编程精髓。 340

waitpid最后以一个参数设为0_Kafka精进 | Producer端核心参数及调优建议

前言在前面文章《Kafka精进 | 一文读懂Producer消息发送机制》中,我们从Kafka消息结构、序列化器、分区器及消息缓冲池等方面介绍了Producer端的原理,回顾示意图如下:实际使用中,Producer端既要保证吞吐量,又要确保无消息丢失,一些核心参数的配置显得至关重要。本文我们就来看看生产端都有哪些重要的参数。生产端核心参数1. acks参数说明:这是一个非常重要的参数,表...

weixin_39791152的博客 283

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

源码系列第1弹 | 带你快速攻略Kafka源码之旅入门篇

Kafka 源码之旅入门

u011359591的专栏 1186

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

别再死记硬背!一文看懂 Kafka 核心组件及其协作原理

Kafka核心架构摘要 Kafka作为分布式消息系统,采用三层架构设计: 主题层:每个Topic划分为多个分区(Partition),分区可配置副本(Replication)实现高可用 分区层:每个分区包含Leader副本(处理读写)和Follower副本(仅同步数据) 消息层:分区内消息按顺序存储,通过Offset唯一标识 关键组件: Producer向Topic发布消息 Consumer通过Consumer Group实现负载均衡 Broker集群处理消息存储与转发 Coordinator管理消费者与分

JavaEdge全是干货的技术号 2818

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

限时发布!阿里内部爆款架构师培训Kafka源码笔记开源,权威性不言而喻!

在大数据、高并发的系统中,为了突破瓶颈,会将系统进行水平扩展和垂直拆分,形成独立的服务。每个独立的服务背后,可能是一个集群在对外提供服务。这就会碰到一个问题,整个系统是由多个服务(子系统)组成的,数据需要在各个服务中不停流转。如果数据在各个子系统中传输时,速度过慢,就会形成瓶颈,降低整个系统的性能。从而就形成了以Kafka为中心的解决方案! 因为阅读Kafka源码重要性就不言而喻,今天小编就分享一份拼多多Kafka的源码笔记,现已面向大众全面开源!(为了不影响大家的阅读体验,免费获取方式放在了文末!)

weixin_50205273的博客 2174

应用角度看kafka的术语和功能

kafka的术语(Terminology) Topic和Consumer Group Topic每条发布到 Kafka 集群的消息都有一个类别,这个类别被称为 Topic。(物理上不同 Topic 的消息分开存储,逻辑上一个 Topic 的消息虽然保存于一个或多个 broker 上但用户只需指定消息的 Topic 即可生产或消费数据而不必关心数据存于何处) 对应用来说,生产者...

weixin_30763397的博客 870

你说嘴巴嘟嘟,ok我是扣码,现在开始学kafka

包括你的Kafka集群的各种元数据,比如说每台机器上有哪些partition,谁是leader,谁是follower,是谁来管理的?生产者生产的消息按照一定的分区策略被发送到topic中partition中,partition在磁盘上就是一个目录,该目录名是topic的名称加上一个序号,在这个partition目录下,有两类文件,一类是以log为后缀的文件,一类是以index为后缀的文件,每一个log文件和一个index文件相对应,这一对文件就是一个segment file,也就是一个段。

m0_47443458的博客 274

Kafka 3.0零拷贝技术全链路源码深度剖析:从发送端到日志存储的极致优化

在分布式消息系统领域,Kafka凭借高吞吐、低延迟的特性成为行业首选。而零拷贝技术作为Kafka性能优化的核心引擎,贯穿于消息从生产者发送、Broker接收存储到消费者读取的全生命周期。本文基于Kafka 3.0版本,深入源码层面,对零拷贝技术在各关键环节的应用进行全景式剖析。

qq_42773076的博客 780

古董笔记!高级架构师培训Kafka源码笔记,全新开源!!

在大数据、高并发的系统中,为了突破瓶颈,会将系统进行水平扩展和垂直拆分,形成独立的服务。每个独立的服务背后,可能是一个集群在对外提供服务。这就会碰到一个问题,整个系统是由多个服务(子系统)组成的,数据需要在各个服务中不停流转。如果数据在各个子系统中传输时,速度过慢,就会形成瓶颈,降低整个系统的性能。从而就形成了以Kafka为中心的解决方案!......

weixin_66896902的博客 96

不愧是Alibaba技术官,Kafka的精髓全写这本“限量笔记”里,真的牛啊!

我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。实际上,作为程序员,丰富自己的知识储备,提升自己的知识深度和广度是很有必要的,在我看来,自己付出多少,回报就有多少。Kafka的学习,并没有想象中那么难,这份Kafka限量笔记里面的内容,对你学习Kafka必有启发和帮助。如果你需要这份完整版的Kafka笔记,只需你多多支持我这篇文章。httpshttpshttpshttpshttpshttpshttpshttps。...

m0_57042151的博客 102

深入理解Kafka

Kafka 本身是分布式集群,可以采用分区技术,并行度高;读数据采用稀疏索引,可以快速定位要消费的数据;Kafka 的 producer 生产数据,要写入到 log 文件中,写的过程是一直追加到文件末端,为顺序写。官网有数据表明,同样的磁盘,顺序写能到 600M/s,而随机写只有 100K/s。这与磁盘的机械机构有关,顺序写之所以快,是因为其省去了大量磁头寻址的时间。Kafka Broker应用层不关心存储的数据,所以就不用走应用层,传输效率高。

rosemary的博客 1499

Kafka消息路由分区机制深度解析:架构设计与实现原理

通过实现Partitioner接口,开发者可以创建业务特定的路由逻辑。时间窗口路由:将同一时间段的消息集中到特定分区地理位置路由:根据客户端IP选择就近分区业务分片路由:基于实体ID进行分片映射自定义策略需要特别注意分区数变更时的兼容性问题。Kafka的分区路由机制揭示了分布式系统设计的核心哲学——在约束条件下寻求最优解。精准诊断生产环境中的性能瓶颈设计出弹性可扩展的消息处理架构前瞻性地应对未来业务规模的增长。

fjkxyl的博客 1673

Kafka为什么这么快?

题上的“快”过于口语化,准确来讲是“高吞吐量”,也就是为什么Kafka每秒钟可处理百万级别的消息。面试官通常希望,候选人能够逻辑清晰地从Kafka底层原理的角度,盘点出若干个高吞吐量的原因。在本文中,我们就来针对这个问题梳理一下。

z1ztai的博客 1160
上一篇: Kafka核心原理之消息存储机制
下一篇: Kafka核心原理之Broker请求处理
南秋同学
博客等级 码龄7年 65粉丝 27原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值