kafka 生产者

kafka 生产者

    

 

  • kafka 发送数据流程

    kafka 发送数据分两个线程,主线程和sender线程,在我们使用KafkaProducer的就会帮我们实例化一个sender线程(kafka-producer-network-thread|加clientId)

    主线程:由KafkaProducer创建消息,经过拦截器、序列化器、分区器,负责发送数据到RecordAccumulator,然后缓存消息,以便sender可以批量发送。RecoredAccumulator里面会为每个分区维护一个双端队列Deque<ProducerBatch》,消息写入缓存,就是将数据追加到这个双端队列的末尾。ProducerBatch里面包含一个或者多个ProducerRecord,ProducerRecord是创建的消息,ProducerBath是一个消息批次,这样会使消息更加紧凑,减少网络请求增加吞吐量。

    sender线程:从RecordAccumulator双端队列的头部读取数据。从PartitionInfo中读取相应partition对象的Node节点,在集群Cluster中获取已经准备好的Node节点(集群中的broker节点),将数据封装到Map<Integer, List<ProducerBatch》>数据中。会按照Node,还有ack,transactionalId把数据封装到ProduceRequest中,这样每个节点就会对应一个request,就可以把这个request发送到对应的节点。会去调用KafkaClient.send()来发送数据,在发送之前会把request封装到InFlightRequest,然后加到一个双端队列Deque<NetworkClient.InFlightRequest>中,最后把数据交给selector去发送。

  • kafka器件

    1、我们可以增加自定义的拦截器,为我们数据格式化或者加指定的头

    ProducerRecord<K, V> interceptedRecord = this.interceptors.onSend(record);
    return doSend(interceptedRecord, callback);
    public class ProducerInterceptorCustom implements ProducerInterceptor<String, String> {
        @Override
        public ProducerRecord onSend(ProducerRecord record) {
            return new ProducerRecord(record.topic(), record.partition(), record.key(), "prefix" + record.value());
        }
    }
    //指定 拦截器
    properties.setProperty(ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, ProducerInterceptorCustom.class.getName());

    2、自定义序列化器

    kafka提供了多种序列化器,StringSerializer、ByteBufferSerializer、BytesSerializer等多种序列化,我们还可以选择Avro、JSON、Thrift、ProtoBuf和ProtoSuff等序列化工具来实现。发送使用序列化,消费的时候使用反序列化得到我们发送的数据。

    props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class);
    props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, ByteBufferDeserializer.class);

    3、分区器

    发送数据之前会指定我们数据发送到哪个partition,如果指定分区就发送到指定的分区,如果没有指定,如果key不为空,就采用MurmurHash2算法(高运算性能低碰撞率),hash值来计算分区;如果key为空,采用轮询的方式发送到各个分区。kafka分区内的数据是有序的,但是不同分区的数据是不能保证有序的,如果要保证数据有序,可以配置key使数据发送到同一个分区。

    //自定义分区器
    properties.setProperty(ProducerConfig.PARTITIONER_CLASS_CONFIG, ProducerPartitionCustom.class.getName());
  • 重要参数理解

    1、acks

    他是生产者发送数据可靠性和吞吐量的权衡

    acks = 1 只要分区的leader接受数据并且成功写入,就会来自服务端的成功访问。可靠性和吞吐量的折中方案。

    acks = 0 生产者发送数据,不需要等待任何的服务器相应,这种情况下吞吐量最大,但是中间出现异常却不知道。

    acks = -1或者all 发送数据之后,需要所有的ISR都成功写入,才会来自服务端的成功响应。可以达到高可靠性。

    2、reties

    生产者重试的次数,默认值是0,消息从生产者写入到服务器,可能会出现一些异常,比如网络抖动、leader选举,这一些异常是可以恢复,通过内部重试可以恢复数据,但是有一些异常是不能通过重试来恢复的,比如说消息太大,需要把异常抛到应用程序来处理。重试次数一般和retry.backoff.ms重试间隔时间同步使用。

    3、max.request.size

    最大客户端能发送消息的最大值。

    4、compression.type

    producer是否需要压缩消息,默认none。压缩消息可以减少网络消息传输从而提升吞吐量,但也会增加cpu的负担。目前kafka支持GZIP、snappy和LZ4压缩算法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值