kafka基础【数据重复消费、自定义拦截器、flume对接kafka、eagle监视器】

一 数据漏消费和重复消费

无论是同步提交还是异步提交offset,都有可能会造成数据的漏消费或者重复消费。先提交offset后消费,有可能造成数据的漏消费;而先消费后提交offset,有可能会造成数据的重复消费。

重复消费解决方案:

(1)下游去重:但是缺点是kafka采取了幂等性和事务,保证了kafka服务端消息没有重复的情况下,下游去重浪费了kafka的性能

(2)确保数据的消费和提交两个操作是原子性的,要么同时成功,要么同时失败。原子化绑定的前提是提交动作不能往kafka服务端提交,因为往kafka服务端提交与消费动作无法实现原子绑定。因此想实现原子化绑定,需要自己保存offset,而不是让kafka帮我们保存offset。

手动保存offset

package com.hike.consumer;

import org.apache.kafka.clients.consumer.ConsumerRebalanceListener;
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.TopicPartition;

import java.io.*;
import java.util.*;

/**
 * 自定义保存offset
 */
public class ConsumerManual {
   
    //记录每个消费者消费的offset,缓存
    private static Map<TopicPartition,Long> offset = new HashMap<TopicPartition, Long>();
    //用来保存Hash值
    private static String file = "d:/offset";

    public static void main(String[] args) throws IOException, InterruptedException {
   
        //1 新建一个consumer对象
        Properties properties = new Properties();
        properties.load(Consumer.class.getClassLoader().getResourceAsStream("consumer1.properties"));
        final KafkaConsumer<String, String> consumer = new KafkaConsumer<String, String>(properties);
        //2 订阅话题,拉取消息
        consumer.subscribe(Collections.singleton("hello"),
                //每当有一个新的消费者加入到consumerGroup都会重新进行分区分配
                new ConsumerRebalanceListener() {
   
            //新加入进来的consumer应该从之前组中的consumer消费过的地方开始消费,而不是从0开始
            //之前由kafka服务器负责告知,现在采用自定义保存offset的方式,服务器不知道消费的位置
            //需要手动的告诉新加入的消费者,需要分别执行以下两个函数,完成此项功能

            //分区分配之前做的事情
            public void onPartitionsRevoked(Collection<TopicPartition> partitions) {
   
                //各个消费者应该将旧的offset提交
                commit();
            }

            //分区分配之后做的事情
            public void onPartitionsAssigned(Collection<TopicPartition> partitions) {
   
                //各个消费者应该将offset遍历,获取新的offset
                readOffset(partitions);
                //遍历所有分区,将offset读取出来,告诉消费者从哪里开始消费
                for (TopicPartition partition : partitions) {
   
                    Long os = offset.get(partition);
                    if (os == null) {
   
                        consumer.seek(partition, 0);
                    } else {
   
                        consumer.seek(partition, os);
                    }
                }
            }
        });

        //消费消息
        while(true){
   
            ConsumerRecords<String, String> records = consumer.poll(2000);
            //将此部分的操作原子绑定
            {
   
                for (ConsumerRecord<String, String> record : records) {
   
                    System.out.println(record);
                    //将获取到的数据存放到高速缓存中
                    offset.put(
                            new TopicPartition(record.topic(), record<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

OneTenTwo76

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

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

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

打赏作者

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

抵扣说明:

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

余额充值