==========================================================================
物理上把 topic 分成一个或多个 patition(对应 server.properties 中的 num.partitions=3 配 置),每个 patition 物理上对应一个文件夹(该文件夹存储该 patition 的所有消息和索引文 件),如下:
[root@hadoop102 logs]$ ll
drwxrwxr-x. 2 demo demo 4096 8 月 6 14:37 first-0
drwxrwxr-x. 2 demo demo 4096 8 月 6 14:35 first-1
drwxrwxr-x. 2 demo demo 4096 8 月 6 14:37 first-2
[root@hadoop102 logs]$ cd first-0
[root@hadoop102 first-0]$ ll
-rw-rw-r–. 1 demo demo 10485760 8 月 6 14:33 00000000000000000000.index
-rw-rw-r–. 1 demo demo 219 8 月 6 15:07 00000000000000000000.log
-rw-rw-r–. 1 demo demo 10485756 8 月 6 14:33 00000000000000000000.timeindex
-rw-rw-r–. 1 demo demo 8 8 月 6 14:37 leader-epoch-checkpoint
==============================================================================
无论消息是否被消费,kafka 都会保留所有消息。有两种策略可以删除旧数据:
-
基于时间:log.retention.hours=168
-
基于大小:log.retention.bytes=1073741824
需要注意的是,因为 Kafka 读取特定消息的时间复杂度为 O(1),即与文件大小无关, 所以这里删除过期文件与提高 Kafka 性能无关。
========================================================================================
注意:producer 不在 zk 中注册,消费者在 zk 中注册。
====================================================================================
kafka 提供了两套 consumer API:高级 Consumer API 和低级 Consumer API。
================================================================================
=================================================================================
-
高级 API 写起来简单
-
不需要自行去管理 offset,系统通过 zookeeper 自行管理。
-
不需要管理分区,副本等情况,系统自动管理。
-
消费者断线会自动根据上一次记录在 zookeeper 中的 offset 去接着获取数据(默认设置 1 分钟更新一下 zookeeper 中存的 offset)
-
可以使用 group 来区分对同一个 topic 的不同程序访问分离开来(不同的 group 记录不同的 offset,这样不同程序读取同一个 topic 才不会因为 offset 互相影响)
=================================================================================
-
不能自行控制 offset(对于某些特殊需求来说)
-
不能细化控制如分区、副本、zk 等
================================================================================
=================================================================================
-
能够让开发者自己控制 offset,想从哪里读取就从哪里读取。
-
自行控制连接分区,对分区自定义进行负载均衡
-
对 zookeeper 的依赖性降低(如:offset 不一定非要靠 zk 存储,自行存储 offset 即可, 比如存在文件或者内存中)
=================================================================================
- 太过复杂,需要自行控制 offset,连接哪个分区,找到分区 leader 等。
==============================================================================
消费者是以 consumer group 消费者组的方式工作,由一个或者多个消费者组成一个组, 共同消费一个 topic。每个分区在同一时间只能由 group 中的一个消费者读取,但是多个 group 可以同时消费这个 partition。在图中,有一个由三个消费者组成的 group,有一个消费者读取主题中的两个分区,另外两个分别读取一个分区。某个消费者读取某个分区,也可以叫做某个消费者是某个分区的拥有者。
在这种情况下,消费者可以通过水平扩展的方式同时读取大量的消息。另外,如果一个消费者失败了,那么其他的 group 成员会自动负载均衡读取之前失败的消费者读取的分区。
==============================================================================
consumer 采用 pull(拉)模式从 broker 中读取数据。
push(推)模式很难适应消费速率不同的消费者,因为消息发送速率是由 broker 决定的。它的目标是尽可能以最快速度传递消息,但是这样很容易造成 consumer 来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。而 pull 模式则可以根据 consumer 的消费能力以适当的速率消费消息。
对于 Kafka 而言,pull 模式更合适,它可简化 broker 的设计,consumer 可自主控制消费 消息的速率,同时 consumer 可以自己控制消费方式——即可批量消费也可逐条消费,同时还能选择不同的提交方式从而实现不同的传输语义。
pull 模式不足之处是,如果 kafka 没有数据,消费者可能会陷入循环中,一直等待数据 到达。为了避免这种情况,我们在我们的拉请求中有参数,允许消费者请求在等待数据到达 的“长轮询”中进行阻塞(并且可选地等待到给定的字节数,以确保大的传输大小)。
==============================================================================
=================================================================================
安装环境:Linux
前提条件:
Linux系统下安装好jdk 1.8以上版本,正确配置环境变量 Linux系统下安装好scala 2.11版本
安装ZooKeeper(注:kafka自带一个Zookeeper服务,如果不单独安装,也可以使用自带的ZK)
【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
**
============================================================================
Apache基金会开源的这些软件基本上安装都比较方便,只需要下载、解压、配置环境变量三步即可完成,kafka也一样,官网选择对应版本下载后直接解压到一个安装目录下就可以使用了,如果为了方便可以在~/.bashrc里配置一下环境变量,这样使用的时候就不需要每次都切换到安装目录了。
具体可参考:Kafka 集群安装与环境测试
==========================================================================
接下来可以通过简单的console窗口来测试kafka是否安装正确。
========================================================================================
如果启动自己安装的ZooKeeper,使用命令zkServer.sh start即可。
如果使用kafka自带的ZK服务,启动命令如下(启动之后shell不会返回,后续其他命令需要另开一个Terminal):
$ cd /opt/tools/kafka #进入安装目录
$ bin/zookeeper-server-start.sh config/zookeeper.properties
=====================================================================================
启动Kafka服务的命令如下所示:
$ cd /opt/tools/kafka #进入安装目录
$ bin/kafka-server-start.sh config/server.properties
===============================================================================================
创建topic的命令如下所示,其参数也都比较好理解,依次指定了依赖的ZooKeeper,副本数量,分区数量,topic的名字:
$ cd /opt/tools/kafka #进入安装目录
$ bin/kafka-topics.sh --create --zookeeper localhost:2181 --replication-factor 1 --partitions 1 --topic test1
创建完成后,可以通过如下所示的命令查看topic列表:
$ bin/kafka-topics.sh --list --zookeeper localhost:2181
==============================================================================================
kafka提供了生产者和消费者对应的console窗口程序,可以先通过这两个console程序来进行验证。
首先启动Producer:
$ cd /opt/tools/kafka #进入安装目录
$ bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test
然后启动Consumer:
$ cd /opt/tools/kafka #进入安装目录
$ bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning
在打开生产者服务的终端输入一些数据,回车后,在打开消费者服务的终端能看到生产者终端输入的数据,即说明kafka安装成功。
=======================================================================================
==============================================================================
kafka-topics.sh --create --zookeeper 192.168.56.137:2181 --topic test --replication-factor 1 --partitions 1
===============================================================================
org.apache.kafka
kafka-clients
2.1.1
===========================================================================
package com.njbdqn.services;
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;
import java.util.Properties;
/**
@author:Tokgo J
@date:2020/9/11
@aim:生产者:往test消息队列写入消息
*/
public class MyProducer {
public static void main(String[] args) {
// 定义配置信息
Properties prop = new Properties();
// kafka地址,多个地址用逗号分割 “192.168.23.76:9092,192.168.23.77:9092”
prop.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,“192.168.56.137:9092”);
prop.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class);
prop.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class);
KafkaProducer<String,String> prod = new KafkaProducer<String, String>(prop);
// 发送消息
try {
for(int i=0;i<10;i++) {
// 生产者记录消息
ProducerRecord<String, String> pr = new ProducerRecord<String, String>(“test”, “hello world”+i);
prod.send(pr);
Thread.sleep(500);
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
prod.close();
}
}
}
注意:
-
kafka如果是集群,多个地址用逗号分割(,) ;
-
Properties的put方法,第一个参数可以是字符串,如:p.put(“bootstrap.servers”,“192.168.23.76:9092”) ;
-
kafkaProducer.send(record)可以通过返回的Future来判断是否已经发送到kafka,增强消息的可靠性。同时也可以使用send的第二个参数来回调,通过回调判断是否发送成功;
-
p.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); 设置序列化类,可以写类的全路径。
===========================================================================
package com.njbdqn.services;
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;
import org.apache.kafka.common.serialization.StringSerializer;
import java.time.Duration;
import java.util.Arrays;
import java.util.Collections;
import java.util.Properties;
/**
@author:Tokgo J
@date:2020/9/11
@aim:消费者:读取kafka数据
*/
public class MyConsumer {
public static void main(String[] args) {
Properties prop = new Properties();
prop.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, “192.168.56.137:9092”);
prop.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
prop.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
prop.put(“session.timeout.ms”, “30000”);
//消费者是否自动提交偏移量,默认是true 避免出现重复数据 设为false
prop.put(“enable.auto.commit”, “false”);