KAFKA第二课之生产者(面试重点)

news/2024/11/23 2:50:30/

生产者学习

1.1 生产者消息发送流程

在消息发送的过程中,涉及到了两个线程——main线程和Sender线程。在main线程中创建了一个双端队列RecordAccumulator。main线程将消息发送给RecordAccumulator,Sender线程不断从RecordAccumulator中拉取消息发送到Kafka Broker。
生产者如何发送的?
现在Main线程中将数据进行处理,处理成IO型数据,然后调用sender进行发送
Main:
1.读取生产者配置
2.产生数据
3.过滤数据(校验什么的)
4.序列化
5.放入缓冲区 RecordAccumulator
6.发送Sender

细节: 考虑的问题 1.生产者配置的读取和修改 2.数据的过滤与分区, 3.缓冲区是如何设置的,大小
4.发送(发送失败怎么样,请求区的大小)
这里注意一下,可以在缓冲区对数据进行压缩,这样就提高缓冲区的容量和发送的数据量,提高吞吐量

1.2 同步发送与异步发送

1.什么是同步和异步

同步就是,串行,一条龙 异步 一起运行
举例: 餐馆点餐
同步: 需要等服务员过来,让服务员记录,
异步: 点餐APP直接点餐,交给队列,让他自己运行

2.发送的同步异步

同步:需要得到返回值
异步:发送过去不管了

3. 分区好处

啥是分区?
将一个数据块分成多个数据块
将数据分布式处理了
存储: 可以分在多个机器上, 也可以整多个副本。便于存储,同时提高健壮性
IO:多个数据块可以同时进行发送接收消费。生产者可以以分区为单位发送数据,消费者可以以分区为单位进行消费

4. 默认分区器

前提条件: 1.分区 2.key值
规则:

  • 1存在,按1分区
  • 1不存在,按2.key值对分区数取余得到的值分区
  • 1.2都不存在 随机选个分区,等这个批次发送完了,再换

3 就是粘性分区
那么粘性分区的缺点是什么?
因为缓冲区溢出的条件是,大小和时间双重判断,如果大小不够,但是时间够了,还是会发走,这样,最后导致,分区上产生数据倾斜
如何解决的?
3.3.1 Kafka去掉粘性分区的时间控制,批次只由大小判断

1.3.自定义分区器

1.思路

  • 1.实现接口Parititoner,重写相关方法
  • 2.修改配置 将partitioner设置为默认配置

2.1 自定义分区器代码

public class MyPartitioner implements Partitioner {//  自定义分区器 实现partitioner接口// 1.分区方法@Overridepublic int partition(String topic, Object key, byte[] keyBytes, Object value, byte[] valueBytes, Cluster cluster) {// 获取消息String data = value.toString();// 创建partition 作为最后的分区标识int partitions;// 分区逻辑// 根据含有的字符串进行判断 判断进入哪个分区if (data.contains("atguigu")){partitions = 0;} else if (data.contains("shangguigu")){partitions = 1;} else {partitions = 2;}return partitions;}@Overridepublic void close() {}@Overridepublic void configure(Map<String, ?> configs) {}
}

2.2 主类

package com.atguigu.producer;import org.apache.kafka.clients.producer.*;
import org.apache.kafka.common.serialization.StringSerializer;import java.util.Properties;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;public class ProducerClientAsync {public static void main(String[] args) {// 0 配置对象Properties properties = new Properties();//  --指定kafka的Broker地址properties.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "hadoop102:9092,hadoop103:9092");//  -- 1.指定序列化器 序列化器的全限定类名properties.setProperty(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());properties.setProperty(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());//.setProperty(ProducerConfig.LINGER_MS_CONFIG,"0");// -- 2.设置分区器properties.setProperty(ProducerConfig.PARTITIONER_CLASS_CONFIG,MyPartitioner.class.getName());// -- 3.获取客户端连接对象KafkaProducer<String,String> kafkaProducer= new KafkaProducer<String,String>(properties);//  key是主题  v是发送内容  这里注意一下// -- 4.发送数据String[] str= {"atguigu","111","atguigu","shangguigu","222"};for (int i =0; i < str.length; i++) {System.out.println(str[i]);try {kafkaProducer.send(new ProducerRecord<>("first", str[i]), new Callback() {@Overridepublic void onCompletion(RecordMetadata metadata, Exception exception) {if (exception == null){System.out.println("主题:" + metadata.topic() + "->"  + "分区:" + metadata.partition());}else {// 出现异常打印exception.printStackTrace();}}}).get();} catch (InterruptedException e) {throw new RuntimeException(e);} catch (ExecutionException e) {throw new RuntimeException(e);}}kafkaProducer.close();}
}

在这里插入图片描述

3.面试细节

1.如何提高生产者的吞吐量

  • 批次大小调到16
  • 将等待时间改成50-100ms 默认是0
  • 压缩数据量,这样每次发送的数据就多了
  • 加大缓冲区大小,进来的数据变多,发送也能提上去

2.生产者如何保证数据可靠性的

主要通过ack机制

1.什么是ACK机制?

根据ack值来决定Kafka集群服务端的存储应答

  • ack=0 最低 生产者只管发送,不用接收
  • ack=1 中等 生产者发送完需要等待Leader保存后回应,
  • ack=-1 最高 生产者发送完需要等待所有副本保存后回应

2.分析ACK机制

性能与安全是成反比的
所以,-1虽然最安全,但是效率最低

3.如果将ACK调到-1会出现什么问题?

有可能出现数据重复发送与接收
比如,在同步的瞬间,Leader死掉,但是其他副本已经落盘,这时候,就是问题了。
因为Leader死掉了,所以会直接更换Leader,选出一个副本作为Leader,注意,这时显示没有收到内容,所以,send重新发送,这时候,每个副本上,收到的就是2份该数据了。

4.应用场景

acks=0 几乎不用
acks=1 传输普通日志,允许丢失
acks=-1 传输高可靠性数据,一般与钱有关

5.ACK=-1一定可靠么?

不一定
如果分区副本数设置为1 ,或者ISR里应答的最小副本数设置为1(默认也是1),这时候,ack=1效果相同了。
也就是说,应答一个,就能走,就没意义了
所以需要完全可靠就需要配置一下
ACK=-1 & 分区副本大于等于2 & ISR应答最小副本数量大于等于2

3. 数据去重

1.概念

至少一次:一次或者多次 完全可靠
在这里插入图片描述
最多一次:直接不管回复只管发送 ack=0

至少:保证数据不丢失,但是无法保证数据不重复
最多: 无法保证数据不丢失

1.如何解决数据的重复发送与接收的问题,同时保证数据的不丢失

注意,这里解决的是sender和服务端的重复发送与接收,而不是生产者本身发送多个重复消息的问题,这个要搞清楚。
一般重复问题,都是通过标识来判别,从而去重的
Kafka 0.11 引入 幂等性和事务
精确一次: 幂等性 +至少一次(ack=-1 & 分区副本>=2 & ISR最小副本>=2)

4.幂等性

1.概念

啥是幂等性,标识一个消息的唯一标识
<pid,partition,Seqnumber>
Pid 是会话ID,每次重新生成会话,就会重新生成PID
partition是分区 标识 消息是哪个分区的
Seqnumber是单调递增的标识,注意,这是每个分区独享的
这三个在一起,才是唯一标识。

2.如何使用幂等性

开启参数enable.idempotence 默认为true,false关闭。
开启开关就行


http://www.ppmy.cn/news/1024949.html

相关文章

Spring-2-深入理解Spring 注解依赖注入(DI):简化Java应用程序开发

今日目标 掌握纯注解开发依赖注入(DI)模式 学习使用纯注解进行第三方Bean注入 1 注解开发依赖注入(DI)【重点】 问题导入 思考:如何使用注解方式将Bean对象注入到类中 1.1 使用Autowired注解开启自动装配模式&#xff08;按类型&#xff09; Service public class StudentS…

JAVA设计模式汇总

文章目录 一、设计模式分为三大类二、设计模式的六大原则三、汇总 一、设计模式分为三大类 创建型模式共五种&#xff1a;工厂方法模式、抽象工厂模式、单例模式、建造者模式、原型模式。 结构型模式共七种&#xff1a;适配器模式、装饰器模式、代理模式、外观模式、桥接模式…

不基于比较的排序:基数排序

本篇只是讨论桶排序的具体实现&#xff0c;想了解更多算法内容可以在我的博客里搜&#xff0c;建议大家看看这篇排序算法总结&#xff1a;排序算法总结_鱼跃鹰飞的博客-CSDN博客 桶排序的原理&#xff1a; 代码&#xff1a;sort1是一个比较二逼的实现方式浪费空间&#xff0c;s…

Leetcode.2789 合并后数组中的最大元素

题目链接 Leetcode.2789 合并后数组中的最大元素 rating : 1485 题目描述 给你一个下标从 0 0 0 开始、由正整数组成的数组 n u m s nums nums 。 你可以在数组上执行下述操作 任意 次&#xff1a; 选中一个同时满足 0 ≤ i < n u m s . l e n g t h − 1 0 \leq i &l…

【React | 前端】在React的前端页面中,判断某个变量值是否被定义?根据是否定义显示不同的内容?

问题描述 在React的前端页面中&#xff0c;判断某个变量值是否被定义&#xff1f;根据是否定义显示不同的内容&#xff1f; 问题场景 假如&#xff0c;现在有一个需求是设计一个新功能&#xff0c;新功能中要求新增一个之前没有的变量&#xff0c;假设是计算某一个数组的长度…

微服务05-Sentinel流量防卫兵

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以 流量 为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。 S…

什么是分布式系统,如何学习分布式系统

正文 虽然本人在前面也写过好几篇分布式系统相关的文章&#xff0c;主要包CAP理论&#xff0c;分布式储存与分布式事务&#xff0c;但对于分布式系统&#xff0c;并没有一个跟清晰的概念。分布式系统涉及到很多的技术、理论与协议&#xff0c;很多人也说&#xff0c;分布式系统…

go练习 day02

go中使用mongodb实现增删改查 连接mongodb yaml配置 mongodb:uri: mongodb://localhost:27017初始化连接 package confimport ("context""fmt""time""github.com/spf13/viper""go.mongodb.org/mongo-driver/mongo""…