最近就kafka消费者消费数据时,消费者提交的offset与同事们有一些分歧和讨论,这里记录一下自己的研究。
我们知道redis和kafka都可以作为消息队列使用,都可以完成发布订阅功能,但是kafka相较于redis可以实现订阅消息的存储,可以实现订阅消息的任意位置消费,更重要的时kafka订阅消息是可以存储到磁盘上的,而redis订阅消息是无法存储磁盘的。
(1)消费者消费数据时加入一个消费者分组之后,可以通过 subscribe函数订阅某个topic,这时这个消费者进入brokers的group management管理机制,同一个分片只能被一个分组中的消费者消费,如果同一个分片希望被多个消费者消费,需要将多个消费者放入到不同的消费者分组中。
//订阅指定的topic
consumer.subscribe(Arrays.asList(topic));
(2)还有一种消费数据的方式是可以通过assign函数指定要消费的分区数据,这种方式可以指定从分区的任意位置开始消费数据,当然这种//消费者指定要消费的分区,指定分区之后消费者崩溃之后 不会引发分区reblance
consumer.assign(list);
消费数据的方式,如果消费者奔溃之后,不会引发分区reblance,也就是说assign的consumer不会拥有kafka的group management机制。
我们上面说过,同一个分片只能由消费者分组中的同一个消费者进行消费,假设当消费者A使用assign指定分区进行消费时,如果这时消费者A使用的分组group B,是通过subscribe订阅了这个主题的分片时,由于消费者A不加入group management,它相当于一个独立的临时消费者,这时消费者A也是可以正常消费的,看起来就是一个分片被一个消费者组中的多个消费者消费一样。
(3)我们还可以配置如下属性auto.offset.reset来,设置消费者从分区的开头或者末尾进行消费数据。当然这也是有条件的。
//一般配置earliest 或者latest 值
props.put("auto.offset.reset", "latest");
我把上述三种情况的消费者不同使用方式下,消费者提交offset的情况进行了归总和说明:
早在kafka0.8.2.2版本的时候,kafka已经支持消息offset存在brokers中,只不过默认是将offset存储到zookeeper中。kafka现在最新发布的版本都是默认将数据存储到brokers中。我的代码示例是使用了kafka0.10.0.0版本,当我们这里通过assign函数分配指定的分区时
下面是我的测试代码,有兴趣的同学可以查看和验证上述结论:
/**
*
* @author yujie.wang
* kafka生产者示例代码
*/
public class Producer_Sample {
//kafka集群机器
private static final String KAFKA_HOSTS = "10.4.30.151:9092,10.4.30.151:9093,10.4.30.151:9094";
//topic名称
private static final String TOPIC = "my-replicated-topic_2";
public static void main(String[] args) {
// TODO Auto-generated method stub
Producer_Sample producer = new Producer_Sample();
producer.producer_send(TOPIC);
System.out.println("end");
}
/**
* 生产者生产数据
* 发送消息是异步进行,一旦消息被保存到