Kafka学习---2、kafka生产者、异步和同步发送API、分区、生产经验(二)

简介: Kafka学习---2、kafka生产者、异步和同步发送API、分区、生产经验(二)

3、案例二

没有指明 partition 值但有 key 的情况下,将 key 的 hash 值与 topic 的 partition 数进行取余得到 partition 值。

package org.zhm.producer;
import org.apache.kafka.clients.producer.*;
import org.apache.kafka.common.serialization.StringSerializer;
import java.util.Properties;
/**
 * @ClassName CustomProducerCallback1
 * @Description TODO
 * @Author Zouhuiming
 * @Date 2023/6/12 19:21
 * @Version 1.0
 */
public class CustomProducerCallback1 {
    public static void main(String[] args) {
        Properties properties=new Properties();
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"hadoop102:9092");
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
        KafkaProducer<String,String> kafkaProducer=new KafkaProducer(properties);
        for (int i = 0; i < 5; i++) {
            //依次指定key值为a、b、f,数据key的hash值与3分别发往1、2、0
            kafkaProducer.send(new ProducerRecord<>("first", "a", "zhm" + i), new Callback() {
                @Override
                public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                    if (e==null){
                        System.out.println("当key为a时:"+"主题:"+recordMetadata.topic()+"分区:"+recordMetadata.partition());
                    }else {
                        e.printStackTrace();
                    }
                }
            });
        }
        for (int i = 0; i < 5; i++) {
            //依次指定key值为a、b、f,数据key的hash值与3分别发往1、2、0
            kafkaProducer.send(new ProducerRecord<>("first", "b", "zhm" + i), new Callback() {
                @Override
                public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                    if (e==null){
                        System.out.println("当key为b时:"+"主题:"+recordMetadata.topic()+"分区:"+recordMetadata.partition());
                    }else {
                        e.printStackTrace();
                    }
                }
            });
        }
        for (int i = 0; i < 5; i++) {
            //依次指定key值为a、b、f,数据key的hash值与3分别发往1、2、0
            kafkaProducer.send(new ProducerRecord<>("first", "f", "zhm" + i), new Callback() {
                @Override
                public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                    if (e==null){
                        System.out.println("当key为f时:"+"主题:"+recordMetadata.topic()+"分区:"+recordMetadata.partition());
                    }else {
                        e.printStackTrace();
                    }
                }
            });
        }
        kafkaProducer.close();
    }
}

(1)测试

①在 hadoop102 上开启 Kafka 消费者。

bin/kafka-console-consumer.sh --bootstrap-server hadoop102:9092 --topic first

②在 IDEA 中执行代码,观察 hadoop102 控制台中是否接收到消息。


096b2f525c0042fcb2f2817eda645082.png1.4.3

1.4.3 自定义分区器

如果研发人员可以根据企业需求,自己重新实现分区器

1、例如我们实现一个分区器实现,发送过来的数据中如果包含 atguigu,就发往 0 号分区,不包含 atguigu,就发往 1 号分区。

2、案例实现

(1)定义类实现 Partitioner 接口。

(2)重写 partition()方法。

package org.zhm.producer;
import org.apache.kafka.clients.producer.Partitioner;
import org.apache.kafka.common.Cluster;
import java.util.Map;
/**
 * @ClassName Mypartitioner
 * @Description TODO
 * @Author Zouhuiming
 * @Date 2023/6/12 19:28
 * @Version 1.0
 */
/**
 1、实现接口Partitioner
 2、实现三个方法:Partition、close、configure
 3、编写Partition方法,返回分区号
 */
public class MyPartitioner implements Partitioner {
    /*
    *
     * @description:返回信息对应的分区
     * @author: zouhuiming
     * @date: 2023/6/12 19:30
     * @param: [s, o, bytes, o1, bytes1, cluster]
     * [主题、消息的key、消息的key序列化后的字节数组、消息的value、消息的value序列哈后字节数组、集群元数据可以查看的分区信息]
     * @return: int
     **/
    @Override
    public int partition(String s, Object o, byte[] bytes, Object o1, byte[] bytes1, Cluster cluster) {
        //获取信息
        String msyValue = o1.toString();
        //创建partition
        int partition;
        //判断信息是否包含zhm
        if (msyValue.contains("zhm")){
            partition=0;
        }
        else {
            partition=1;
        }
        //返回分区号
        return partition;
    }
    @Override
    public void close() {
    }
    @Override
    public void configure(Map<String, ?> map) {
    }
}

(3)使用分区器的方法,在生产者的配置中添加分区器参数。

package org.zhm.producer;
import org.apache.kafka.clients.producer.*;
import org.apache.kafka.common.serialization.StringSerializer;
import java.util.Properties;
/**
 * @ClassName CustomProducerCallbackPartitionsMine
 * @Description TODO
 * @Author Zouhuiming
 * @Date 2023/6/12 19:35
 * @Version 1.0
 */
public class CustomProducerCallbackPartitionsMine {
    public static void main(String[] args) {
        Properties properties=new Properties();
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG,"hadoop102:9092");
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG,StringSerializer.class.getName());
        //添加自定义分区器
        properties.put(ProducerConfig.PARTITIONER_CLASS_CONFIG,"org.zhm.producer.MyPartitioner");
        KafkaProducer<String,String> kafkaProducer=new KafkaProducer<String, String>(properties);
        for (int i = 0; i < 5; i++) {
            kafkaProducer.send(new ProducerRecord<>("first", "zhm" + i), new Callback() {
                @Override
                public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                    if (e==null){
                        System.out.println("主题:"+recordMetadata.topic()+"分区:"+recordMetadata.partition());
                    }else {
                        e.printStackTrace();
                    }
                }
            });
        }
        for (int i = 0; i < 5; i++) {
            kafkaProducer.send(new ProducerRecord<>("first", "hello" + i), new Callback() {
                @Override
                public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                    if (e==null){
                        System.out.println("主题:"+recordMetadata.topic()+"分区:"+recordMetadata.partition());
                    }else {
                        e.printStackTrace();
                    }
                }
            });
        }
        kafkaProducer.close();
    }
}

(4)测试

①在 hadoop102 上开启 Kafka 消费者。

bin/kafka-console-consumer.sh --bootstrap-server hadoop102:9092 --topic first

②在 IDEA 控制台观察回调信息。


6db2cf3c8d88468baf9f3146649c76e5.png

1.5 生产经验——生产者如何提高吞吐量

  • batch.size:批次大小,默认16k
  • linger.ms:等待时间,修改为5-100ms
  • compression.type:压缩snappy
  • RecordAccumulator:缓存区大小,修改1为64MB

1.6 生产经验——数据可靠性

1、ack应答原理


c5dca299ef18494f9f9149c6a806fdef.png

1f972ebfa731484685839e2681177725.png

可靠性总结:

acks=0,生产者发送过来数据就不管了,可靠性差,效率高;

acks=1,生产者发送过来数据Leader应答,可靠性中等,效率中等;

acks=-1(all),,生产者发送过来数据Leader和ISR队列里面所有Follwer应答,可靠性高,效率低;

在生产环境中,acks=0很少使用;acks=1,一般用于传输普通日志,允许丢个别数据;acks=-1,一般用于传输和钱相关的数据,对可靠性要求比较高的场景。

数据重复分析


cbe1bd09d5f04fc8877554560bdc7fb1.png

1.7 生产经验——数据去重

1.7.1 数据传递语义

至少一次(At Least Once) =ACK级别设置为-1+分区副本数大于等于2+ISR里应答的最小副本数量大于等于2

最多一次(At Most Once)=ACK级别设置为0

总结

At Least Once可以保证数据不丢失,但是不能保证数据不重复;

At Most Once可以保证数据不重复,但是不能保证数据不丢失。

精确一次(Exactly Once):对于一些非常重要的信息,比如和钱相关的数据,要求数据既不能重复也不丢失。Kafka 0.11版本以后,引入了一项重大特性:幂等性和事务。

1.7.2 幂等性

幂等性就是指Producer不论向Broker发送多少次重复数据,Broker端都只会持久化一条,保证了不重复。

精确一次(Exactly Once) = 幂等性 + 至少一次( ack=-1 + 分区副本数>=2 + ISR最小副本数量>=2) 。

重复数据的判断标准:具有<PID,Partition,SeqNumber>相同主键的消息提交时,Broker只会持久化一条。其中PID是Kafka每次重启都会分配一个新的;Partition表示分区号;Sequence Number是单调自增的。

所以幂等性只能保证的是在单分区单会话内不重复。

2a46e4c62cfd417bbd35adf4c7bfd87c.png

如何启用幂等性

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

1.7.3 生产者事务

1、Kafka事务原理

注意:开启事务,必须开启幂等性

77ca8957460f4f7fa4d9d25201b12839.png

2、Kafka 的事务一共有如下 5 个 API

// 1 初始化事务
void initTransactions();
// 2 开启事务
void beginTransaction() throws ProducerFencedException;
// 3 在事务内提交已经消费的偏移量(主要用于消费者)
void sendOffsetsToTransaction(Map<TopicPartition, OffsetAndMetadata> offsets,
 String consumerGroupId) throws 
ProducerFencedException;
// 4 提交事务
void commitTransaction() throws ProducerFencedException;
// 5 放弃事务(类似于回滚事务的操作)
void abortTransaction() throws ProducerFencedException;

1.8 生产经验——数据有序

3bf19989412c45a08227b0c997189af4.png

1.8 生产检验——数据乱序


1、kafka在1.x版本之前保证数据单分区有序,条件如下:

max.in.flight.requests.per.connection=1(不需要考虑是否开启幂等性)。

2、kafka在1.x及以后版本保证数据单分区有序,条件如下:

(1)未开启幂等性

max.in.flight.requests.per.connection需要设置为1。

(2)开启幂等性

max.in.flight.requests.per.connection需要设置小于等于5。

原因说明:因为在kafka1.x以后,启用幂等后,kafka服务端会缓存producer发来的最近5个request的元数据,故无论如何,都可以保证最近5个request的数据都是有序的。

31747b30cbe04ca6a2d8d285d22cf028.png

相关文章
|
11月前
|
机器学习/深度学习 人工智能 缓存
电商 API 接口:开启全平台商品信息同步新时代
在数字化浪潮下,电商平台激增,消费者跨平台购物成为常态。然而,商品信息分散导致数据不一致、库存混乱等问题。电商 API 接口应运而生,通过标准化数据交换,实现多平台商品信息实时同步,提升运营效率、降低成本、增强用户体验,成为企业数字化转型的关键引擎。
|
9月前
|
缓存 边缘计算 监控
89_批量推理:异步API调用
在当今数据密集型应用和大模型部署的时代,批量推理已成为提升系统性能和资源利用率的关键技术。随着深度学习模型规模的不断扩大和应用场景的日益复杂,如何高效地处理大量推理请求成为技术团队面临的重要挑战。传统的同步API调用方式在面对高并发、大规模数据处理时,往往会遇到响应延迟高、资源利用不充分等问题。异步API调用作为一种更高效的处理模式,通过非阻塞操作和并发处理能力,为批量推理场景提供了理想的解决方案。
677 0
|
10月前
|
存储 JSON 监控
淘宝/天猫:通过商品详情API实现多店铺商品信息批量同步,确保价格、库存实时更新
在电商运营中,管理多个淘宝或天猫店铺的商品信息(如价格、库存)耗时易错。本文介绍如何通过淘宝/天猫开放平台的商品详情API,实现自动化批量同步,确保信息实时更新。内容涵盖API调用、多店铺数据处理、实时更新策略及注意事项,助您高效管理多店铺商品信息。
|
11月前
|
人工智能 JSON 监控
电商 API 赋能,多平台促销活动精准同步
在电商多平台促销中,手动管理易导致价格混乱、库存超卖等问题。电商 API 通过自动化实现促销活动的精准同步,提升效率、减少错误,助力企业高效运营,实现销售增长与成本节约,是电商数字化转型的关键工具。
|
12月前
|
供应链 安全 API
淘宝API一键同步库存,销量翻倍轻松实现!
在电商竞争激烈的当下,库存管理是提升销量的关键。淘宝开放平台提供API接口,支持一键同步库存,实现线上线下数据实时更新,避免缺货或超卖。本文详解操作步骤,并附Python示例代码,助你轻松掌握自动化库存管理,提升转化率,实现销量翻倍。
|
JSON 人工智能 自然语言处理
根据标题利用API实现电商多平台同步:省时省力生成文章
在电商运营中,多平台同步产品信息、库存和订单数据至关重要。手动操作耗时易错,而通过API实现自动化同步,不仅能提升效率,还可结合内容生成工具自动创建产品文章。本文详解如何利用API完成数据同步与内容生成,帮助商家节省时间、减少错误、优化成本,提升运营效率。
|
9月前
|
缓存 监控 前端开发
顺企网 API 开发实战:搜索 / 详情接口从 0 到 1 落地(附 Elasticsearch 优化 + 错误速查)
企业API开发常陷参数、缓存、错误处理三大坑?本指南拆解顺企网双接口全流程,涵盖搜索优化、签名验证、限流应对,附可复用代码与错误速查表,助你2小时高效搞定开发,提升响应速度与稳定性。
|
10月前
|
数据可视化 测试技术 API
从接口性能到稳定性:这些API调试工具,让你的开发过程事半功倍
在软件开发中,接口调试与测试对接口性能、稳定性、准确性及团队协作至关重要。随着开发节奏加快,传统方式已难满足需求,专业API工具成为首选。本文介绍了Apifox、Postman、YApi、SoapUI、JMeter、Swagger等主流工具,对比其功能与适用场景,并推荐Apifox作为集成度高、支持中文、可视化强的一体化解决方案,助力提升API开发与测试效率。
|
9月前
|
JSON 算法 API
Python采集淘宝商品评论API接口及JSON数据返回全程指南
Python采集淘宝商品评论API接口及JSON数据返回全程指南
|
9月前
|
JSON API 数据安全/隐私保护
Python采集淘宝拍立淘按图搜索API接口及JSON数据返回全流程指南
通过以上流程,可实现淘宝拍立淘按图搜索的完整调用链路,并获取结构化的JSON商品数据,支撑电商比价、智能推荐等业务场景。

热门文章

最新文章