kafka实战

https://www.cnblogs.com/hei12138/p/7805475.html

前面几张图,把kafka最重要的分区介绍的很清楚。

 

上面的,还有下面这两篇文章中,spring kafka的使用方法还是有些不同的

http://blog.csdn.net/isea533/article/details/73864435

https://www.cnblogs.com/xiaojf/p/6613559.html

2020.5.17  kafka用offset来记录一个分区中的一条唯一消息。 已经消费的位置,存储在kafka服务端(早期是zookeeper中,后来是一个topic中)

https://www.jianshu.com/p/449074d97daf

每个分区只有一个消费者,所以服务端记录offset时,是不关心消费者id的(每个topic的每个消费组,记录一个offset)。

另外,一个生产者的消息,可以指定发到哪个分区,也可以根据消息的key.hashcode决定哪个分区(没有key,可以随机或轮流)。一个消息,有两个必填参数:主题和value。选填key和分区。

zookeeper集群、kafka集群搭建

https://www.cnblogs.com/fengzhiwu/p/5942566.html

-----gaofeng---2019-1-2----

kafka是用scalar开发的,后来又转向java。所以它的版本号很奇怪。比如 kafka_2.11-0.11.0.1,前面的2.11是scalar的版本号,后面的0.11.0.1是java的版本号。它的api也有很多套(scalar的,java的,老的(原始的,高级的),新的),看着很乱。

我们使用新的java的api。

<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
    <version>0.11.0.1</version>  --这个是2017 Sep,   最新的是 2018 Nov,   2.1.0
</dependency>

2020.10.10  使用kafka_2.11-2.1.1.tgz 这个版本做个实验

2.1.1

1、启动zookeeper
./zookeeper-server-start.sh ../config/zookeeper.properties
2、启动kafka
./kafka-server-start.sh ../config/server.properties
3、查询topic列表
./kafka-topics.sh --zookeeper 127.0.0.1:2181 --list
4、创建topic
./kafka-topics.sh --zookeeper 127.0.0.1:2181 --create --topic test1 --partitions 1 --replication-factor 1
5、启动一个消费者消费
./kafka-console-consumer.sh --bootstrap-server 127.0.0.1:9092 --from-beginning --topic test1
6、创建生产者,并手工发消息
./kafka-console-producer.sh --broker-list 127.0.0.1:9092 --topic test1
输入一段文本,并回车,在消费者那边就可以看到这个消息已经被消费(打印)了
7、查看当前的offset
group + topic 定位一个offset, --dry-run 表示干跑,不执行,可以用于查看
[root@LIN-49AB0E67FE4 bin]# ./kafka-consumer-groups.sh --bootstrap-server localhost:9092  --reset-offsets --group group_test1 --topic test1 --to-current --dry-run

TOPIC                          PARTITION  NEW-OFFSET     
test1                          0          1469
8、查看最新的offset
[root@LIN-49AB0E67FE4 bin]# ./kafka-consumer-groups.sh --bootstrap-server localhost:9092  --reset-offsets --group group_test --topic test1 --to-latest --dry-run

TOPIC                          PARTITION  NEW-OFFSET     
test1                          0          1470
9、重置到指定的offset
[root@LIN-49AB0E67FE4 bin]# ./kafka-consumer-groups.sh --bootstrap-server localhost:9092  --reset-offsets --group group_test --topic test1 --to-offset 1460 --execut
10、重置到最早的offset
[root@LIN-49AB0E67FE4 bin]# ./kafka-consumer-groups.sh --bootstrap-server localhost:9092  --reset-offsets --group group_test --topic test1 --to-earliest --execut
11、重置到最新的offset 
[root@LIN-49AB0E67FE4 bin]# ./kafka-consumer-groups.sh --bootstrap-server localhost:9092  --reset-offsets --group group_test --topic test1 --to-latest --execut

通过java代码读取消息,也可以验证这一点
		<dependency>
			  <groupId>org.apache.kafka</groupId>
			  <artifactId>kafka_2.12</artifactId>
			  <version>2.1.1</version>
		</dependency>

package gaofeng.test1;

import java.util.Properties;
import java.util.Random;

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;

public class MyKafkaProducer {
	public static void main(String[] args) throws InterruptedException {
        Properties p = new Properties();
        p.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "127.0.0.1:9092");//kafka地址,多个地址用逗号分割
        p.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        p.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
        
        KafkaProducer<String,String> kafkaProducer = new KafkaProducer<>(p);
        try {
        	String topic = "test1";
            while (true) {
                String msg = "Hello," + new Random().nextInt(100);
                ProducerRecord<String, String> record = new ProducerRecord<>(topic, msg);
                kafkaProducer.send(record);
                System.out.println("消息发送成功:" + msg);
                Thread.sleep(500);
            }
        } finally {
            kafkaProducer.close();
        }
	}
}

package gaofeng.test1;

import java.time.Duration;
import java.util.Collections;
import java.util.Properties;
import org.apache.kafka.clients.consumer.ConsumerConfig;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.serialization.StringDeserializer;

public class MyKafkaConsumer {
	public static void main(String[] args) {
        Properties p = new Properties();
        p.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "127.0.0.1:9092");//kafka地址,多个地址用逗号分割
        p.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        p.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
        p.put(ConsumerConfig.GROUP_ID_CONFIG, "group_test1");
        p.put(ConsumerConfig.CLIENT_ID_CONFIG, "client1");
        p.put(ConsumerConfig.AUTO_COMMIT_INTERVAL_MS_CONFIG, "60000");//默认是6秒,这里改为60秒是为了做实验
        String topic = "test1";
        KafkaConsumer<String,  String> kafkaConsumer = new KafkaConsumer<String, String>(p);
        try {
            kafkaConsumer.subscribe(Collections.singletonList(topic));// 订阅消息
            while (true) {
                ConsumerRecords<String, String> records = kafkaConsumer.poll(Duration.ofSeconds(5));
                System.out.println("recv:" + records.count());
                for (ConsumerRecord<String, String> record : records) {
                    System.out.println(String.format("topic:%s,offset:%d,消息:%s", //
                        record.topic(), record.offset(), record.value()));
                }
            }
        }finally {
        	kafkaConsumer.close();//会自动调用 kafkaConsumer.commitSync();
        }
	}
}

这里把自动提交周期改为60秒,是为了验证周期没到,提前结束java程序,下次再启动,会重复消费这个消息。
上的finally是没有用的,因为直接结束java虚拟机。

另外,如果调用了kafkaConsumer.close(),也会自动提交,不用等到60秒的周期。
公司系统出现重复消费问题,是因为底层的close函数调用失败,没有进行自动提交导致的。

还验证了group1消费后没有提交,和group2没有关系,他们有独立的offset.

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值