【kafka】---kafka生产者消息确认机制和发送方式

系统间通知要求是要保证消息不丢失,那么作为生产者怎样保证消息能安全的发送到kafka集群上。

一、kafka消息确认机制

侧重于消息到达kafka集群的情况。
kafka有一个参数:“request.required.acks”。这个参数觉得了kafka消息确认机制。
properties.put(“request.required.acks”, “1”);
acks=0,Kafka Producer只要把消息发送出去,不管那条数据有没有是否落到Partition Leader磁盘上,只要消息发出去就认为这个消息发送成功了。
acks=1,只要Partition Leader接收到消息而且写入本地磁盘了,就认为成功了,不管他其他的Follower有没有同步过去这条消息了。
acks=all/-1,意思就是说Partition Leader接收到消息之后,还必须要求ISR列表里跟Leader保持同步的那些Follower都要把消息同步过去,才能认为这条消息是写入成功了。

二、kafka发送方式

上面的消息确认机制是确定消息发送到某种程度,对于一些特定场景,需要producer生产者考虑发送失败等异常下,如何去处理?
主要有三种发送方式:

2.1、发送即忘记

不关心消息是否正常到达,对返回结果不做任何判断处理。这种方式虽然吞吐量高,但无法保证消息的可靠性。

public synchronized void send(Object obj) {
        try {
            // 发送对象转JSON
            String message = JSON.toJSONString(obj);
            // 随机发送到各个节点分区
            String key = getNumPartitions();
            // 发送消息到消息中介,kafka_topic指定要接受消息的主题
            KeyedMessage<String, String> data = new KeyedMessage<String, String>(getTopic(), key, message);
            //执行发送
            getProducer().send(data);
        } catch (Exception e) {
        }
    }

2.2、同步发送

通过get方式等待kafka响应,判断消息是否成功。
-------以同步方式发送消息,每条消息发送的返回结果进行判断,是同步阻塞方式,只有返回了才能继续下一条消息发送。

public synchronized void sendV2(Object obj) {
           String message = JSON.toJSONString(obj); // 发送对象转JSON
           String key = getNumPartitions();// 随机发送到各个节点分区
            //执行发送
            ProducerRecord<String,String> data = new ProducerRecord<String,String>(getTopic(),
                    key,message);
            RecordMetadata metadata =null;        
        try {
              metadata = getKafkaProducer().send(data).get();
           } catch (Exception e) {
          }
        if(null!=metadata){
               System.out.println("同步发送后获得分区为 :" + metadata.partition() + " ,同步发送后获得offset为 :" + metadata.offset());
               }
    }

2.3、异步发送+回调函数

消息以异步方式发送,通过回调函数返回消息来确定发送成功或失败。
--------在调用send方式发送消息时,指定一个回调函数,服务器在返回响应时会调用回调函数,通过回调能够对异常情况进行处理,只有回调函数执行完毕,生产者才会结束,否则一直阻塞。

public synchronized void sendV3(Object obj) {
        try {
            String message = JSON.toJSONString(obj);  // 发送对象转JSON
            String key = getNumPartitions();// 随机发送到各个节点分区
            //执行发送
            ProducerRecord<String,String> data = new ProducerRecord<String,String>(getTopic(),
                    key,message);
            getKafkaProducer().send(data, new Callback() {
                @Override
                public void onCompletion(RecordMetadata recordMetadata, Exception e) {
                    if (recordMetadata != null) {
         //异步发送,record真正发送成功后才会执行该方法,所以可以在该方法里面获取到metadata
          System.out.println("异步发送后获得分区为 :" + recordMetadata.partition() + " ,同步发送后获得offset为 :" + recordMetadata.offset());
                    }
                }
            });
        } catch (Exception e) {
        }
    }

三、kafka发送方式场景

如果业务要求消息必须是按顺序发送的,那么可以使用同步发送方式,并且只能在一个partation上,结合参数设置retries的值让发送失败时重试,设置max_in_flight_requests_per_connection=1,可以控制生产者在收到服务器晌应之前只能发送1个消息,从而控制消息顺序发送。
如果业务只关心消息的吞吐量,容许少量消息发送失败,也不关注消息的发送顺序,那么可以使用发送并忘记方式,并配合参数acks=0,这样生产者不需要等待服务器的响应,以网络能支持的最大速度发送消息。
如果业务需要知道消息发送是否成功,并且对消息的顺序不关心,那么可以异步发送+回调函数方式来发送消息,并将发送失败的消息记录到日志文件中。

猜你喜欢

转载自blog.csdn.net/xunmengyou1990/article/details/110691992
今日推荐