kafka源码浅析

 

概要

说到 kafka 源码理解

可能大家听到的kafka对多的是kafka

顺序追加?

0拷贝?

高并发?

线程安全?

....

但是这些到底为什么呢 ?其实看看kafka的源码就非常的清晰了

优秀的点非常的多,我这里重点讲我认为设计的非常优秀美观的地方.

 核心优势

kafka的优秀的点.

分段加锁

double check

读写分离

内存池的设计

高性能的设计

跳表设计

稀疏索引设计

零拷贝..

源码浅析

kafka producer

请看下面 kafka producer主要干了啥

 

 

那我们就从producer.send的开始吧,此处引用的是kafka2.7的版本,可能各版本有细节的差异,比如可以观测下面frre.dealocate的位置和前面的版本有所差异哦

doSend()主要分为 以下步骤

1.同步等待拉取元数据

 

     // first make sure the metadata for the topic is available
            long nowMs = time.milliseconds();
            ClusterAndWaitTime clusterAndWaitTime;
            try {
                clusterAndWaitTime = waitOnMetadata(record.topic(), record.partition(), nowMs, maxBlockTimeMs);
            } catch (KafkaException e) {
                if (metadata.isClosed())
                    throw new KafkaException("Producer closed while send in progress", e);
                throw e;
            }
            nowMs += clusterAndWaitTime.waitedOnMetadataMs;
            long remainingWaitMs = Math.max(0, maxBlockTimeMs - clusterAndWaitTime.waitedOnMetadataMs);
            Cluster cluster = clusterAndWaitTime.cluster;
 


2.对消息的key value进行序列化

3.计算出应该发到哪个分区(如果有自定义,走自定义)

4.确认消息的序列化之后有没有超过1M(此时这个参数可以设置.) max.request.size

 

 

5.给消息绑定相应的回调函数

6.最核心,最关键的.就是上图说的accumulaor.append,看看优秀的kafka是怎样完美的实现了 高并发读写,并且还能线程安全的

将消息放入一个 32M的内存,然后有个accumulator.apend 封装成一个批次,一个批次的发出去

 

 

7.唤醒sender的线程,将将准备好的批次数据开始批量的发送

 

 

 

RecordAccumulator.RecordAppendResult result = accumulator.append(tp, timestamp, serializedKey)

 

 

(1)获取队列,如果有就获取,没有就创建

 

(2)线程1第一次进来 check1(这一步一定是高频操作,不断的往去追加数据到空闲的recordBatch.并排成队列等待处理.在高并发下保证线程安全,不然数据的顺序性,不然回滚等一致性操作全部乱了, 所以此处加了 锁

写的时候,如果有这个队列中有个ProducerBatch, 那么直接获取最后一条.如果没有,就新生产一个bath

队列中buffersize 预估内存,如果不够,还要去内存池中申请.这里的一个batchSize是16k.如果不够,将会调用free.allocate去内存池里申请内存.

申请内存为耗时操作.

 

 

你们有没有惊奇的发现,相同的tryAppend又来了,难道是源码写错了? 

当然不是啦,源码设计精巧之处就在在这里.   如果线程1申请到空间但是他并没有使用不是吗?

1.倘若线程2又跳到这里,是不是刚好可以用, 而且各自都是按照latest的方式去追加在末尾. 并在同一批次中准备待命.

2.将申请空间的代码抽离出来,追加数据的代码用锁的方式封装起来, 实现了真正的高并发.其实细节很多的,鉴于技术有限,实在是描述不清楚,做个了解就行.

3.真正实现了读写分离,不管是读请求,还是写请求,都会非常的快速

4.最后会有一个free.deallocate(buffer) ,用完的空间有回归出去,为下一个批次做准备.

我也快下班了.今天就写到这里.下次我们还可以聊聊

跳表设计

稀疏索引设计

零拷贝..

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值