kafka高性能设计 杂谈

本文深入解析Kafka消息中间件的工作原理,包括生产者、Broker、主题、消费者组等关键组件的功能与交互,探讨数据分组策略、数据完整生产保证、零拷贝技术等提高吞吐量的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、kafka 定义:
kafka是一个生产-消费模型。(像mq似的消息中间件)

producer:生产者,只负责数据生产,生产者的代码可以集成到任务系统中。 数据的分发策略由producer决定,默认是defaultPartition Utils.abs(key.hashCode) % numPartitions

Broker:当前服务器上的Kafka进程,俗称拉皮条。只管数据存储,不管是谁生产,不管是谁消费。
在集群中每个broker都有一个唯一brokerid,不得重复。

topic:目标发送的目的地,这是一个逻辑上的概念,落到磁盘上是一个partition的目录。partition的目录中有多个segment组合(index,log),一个Topic对应多个partition[0,1,2,3],一个partition对应多个segment组合。一个segment有默认的大小是1G。每个partition可以设置多个副本(replication-factor 1),会从所有的副本中选取一个leader出来。所有读写操作都是通过leader来进行的。特别强调,和mysql中主从有区别,mysql做主从是为了读写分离,在kafka中读写操作都是leader。

ConsumerGroup:数据消费者组,ConsumerGroup可以有多个,每个ConsumerGroup消费的数据都是一样的。可以把多个consumer线程划分为一个组,组里面所有成员共同消费一个topic的数据,组员之间不能重复消费。

2、kafka生成数据时的分组策略
默认是defaultPartition Utils.abs(key.hashCode) % numPartitions 上文中的key是producer在发送数据时传入的,produer.send(KeyedMessage(topic,myPartitionKey,messageContent))

3、kafka如何保证数据的完全生产
ack机制:broker表示发来的数据已确认接收无误,表示数据已经保存到磁盘。
0:不等待broker返回确认消息
1:等待topic中某个partition leader保存成功的状态反馈
-1:等待topic中某个partition 所有副本都保存成功的状态反馈

4、broker如何保存数据
在理论环境下,broker按照顺序读写的机制,可以每秒保存600M的数据(不同集群值不同)。主要通过pagecache机制,尽可能的利用当前物理机器上的空闲内存来做缓存。 当前topic所属的broker,必定有一个该topic的partition,partition是一个磁盘目录。partition的目录中有多个segment组合(index,log)

5、partition如何分布在不同的broker上 根据算法可知他是均衡的去分布partition

    int i = 0
	list{kafka01,kafka02,kafka03}
	
	for(int i=0;i<5;i++){
		brIndex = i%broker;
		hostName = list.get(brIndex)
	}

6、consumerGroup的组员和partition之间如何做负载均衡
最好是一一对应,一个partition对应一个consumer。
如果consumer的数量过多,必然有空闲的consumer。
分配原则:消费组中的消费者个数要小于或等于partition的个数。(如果消费组中消费者个数小于partition的个数。最后保证其是partition 的约数。)

算法:
假如topic1,具有如下partitions: P0,P1,P2,P3
加入group中,有如下consumer: C1,C2
首先根据partition索引号对partitions排序: P0,P1,P2,P3
根据consumer.id排序: C0,C1
计算倍数: M = [P0,P1,P2,P3].size / [C0,C1].size,本例值M=2(向上取整)
然后依次分配partitions: C0 = [P0,P1],C1=[P2,P3],即Ci = [P(i * M),P((i + 1) * M -1)]
7、如何保证kafka消费者消费数据是全局有序的。
伪命题
如果要全局有序的,必须保证生产有序,存储有序,消费有序。
由于数据存储到不同分区中。所以生成数据在不同partition中。然后消费组中每个消费者去拿取数据,不能保证谁先谁后。要保证全局有序,就需要保证每个环节都有序。 只有一个可能,就是一个生产者,一个partition,一个消费者。这种场景和大数据应用场景相悖。

8、kafka吞吐量之零拷贝技术
(1)传统的文件拷贝
传统的文件拷贝通常需要从用户态去转到核心态,经过read buffer,然后再返回到用户态的应用层buffer,然后再从用户态把数据拷贝到核心态的socket buffer,然后发送到网卡。如下图所示:
在这里插入图片描述
(2)零拷贝技术 减少了数据传输过程中用户态和核心态之间的切换。并且利用DMA(Direct Memory Access)技术减少了通过cpu去访问内存这种机制。直接由网卡去访问系统主内存。如下图:
大大加快了数据
在这里插入图片描述

(3)传统的文件传输和零拷贝传输JAVA 不同实现方式
传统的文件传输是通过java.io.DataOutputStream,java.io.FileInputStream来实现的,然后通过while循环来读取input,然后写入到output中。
在这里插入图片描述
零拷贝则是通过java.nio.channels.FileChannel中的transferTo方法来实现的。transferTo方法底层是基于操作系统的sendfile这个system call来实现的(不再需要拷贝到用户态了),sendfile负责把数据从某个fd(file descriptor)传输到另一个fd。
在这里插入图片描述

总结:kafka 读写快的原因
写入文件快:
1)、顺序IO
Kafka使用了顺序IO(Sequential IO),并极力避免随机磁盘访问(Random Disk Access)。前者的写入速度比后者快了一个数量级,比如在一个由6块7200转SATA硬盘组成的磁盘阵列上,顺序写入的速度可以达到300MB/S,而随机写入速度只有50KB/S。差距如此之大,难怪Kafka会快得飞起来。
Kafka所采用的提交日志就是以追加的方式写入分区的,就是说单个分区的写入是可以保证顺序的,没有删除和更新操作,因此避免了随机写入。另外,从分区读取数据的时候也是按顺序读取的,避免了随机读取
2)、内存映射文件
内存映射文件将磁盘上的文件内容与内存映射起来,我们往内存里写入数据,操作系统会在稍后把数据冲刷到磁盘上。所以,在写入数据时几乎就是写入内存的速度,这是Kafka快到飞起的另一个原因。
3)、
Kafka还在应用程序层面提供了一些手段来提升性能。最明显的就是使用批次。在向Kafka写入数据时,可以启用批次写入,这样可以避免在网络上频繁传输单个消息带来的延迟和带宽开销。假设网络带宽为10MB/S,一次性传输10MB的消息比传输1KB的消息10000万次显然要快得多

读数据快的原因
1)、零拷贝 (参考上面原理)

参考:https://cloud.tencent.com/developer/article/1421266

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值