Kafka知识整理系列一

Kafka生产者

在这里插入图片描述

我们用java去写一个kafka生产者,通常有以下步骤及参数需要设置

  1. 配置Properties参数。Properties相当于一个配置文件,配置信息都以key-value的形式进行存储。
Properties properties = new Properties(参数名,参数值);
  1. 构建KafkaProducer。顾名思义是一个kafka生产者,把第一步的配置文件放到里面,会根据配置信息创建一个producer
KafkaProducer producer = new KafkaProducer(properties);
  1. 构建待发送的消息ProducerRecord。并指定一个topic,把消息send出去
producer.send(new ProducerRecord<String,String>(发送的目的topic,发送的消息));
  1. 关闭producer
producer.close();

这是构建一个生产者的必要步骤
重点来了,这是一些必要的参数设置,意思是一定要配置

  1. bootstrap.server:配置kafka集群地址。
  2. key.serializer以及value.serializer:配置转换字节数组所需要的序列化器(消息发送出去,存储到kafka当中,肯定是需要经过序列化的,就好像java当中,把对象信息存储到mysql当中)

例子:
在这里插入图片描述

一个简单的生产者demo

kafka生产者消费者代码网上有很多,我这里给出一个简单的配置:
首先是pom:

<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka-clients</artifactId>
    <version>0.11.0.0</version>
</dependency>
<dependency>
    <groupId>org.apache.kafka</groupId>
    <artifactId>kafka_2.12</artifactId>
    <version>0.11.0.0</version>
</dependency>

生产者代码:

package com.pro.kafka;

import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;

import java.util.Properties;

public class Test {
    public static void main(String[] args) {
        // 第一步,创建配置文件并把配置信息放入进去
        Properties properties = new Properties();
        // 设置集群地址,value用ip:9092的形式
        properties.put("bootstrap.servers", "node1:9092");
        // 设置应答机制,all是需要等待所有副本节点的应答
        properties.put("acks", "all");
        // 消息发送最大尝试次数
        properties.put("retries", "0");
        // 处理一批消息的大小
        properties.put("batch.size", "16384");
        // 请求延时
        properties.put("linger.ms", "1");
        // 发送缓存区内存大小
        properties.put("buffer.memory", "33554432");
        // key序列化,序列化器可使用StringSerializer
        properties.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        // value序列化,序列化器可使用StringSerializer
        properties.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
        // 第二步,根据配置文件创建一个KafkaProducer
        KafkaProducer producer = new KafkaProducer(properties);
        // 第三步,模拟发送消息
        for (int i = 0; i < 5; i++) {
            producer.send(new ProducerRecord<String, String>("test", "hello" + i));
        }
        // 第四步,关闭producer
        producer.close();
    }
}

生产者的几种发送模式以及重要参数

  1. fire-and-forget:只管发送,不关系消息是否到达目的地。
  2. sync(同步):send()调用之后,会返回一个Future类型的对象,可以通过get()来阻塞任务发送的结果,并做出相应的处理。
Future future = producer.send(new ProducerRecord<String,String>(发送的目的topic,发送的消息));
// 这里就可以获得任务发送的一个结果
Object data = future.get();
  1. async(异步):通过向Future注册一个回调函数Callback。

重要参数:
在这里插入图片描述

Kafka消费者

消费者和消费者组的概念

首先消费者不同于生产者,需要注意以下两点:

  1. 消费者具有消费组的这么一个概念。
  2. 每个分区只能被一个消费者组的一个消费者消费。
  3. 消费者是一个实际的应用实例,可以作为一个线程or一个进程。
  4. 同组内的消费者是竞争关系。

消费者的消费步骤:

  1. 配置参数(Properties)参考生产者。
  2. 创建一个KafkaConsumer实例。
  3. 订阅主题topic。
  4. 拉去消息并消费。
  5. 提交消费位移(offset)。
  6. 关闭实例。

同样,消费者也有必须要配置的信息:

  1. bootstrap.servers:集群broker的地址
  2. group.id:消费者组的id
  3. key/value.deserializer:反序列化器

其他的重要参数:
在这里插入图片描述

Kafka消息的存储

消息存储的方式:
在这里插入图片描述
kafka的消息,以topic为单位进行归类
总结为以下几点:

  1. topic与partition(分区)为一对多的关系。
  2. 每个分区可以看做一个可追加的日志文件。(新加的消息从尾巴添加)
  3. 消息在追加到分区的时候,会分配一个偏移量(offset 一个唯一标识)
  4. kafka通过偏移量来保证消息在分区内的一个顺序(但是只能够保证分区有序,而不能保证topic有序,也因此上文中,kafka消费消息后,offset需要提交消费位移offset

存储的地址

kafka把消息发送到broker(一个节点上)后,将消息存储到磁盘上,通过日志的方式来持久化信息。
目录的名称有一定的规律,格式为 [topic名称]-[分区号],如图:
在这里插入图片描述
顺便一提,存放地址可以通过配置server.properties文件来更改:
在这里插入图片描述

存放文件目录的组成

打开上图一个分区目录,进去查看目录结构:
在这里插入图片描述
发现了有两种文件:

  1. .index文件:存储索引的文件
  2. .log文件:存储数据

kafka通过分段的方式将数据分为LogSegment,而每一个LogSegment就包括一个index文件和一个log文件。并且每一个Segment文件的命名也有一定的规则,末尾的数字就是这个消息的offset值(并且由上一个Segment中最后一条消息的offset值决定)
在这里插入图片描述

kafka查看日志的命令

如果直接用cat命令或者vi命令去查看肯定是不行的,会乱码,最好用kafka自带的脚本去查看:

bin/kafka-run-class.sh kafka.tools.DumpLogSegments --files /日志地址/xxx.log --print-data-log

在这里插入图片描述
具体参数的意义:

单词意义
position偏移量
magic消息格式版本号
compresscodec压缩编码
playload偏移数据
offset记录号

另外,每个索引会对应着一个数字,而这个数字是这条消息在日志文件当中的位置,相当于一个映射
在这里插入图片描述

Partition如何根据offset去查找信息

  1. 根据offset值,查找segment段中的index索引文件,使用二分查找去定位索引文件的位置。
  2. 找到索引后,通过offset寻找对应匹配的偏移量position
  3. 得到position后,到目标对应的log文件中,从position(一个数字)处开始,查找offset对应的消息。

举个例子:
再把上文的图拿来用一用:
在这里插入图片描述
比如此处,我需要查找offset=2490的消息
步骤如下:

  1. 先找到00000xxx.index索引文件
  2. 找到[2487,49111]这一行索引(图中第三行),此时得到position为49111
  3. 到对应的00000xxx.log文件中,从49111处开始查找,比较每条消息的offset是不是为2490
  4. 如果是,则返回

kafka副本机制

kafka有一个多副本机制:

  1. 也就是说,一个分区会在多个副本中存储相同的信息,并且副本与副本之间存在主从关系。
  2. 有一个副本作为主副本,负责读和写,另外的从副本只有读的功能,只负责备份。
  3. 从副本在主副本挂的时候,可以成为竞争为主副本。

一些kafka专业术语

副本术语

缩写意义
ISR由与leader保持一定程度的同步关系的副本组成
OSR由同步之后,剩下的的副本组成Out-Of-Sync Replica
AR分区中所有的副本称为AR

偏移量术语

缩写意义
LEO标识当前分区下一条待写入消息的offset(Log End Offset)
HW高水位,consumer只能拉取到此offset之前的消息(High WaterMark)

kafka副本的作用有哪些

看下副本的图:
在这里插入图片描述
上图大概意思是:

  1. 每个topic有多个分区
  2. 每个分区有多个副本
  3. 副本之间又存在主从副本
  4. 副本又分布在不同的broker上。

副本的解释:

  1. kafka中的副本,本质上是一个能够追加写消息的日志。
  2. 同一个分区下的所有副本保存相同的消息序列。
  3. 分工明确,一个主副本,负责接收处理某一个分区下的所有读写请求。
  4. 从副本不对外提供服务,唯一的任务就是与leader 副本同步数据

副本的具体作用:

  1. 提供数据的冗余,实现高可用。(这个不难理解,毕竟有备份)
  2. 方便实现Read-yours-writes:即生产者成功向kafka中写入消息的时候,马上使用消费者去读取刚刚生产的消息
    (如果允许从副本提供服务,那么由于kafka数据的同步是异步的,所以无法保证client从 从副本中获取的数据为最新的,也因此只能够运行从主副本中读取数据)
  3. 方便实现单调读Monotonic Reads:对于一个消费者而言,在多次消费消息的时候,不会看到某一个消息时而在时而不在的情况

这里假设:允许从副本提供服务,并假设有两个从副本,分别叫做A和B副本,他们异步拉去leader主副本的数据,放图(手画的不好,将就下)
在这里插入图片描述
因此出现数据消费结果不一致的情况,也因此,所有请求都交给leader去处理。即实现了单调读一致性,

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zong_0915

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

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

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

打赏作者

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

抵扣说明:

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

余额充值