Topic&Partition

集群:在每个Kafka的节点配置中配置 zookeeper.connect=IP:2181,IP:2181,IP:2181/kafka
Topic:相当于数据库中的表,每个Topic 可以有多个Partition 以及副本ReplicationFactor
Partition:相当于每个大表的分表,一个Partition只能由同一Group 的单个Consumer消费,一个Partition存在多个Consumer 只有一个Consumer能消费数据
ReplicationFactor:每个Partition的副本
Offset:在data中会保存 数据log、indexlog、timestamplog;
①通过当前offset,去indexlog中找到offset对应的position在数据log中的字节位置
②通过时间戳 ,去timestamplog中找到对应的offset位置 再重复上面操作

生产者

生产者代码(源码)
public static String brokers = "node01:9092,node02:9092,node03:9092";public static Properties initConf(){
Properties conf = new Properties();
conf.setProperty(ProducerConfig.ACKS_CONFIG,"0");
conf.setProperty(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); //key得序列话
conf.setProperty(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());//value得序列话
conf.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,brokers); //集群
conf.setProperty(ProducerConfig.PARTITIONER_CLASS_CONFIG, DefaultPartitioner.class.getName());
conf.setProperty(ProducerConfig.BATCH_SIZE_CONFIG,"16384"); //16k 要调整的,分析我们msg的大小,尽量触发批次发送,减少内存碎片,和系统调用的复杂度
conf.setProperty(ProducerConfig.LINGER_MS_CONFIG,"0"); //
conf.setProperty(ProducerConfig.MAX_REQUEST_SIZE_CONFIG,"1048576"); //一个批次最大 (batch累加不可超过)
//message.max.bytes
conf.setProperty(ProducerConfig.BUFFER_MEMORY_CONFIG,"33554432");//32M //所有分区 所有batch的大小
conf.setProperty(ProducerConfig.MAX_BLOCK_MS_CONFIG,"60000"); //60秒
conf.setProperty(ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION,"5");
conf.setProperty(ProducerConfig.SEND_BUFFER_CONFIG,"32768"); //32K -1 //单次发送大小
conf.setProperty(ProducerConfig.RECEIVE_BUFFER_CONFIG,"32768"); //32k -1
return conf;
}Properties conf = initConf();
KafkaProducer<String, String> producer = new KafkaProducer<>(conf);
while (true) {
ProducerRecord<String, String> msg = new ProducerRecord<String, String>("ooxx", "hello", "ooxx1");
Future<RecordMetadata> future = producer.send(msg);
RecordMetadata recordMetadata = future.get();
}首先new KafkaProducer对象 初始化
- RecordAccumulator 纪录累加器
每个Topic的分区为单位
- ②new Sender
当new KafkaProducer对象就会起一个线程 死循环去RecordAccumulator 纪录累加器取数据真正的send到磁盘中
该类是实现了Runnable
- ③new KafkaThread(ioThreadName, this.sender, true);
启动线程实现Sender的方法
调用send方法 (RecordAccumulator.append)
- key、value序列号
- 计算分区:ProducerRecord生产数据时要有topic key value,其中key通过partitioner.partition()方法计算出所在分区,key为null时:在目前可用分区中通过count累加取余数算出partition ;key不为null时:通过所有分区Hash取余数算出partition。
- accumulator.append() 往RecordAccumulator 纪录累加器中append()
通过所在分区,往Batch为实体的双端队列中(Deque<RecordBatch> ) append ,使用synchronized避免并发问题。
RecordBatch配置BATCH_SIZE_CONFI该参数:当生产的数据大小 小于该配置时,使用系统提前分配好的内存空间往batch塞数据,当大于时 系统会阻塞分配内存空间至新的batch(该大小合理分配 不会阻塞,且不易产生碎片问题)
IOthread:Sender(待完善)
- 死循环去RecordAccumulator 纪录累加器取数据真正的send到磁盘中
- accumulator.ready()每个双端队列Deque中,是否超时,或者超过batch批次大小
LINGER_MS_CONFIG:配置时间,当超过这个时间触发一次,send到磁盘中
MAX_REQUEST_SIZE_CONFIG:配置批次大小,超过 则send到磁盘中
ACK
0:生产消息时,直接往Kafka中丢数据,不返回offset值
1(默认):生产消息时,往Kafka中丢数据,成功往某个Topic的partition中send数据后 返回offset值
-1(All):(分布式)生产消息时,往Kafka中丢数据,成功往某个Topic的partition中send数据后 返回offset值,并且等副本ReplicationFactor同步该数据后返回offset值

ISR:

OSR:

AR:

















