Java程序员:世界有三个伟大的发明「火、轮子,Java面试相关文章及Github学习资料

程序员 专栏收录该内容
103 篇文章 1 订阅

4.2.1 存储方式

==========================================================================

物理上把 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

4.2.2 存储策略

==============================================================================

无论消息是否被消费,kafka 都会保留所有消息。有两种策略可以删除旧数据:

  • 基于时间:log.retention.hours=168

  • 基于大小:log.retention.bytes=1073741824

需要注意的是,因为 Kafka 读取特定消息的时间复杂度为 O(1),即与文件大小无关, 所以这里删除过期文件与提高 Kafka 性能无关。

4.2.3 Zookeeper 存储结构

========================================================================================

Java程序员:世界有三个伟大的发明「火、轮子、kafka」

注意:producer 不在 zk 中注册,消费者在 zk 中注册。

4.3 Kafka 消费过程分析

====================================================================================

kafka 提供了两套 consumer API:高级 Consumer API 和低级 Consumer API。

4.3.1 高级 API

================================================================================

「1)高级 API 优点」

=================================================================================

  • 高级 API 写起来简单

  • 不需要自行去管理 offset,系统通过 zookeeper 自行管理。

  • 不需要管理分区,副本等情况,系统自动管理。

  • 消费者断线会自动根据上一次记录在 zookeeper 中的 offset 去接着获取数据(默认设置 1 分钟更新一下 zookeeper 中存的 offset)

  • 可以使用 group 来区分对同一个 topic 的不同程序访问分离开来(不同的 group 记录不同的 offset,这样不同程序读取同一个 topic 才不会因为 offset 互相影响)

「2)高级 API 缺点」

=================================================================================

  • 不能自行控制 offset(对于某些特殊需求来说)

  • 不能细化控制如分区、副本、zk 等

4.3.2 低级 API

================================================================================

「1)低级 API 优点」

=================================================================================

  • 能够让开发者自己控制 offset,想从哪里读取就从哪里读取。

  • 自行控制连接分区,对分区自定义进行负载均衡

  • 对 zookeeper 的依赖性降低(如:offset 不一定非要靠 zk 存储,自行存储 offset 即可, 比如存在文件或者内存中)

「2)低级 API 缺点」

=================================================================================

  • 太过复杂,需要自行控制 offset,连接哪个分区,找到分区 leader 等。

4.3.3 消费者组

==============================================================================

Java程序员:世界有三个伟大的发明「火、轮子、kafka」

消费者是以 consumer group 消费者组的方式工作,由一个或者多个消费者组成一个组, 共同消费一个 topic。每个分区在同一时间只能由 group 中的一个消费者读取,但是多个 group 可以同时消费这个 partition。在图中,有一个由三个消费者组成的 group,有一个消费者读取主题中的两个分区,另外两个分别读取一个分区。某个消费者读取某个分区,也可以叫做某个消费者是某个分区的拥有者。

在这种情况下,消费者可以通过水平扩展的方式同时读取大量的消息。另外,如果一个消费者失败了,那么其他的 group 成员会自动负载均衡读取之前失败的消费者读取的分区。

4.3.4 消费方式

==============================================================================

consumer 采用 pull(拉)模式从 broker 中读取数据。

push(推)模式很难适应消费速率不同的消费者,因为消息发送速率是由 broker 决定的。它的目标是尽可能以最快速度传递消息,但是这样很容易造成 consumer 来不及处理消息,典型的表现就是拒绝服务以及网络拥塞。而 pull 模式则可以根据 consumer 的消费能力以适当的速率消费消息。

对于 Kafka 而言,pull 模式更合适,它可简化 broker 的设计,consumer 可自主控制消费 消息的速率,同时 consumer 可以自己控制消费方式——即可批量消费也可逐条消费,同时还能选择不同的提交方式从而实现不同的传输语义。

pull 模式不足之处是,如果 kafka 没有数据,消费者可能会陷入循环中,一直等待数据 到达。为了避免这种情况,我们在我们的拉请求中有参数,允许消费者请求在等待数据到达 的“长轮询”中进行阻塞(并且可选地等待到给定的字节数,以确保大的传输大小)。

五、Kafka 安装

==============================================================================

5.1 安装环境与前提条件

=================================================================================

安装环境:Linux

前提条件:

Linux系统下安装好jdk 1.8以上版本,正确配置环境变量 Linux系统下安装好scala 2.11版本

安装ZooKeeper(注:kafka自带一个Zookeeper服务,如果不单独安装,也可以使用自带的ZK)

**5.2 安装步骤

【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】

浏览器打开:qq.cn.hn/FTf 免费领取

**

============================================================================

Apache基金会开源的这些软件基本上安装都比较方便,只需要下载、解压、配置环境变量三步即可完成,kafka也一样,官网选择对应版本下载后直接解压到一个安装目录下就可以使用了,如果为了方便可以在~/.bashrc里配置一下环境变量,这样使用的时候就不需要每次都切换到安装目录了。

具体可参考:Kafka 集群安装与环境测试

5.3 测试

==========================================================================

接下来可以通过简单的console窗口来测试kafka是否安装正确。

「(1)首先启动ZooKeeper服务」

========================================================================================

如果启动自己安装的ZooKeeper,使用命令zkServer.sh start即可。

如果使用kafka自带的ZK服务,启动命令如下(启动之后shell不会返回,后续其他命令需要另开一个Terminal):

$ cd /opt/tools/kafka #进入安装目录

$ bin/zookeeper-server-start.sh config/zookeeper.properties

「(2)第二步启动kafka服务」

=====================================================================================

启动Kafka服务的命令如下所示:

$ cd /opt/tools/kafka #进入安装目录

$ bin/kafka-server-start.sh config/server.properties

「(3)第三步创建一个topic,假设为“test”」

===============================================================================================

创建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

「(4)开启Producer和Consumer服务」

==============================================================================================

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安装成功。

六、Apache Kafka 简单示例

=======================================================================================

6.1 创建消息队列

==============================================================================

kafka-topics.sh --create --zookeeper 192.168.56.137:2181 --topic test --replication-factor 1 --partitions 1

6.2 pom.xml

===============================================================================

org.apache.kafka

kafka-clients

2.1.1

6.3 生产者

===========================================================================

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();

}

}

}

注意:

  1. kafka如果是集群,多个地址用逗号分割(,) ;

  2. Properties的put方法,第一个参数可以是字符串,如:p.put(“bootstrap.servers”,“192.168.23.76:9092”) ;

  3. kafkaProducer.send(record)可以通过返回的Future来判断是否已经发送到kafka,增强消息的可靠性。同时也可以使用send的第二个参数来回调,通过回调判断是否发送成功;

  4. p.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class); 设置序列化类,可以写类的全路径。

6.4 消费者

===========================================================================

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”);

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:游动-白 设计师:我叫白小胖 返回首页

打赏作者

安卓开发YYDS

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值