Kafka源码之Producer阅后总结

文章详细阐述了Kafka生产者发送消息的核心流程,包括同步拉取元数据、消息序列化、分区选择策略、消息大小检查、accumulator缓存以及异步发送机制。同时,介绍了内部数据结构如ConcurrentMapTopicPartition和CopyOnWriteMap在确保线程安全和效率方面的作用。
摘要由CSDN通过智能技术生成

生产者源码核心流程

1.同步等待拉取元数据

  1. 首先main线程想要发送消息,因此Kafka会开启一个send()线程来专用发送消息,因为这时Kafka第一次去读取数据,发送消息之前会尝试去MetaData(元数据的管理组件)拉取元数据。

  2. 唤起sender()线程去Kafka集群获取topic信息,获取到元数据信息后,更新版本号(版本号是一次递增的,用户更新配置后实时更新元数据信息),唤醒主线程,拉取到元数据信息后。
    启动Kafka集群时创建的send()线程就可以开始发送数据了。

  3. sender()线程也会 定期的去集群拉去元数据信息,并更新版本号。

    * 唤醒sender()线程,去拉取元数据。
    * 启动Kafka时,在获取配置信息时,就已经创建了sender()线程,是一个死循环,一直在运行,sender线程的run()方法中有一个poll()方法负责拉去元数据。
        a.封装一个拉取元数据的请求,发送请求。就是执行网络io的操作。
        b.处理相应的信息,信息中就包括元数据信息。
    

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

3.根据分区器进行选择消息应该发送的分区

有两个分区策略
策略1:用户没有指定具体分区,Kafka计算出分区的总数对10进行取模,然后以轮询的方式发送到各个分区,达到负载均衡。
策略2:用户指定了具体分区,Kafka会计算消息的key的hash值,并对分区总数取模,然后发送到具体的分区,如果消息的key一样的话就会造成数据倾斜。

4.确认消息的大小是否超过了最大值

Kafka producer在初始化的时候,指定一个参数,代表的是producer最大发送一条消息的大小。
默认是1M,在实际生产环境中一般都会去修改为10M,具体还要根据数据的情况去设置。

5.根据元数据信息,封装分区信息

6.给每一条消息绑定他的回调函数,因为是异步的方式发送的消息

7.把消息封装到accumulator(32M内存)

消息首先缓存到accumulator缓存中,这个缓存中有多个队列(queue),队列的数量和topic分区的数量一一对应的,一个队列的消息(消息一个批次一个批次的发送,默认16kb)都会发送到对应的分区中,并且accumulator中有缓存池,内存不够时都可以向缓存池申请资源,达到内存资源高利用率的优化,同时也减少了GC带来的影响。

1.根据分区找到对应批次队列,如果已存在这个队列,则直接使用,否则新创建一个队列(ArrayDequeue)。

2.尝试往队列添加消息。

3.计算消息的大小和批次大小之间取一个最大值,用这个值作为当前批次的大小。有可能出现的情况是一条消息的大小有可能超过默认批次大小,所以这个默认批次的大小根据公司的具体情况去设置。

4.根据批次的大小分配内存。

5.尝试将消息写入到批次里面,如果是第一次执行还是失败的,因为只有内存,没有队列。

6.准备好之后会将批次的消息添加到队尾

8.唤醒sender线程,真正的发送数据

Kafka存储数据的核心数据结构

ConcurrentMapTopicPartition<TopicPartition, Dequeue<Recordbatch>> batchs;
batchs = new CopyOnWriteMap<>(); 这个数据结构是Kafka自身实现的数据结构,实现了ConcurrentMap接口。核心成员变量是map,并且使用volatile关键字修饰的,作用是在多线程情况下,如果map值发生变化,其他线程是可见的。
CopyOnWriteMap的put方法:
 	整个方法是synchronized关键字修饰的,说明这个方法是线程安全的。即使加了锁,执行性能也是很好的,因为基于内存的操作。
	put方法中还采用的是读写分离的设计思想,读操作和写操作是互不影响的,所以读操作是线程安全的。
	最后把新写的数据赋值给map,正因为map是volatile关键字修饰的,所以map修改了,其他线程也能感知到map的变化。

设计思想,也会带来相应的弊端,就是比较耗费内存空间,所以比较适合读多写少的场景。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值