kafka 维护消费状态跟踪的方法和消费进度的跟踪

 kafka 维护消费状态跟踪

大部分消息系统在 broker 端的维护消息被消费的记录:一个消息被分发到consumer 后 broker 就马上进行标记或者等待 customer 的通知后进行标记。这样也可以在消息在消费后立马删除以减少空间占用。

但是这样会不会有什么问题呢?如果一条消息发送出去之后就立即被标记为消费过的,一旦 consumer处理消息时失败了(比如程序崩溃)消息就丢失了。

为了解决这个问题,很多消息系统提供了另外一个个功能:当消息被发送出去之后仅仅被标记为已发送状态,当接到 consumer 已经消费成功的通知后才标记为已被消费的状态。

这虽然解决了消息丢失的问题,但产生了新问题,首先如果 consumer处理消息成功了但是向 broker 发送响应时失败了,这条消息将被消费两次。第二个问题时,broker 必须维护每条消息的状态,并且每次都要先锁住消息然后更改状态然后释放锁》这样麻烦又来了,且不说要维护大量的状态数据,比如如果消息发送出去但没有收到消费成功的通知,这条消息将一直处于被锁定的状态

Kafka 采用了不同的策略.Topic 被分成了若干分区,每个分区在同一时间只被一个 consumer 消费。这意味着每个分区被消费的消息在日志中的位置仅仅是一个简单的整数:offset。这样就很容易标记每个分区消费状态就很容易了,仅仅需要一个整数而已。这样消费状态的跟踪就很简单了。这带来了另外一个好处:consumer 可以把 offset 调成一个较老的值,去重新消费老的消息。这对传统的消息系统来说看起来有些不可思议,但确实是非常有用的,谁规定了一条消息只能被消费一次呢?
 

 消费进度的跟踪

  1. 所谓滞后程度,就是指消费者当前落后于生产者的程度。
  2. Lag 应该算是最最重要的监控指标了。它直接反映了一个消费者的运行情况。一个正常工作的消费者,它的 Lag 值应该很小,甚至是接近于 0 的,这表示该消费者能够及时地消费生产者生产出来的消息,滞后程度很小。反之,如果一个消费者 Lag 值很大,通常就表明它无法跟上生产者的速度,最终 Lag 会越来越大,从而拖慢下游消息的处理速度。
  3. 通常来说,Lag 的单位是消息数,而且我们一般是在主题这个级别上讨论 Lag 的,但实际上,Kafka 监控 Lag 的层级是在分区上的。如果要计算主题级别的,你需要手动汇总所有主题分区的 Lag,将它们累加起来,合并成最终的 Lag 值。
  4. 你在实际业务场景中必须时刻关注消费者的消费进度。
  5. 使用 Kafka 自带的命令行工具 kafka-consumer-groups 脚本。
  6. 使用 Kafka Java Consumer API 编程。
  7. 使用 Kafka 自带的 JMX 监控指标。
  8. 消费进度监控3 种方法。
  9. Kafka 自带命令

  10.  Kafka 自带的命令行工具 bin/kafka-consumer-groups.sh
  11. kafka-consumer-groups 脚本是 Kafka 为我们提供的最直接的监控消费者消费进度的工具。
  12. bin/kafka-consumer-groups.sh --bootstrap-server <Kafka broker连接信息> --describe --group <group名称>
  13.  
  14. Kafka 连接信息就是 < 主机名:端口 > 对,而 group 名称就是你的消费者程序中设置的 group.id 值。
  15. 示例: Kafka 集群的连接信息,即 localhost:9092。消费者组名:testgroup
  16. 它会按照消费者组订阅主题的分区进行展示,每个分区一行数据;其次,除了主题、分区等信息外,它会汇报每个分区当前最新生产的消息的位移值(即 LOG-END-OFFSET 列值)、该消费者组当前最新消费消息的位移值(即 CURRENT-OFFSET 值)、LAG 值(前两者的差值)、消费者实例 ID消费者连接 Broker 的主机名以及消费者的 CLIENT-ID 信息。
  17. Kafka Java Consumer API [ Kafka 2.0.0 ]

  18. 代码示例:
  19. 第 1 处是调用 AdminClient.listConsumerGroupOffsets 方法获取给定消费者组的最新消费消息的位移;
  20. 第 2 处则是获取订阅分区的最新消息位移;a
  21. 第3 处就是执行相应的减法操作,获取 Lag 值并封装进一个 Map 对象。
  22. 
    public static Map<TopicPartition, Long> lagOf(String groupID, String bootstrapServers) throws TimeoutException {
            Properties props = new Properties();
            props.put(CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
            try (AdminClient client = AdminClient.create(props)) {
                ListConsumerGroupOffsetsResult result = client.listConsumerGroupOffsets(groupID);
                try {
                    Map<TopicPartition, OffsetAndMetadata> consumedOffsets = result.partitionsToOffsetAndMetadata().get(10, TimeUnit.SECONDS);
                    props.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false); // 禁止自动提交位移
                    props.put(ConsumerConfig.GROUP_ID_CONFIG, groupID);
                    props.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
                    props.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName());
                    try (final KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props)) {
                        Map<TopicPartition, Long> endOffsets = consumer.endOffsets(consumedOffsets.keySet());
                        return endOffsets.entrySet().stream().collect(Collectors.toMap(entry -> entry.getKey(),
                                entry -> entry.getValue() - consumedOffsets.get(entry.getKey()).offset()));
                    }
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    // 处理中断异常
                    // ...
                    return Collections.emptyMap();
                } catch (ExecutionException e) {
                    // 处理ExecutionException
                    // ...
                    return Collections.emptyMap();
                } catch (TimeoutException e) {
                    throw new TimeoutException("Timed out when getting lag for consumer group " + groupID);
                }
            }
        }
    
     
  23.  
  24. Kafka JMX 监控指标

  25. Kafka 默认提供的 JMX 监控指标来监控消费者的 Lag 值
  26. Kafka 消费者提供了一个名为 kafka.consumer:type=consumer-fetch-manager-metrics,client-id=“{client-id}”的 JMX 指标,里面有很多属性。和我们今天所讲内容相关的有两组属性:records-lag-max 和 records-lead-min它们分别表示此消费者在测试窗口时间内曾经达到的最大的 Lag 值和最小的 Lead 值。
  27. Lead 值是指消费者最新消费消息的位移与分区当前第一条消息位移的差值。很显然,Lag 和 Lead 是一体的两个方面:Lag 越大的话,Lead 就越小,反之也是同理。
  28. 监控到 Lag 越来越大,消费者程序变得越来越慢了,至少是追不上生产者程序了.
  29. Lead 越来越小,甚至是快接近于 0 了,消费者端要丢消息了
  30.  
  31.  
  32. Kafka 的消息是有留存时间设置的,默认是 1 周,也就是说 Kafka 默认删除 1 周前的数据。倘若你的消费者程序足够慢,慢到它要消费的数据快被 Kafka 删除了,这时你就必须立即处理,否则一定会出现消息被删除,从而导致消费者程序重新调整位移值的情形。这可能产生两个后果:一个是消费者从头消费一遍数据,另一个是消费者从最新的消息位移处开始消费,之前没来得及消费的消息全部被跳过了,从而造成丢消息的假象。
  33.  
  34. Kafka 消费者还在分区级别提供了额外的 JMX 指标,用于单独监控分区级别的 Lag 和 Lead 值。JMX 名称为:kafka.consumer:type=consumer-fetch-manager-metrics,partition=“{partition}”,topic=“{topic}”,client-id=“{client-id}”

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
是的,Flink 可以帮助你查看 Kafka 消费进度。通过使用 Flink 的 Kafka Consumer,你可以获取当前消费者组在每个 Kafka 分区上的偏移量信息,并据此计算消费进度。 以下是一种获取 Kafka 消费进度方法: 1. 在 Flink 中使用 Kafka Consumer 来消费 Kafka 数据。你可以使用 Flink 提供的 `FlinkKafkaConsumer` 或 `FlinkKafkaConsumerBase` 类来创建 Kafka Consumer。 2. 获取 Kafka 消费者的偏移量信息。通过调用 Kafka Consumer 的 `KafkaConsumer#getPositions()` 方法,你可以获得当前消费者组在每个分区上的偏移量。 ```java // 创建 Kafka Consumer FlinkKafkaConsumer<String> consumer = new FlinkKafkaConsumer<>("topic", new SimpleStringSchema(), properties); // 获取消费者组在每个分区上的偏移量 Map<KafkaTopicPartition, Long> positions = consumer.getKafkaConsumer().getPositions(consumer.getSubscribedPartitions()); ``` 3. 根据偏移量信息计算消费进度。根据每个分区的当前偏移量和分区的末尾偏移量,可以计算出每个分区的消费进度。然后,你可以根据自己的需求,将这些进度信息打印出来或存储到外部系统中。 请注意,获取偏移量信息和计算消费进度需要在 Flink 作业运行时进行。你可以在 Flink 作业中的适当位置(例如 `open()` 方法或 `processElement()` 方法)执行这些操作,以便能够及时地获取最新的偏移量信息和进度。 通过这种方式,你可以方便地查看 Flink 消费 Kafka进度,并了解每个分区的消费情况。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值