Kafka 接收消息 at least once

– Start

点击此处观看本系列配套视频


首先启动 ZooKeeper 和 Kafka borker。
下面的例子演示了如何接收数据以及手动提交 offset。

package shangbo.kafka.example5;

import java.util.Arrays;
import java.util.Properties;

import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;

public class App {
	public static void main(String[] args) {
		Properties props = new Properties();
	     props.put("bootstrap.servers", "localhost:9092");
	     props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
	     props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
	     props.put("group.id", "ConsumerGroup2"); // 消费者组的标识
	     props.put("enable.auto.commit", "false"); // 收到消息后,手动提交 offset
	     props.put("auto.offset.reset", "earliest"); // 如果消费者组第一次接收消息,从哪里开始呢?earliest:最早,latest:最新
	     
	     // 创建 Consumer
	     KafkaConsumer consumer = new KafkaConsumer(props);
	     
	     // 从 topic0 接收数据
	     consumer.subscribe(Arrays.asList("topic0"));
	     
	     // 也可以从指定的 topic/partition 接收数据
//	     TopicPartition partition0 = new TopicPartition("topic0", 0);
//	     consumer.assign(Arrays.asList(partition0));
	     
	     while (true) {
	    	 // 接收消息
	         ConsumerRecords records = consumer.poll(100);
	         for (ConsumerRecord record : records)
	             System.out.printf("offset = %d, key = %s, value = %s%n", record.offset(), record.key(), record.value());
	         
	         // 手动提交
	         consumer.commitSync(); // 同步提交
//	         consumer.commitAsync(); // 异步提交
	     }
	}
}

这其实是 at least once 实现,聪明人已经看出来了,手动提交依然有缺陷,如果一部分消息处理成功了,另一部分失败了,可能导致消息重复处理。有两种破解办法,一种是消息处理要实现 idempotent,也就是说支持重复处理。另一种办法是将 offset 存储在数据库中,和消息处理放在同一事务中,真正实现 exactly once.

– 更多参见:Kafka 精萃
– 声 明:转载请注明出处
– Last Edited on 2018-06-13
– Written by ShangBo on 2018-06-13
– End

你可能感兴趣的:(Kafka)