一般情况下,producer在发送一条数据时就会登记回调函数(回调函数暂时不运行,由于是异步,主程序会继续发送其他数据),数据到达服务器broker上指定分区时,服务器会通知producer已经发送成功。producer收到消息后就会触发回调函数,可以显示这条数据在服务器端的一些信息(偏移量,分区等)。
Kafka的producer:
public static void producerSendWithCallback(){
Properties properties = new Properties();
properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,kafka_servers);
properties.put(ProducerConfig.ACKS_CONFIG,"all"); //ack参数
properties.put(ProducerConfig.RETRIES_CONFIG,"0");
properties.put(ProducerConfig.BATCH_SIZE_CONFIG,"16384");
properties.put(ProducerConfig.LINGER_MS_CONFIG,"1");
properties.put(ProducerConfig.BUFFER_MEMORY_CONFIG,"33554432");
properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,"org.apache.kafka.common.serialization.StringSerializer");
// Producer的主对象
Producer<String,String> producer = new KafkaProducer<>(properties);
// 消息对象 - ProducerRecoder
for(int i=0;i<5;i++){
ProducerRecord<String,String> record =
new ProducerRecord<>(TOPIC_NAME,"key-"+i,"value-"+i);
producer.send(record, new Callback() {
@Override
public void onCompletion(RecordMetadata recordMetadata, Exception e) {
System.out.println(
"time : "+recordMetadata.timestamp() +",partition : "+recordMetadata.partition()+" , offset : "+recordMetadata.offset());
}
});
}
// 所有的通道打开都需要关闭
producer.close();
}
设置acks=all
Leader接收到消息并写入磁盘分区之后(写入磁盘当然才能知道数据的offset信息),还必须要求ISR列表里跟Leader保持同步的那些Follower都要把消息同步写入磁盘分区,才能认为这条消息是写入成功了。
properties.put(ProducerConfig.ACKS_CONFIG,"all");
回调函数返回结果:
time : 1611678310197,partition : 1 , offset : 275
time : 1611678310207,partition : 1 , offset : 276
time : 1611678310207,partition : 1 , offset : 277
time : 1611678310207,partition : 0 , offset : 200
time : 1611678310207,partition : 0 , offset : 201
消费者信息(注意:回调函数的结果和消费者打印的结果不是一一对应的):
[hadoop@hadoop000 kafka_2.11-2.2.1]$ kafka-console-consumer.sh --bootstrap-server hadoop000:9092 --topic topic_test
value-1
value-2
value-0
value-3
value-4
设置acks=0
把消息发送出去,不管那条数据有没有在哪怕Partition Leader上落到磁盘,我就不管他了,直接就认为这个消息发送成功了。
properties.put(ProducerConfig.ACKS_CONFIG,"0");
回调函数返回结果:
time : 1611678235720,partition : 1 , offset : -1
time : 1611678235729,partition : 1 , offset : -1
time : 1611678235729,partition : 1 , offset : -1
time : 1611678235729,partition : 0 , offset : -1
time : 1611678235729,partition : 0 , offset : -1
所以获取不到offset的值。