关于Kafka 的消息日志Offset 的了解

之前在做Kafka 整合Storm的时候,因为对Kafka 不是很熟,考虑过这样的一个场景问题,针对一个Topic,Kafka消息日志中有个offset信息来标注消息的位置,Storm每次从kafka 消费数据,都是通过zookeeper存储的数据offset,来判断需要获取消息在消息日志里的起始位置。

那么我们想,这个Offset 是消息在日志里是一个什么样的位置,是绝对位置还是相对位置?而Kafla 有个参数log.retention.hours会根据设定的小时,来清理日志文件。这样就可能会有这样的一个问题,针对一个Topic,Kafka 生产数据后,消费者消费信息后,此时的消息的offset是一个高位,比如100,消费者在消费完会记录这个offset准备下个数据的获取。而当系统时间达到参数log.retention.hours设定的时间后,kafka会自动删除这个Topic的缓存日志,那么这个时候新加入10条消息,消息的offset 是重新开始还是从删除日志前的Offset 开始?如果是前者,这个时候消费者因为记录消费这个Topic信息的Offset 仍在高位,那么他就获取不到在这个Offset前的新加入数据,这样就比较麻烦了。而后者,offset又是怎么记录消息相对位置的从而消费者一直消费到数据,无论系统怎么处理日志。这个是Storm 消费Kafla数据的时候必须要确认的问题。 

所以做了一个针对性测试。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
在 Flink 1.11 中使用 Kafka Connector 时,可以通过设置 `timestamp.extractor` 参数来指定消息时间戳的提取方式。如果你想要获取 Kafka 消息的日志时间,可以使用 `LogAndSkipOnInvalidTimestamp` 提取方式,并将 `timestamp.extractor.watermark.delay-ms` 参数设置为 0。 具体来说,你需要在创建 Kafka 数据源时设置 `timestamp.extractor` 和 `timestamp.extractor.watermark.delay-ms` 参数,示例如下: ```java import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer; import org.apache.flink.streaming.util.serialization.SimpleStringSchema; import org.apache.flink.api.common.serialization.DeserializationSchema; import org.apache.flink.api.common.typeinfo.Types; import org.apache.flink.streaming.api.functions.AssignerWithPunctuatedWatermarks; import org.apache.flink.streaming.api.watermark.Watermark; import org.apache.flink.streaming.connectors.kafka.KafkaDeserializationSchema; import org.apache.flink.streaming.connectors.kafka.KafkaDeserializationSchemaWrapper; import org.apache.flink.streaming.connectors.kafka.KafkaDeserializationSchema.DeserializationSchemaWrapper; import java.util.Properties; import java.util.regex.Pattern; public class KafkaSourceExample { public static void main(String[] args) throws Exception { final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setParallelism(1); Properties properties = new Properties(); properties.setProperty("bootstrap.servers", "localhost:9092"); properties.setProperty("group.id", "test"); FlinkKafkaConsumer<String> consumer = new FlinkKafkaConsumer<>( Pattern.compile("test-topic.*"), new LogAndSkipOnInvalidTimestamp<>(), // 设置 timestamp.extractor properties); consumer.setStartFromEarliest(); consumer.assignTimestampsAndWatermarks(new AssignerWithPunctuatedWatermarks<String>() { @Override public long extractTimestamp(String element, long previousTimestamp) { // 不需要实现,因为我们已经在 Kafka Consumer 中设置了 timestamp.extractor return 0; } @Override public Watermark checkAndGetNextWatermark(String lastElement, long extractedTimestamp) { // 不需要实现,因为我们已经在 Kafka Consumer 中设置了 timestamp.extractor.watermark.delay-ms return null; } }); env .addSource(consumer) .print(); env.execute("Kafka Source Example"); } public static class LogAndSkipOnInvalidTimestamp<T> extends DeserializationSchemaWrapper<T> { public LogAndSkipOnInvalidTimestamp() { super(new SimpleStringSchema()); } @Override public T deserialize(byte[] messageKey, byte[] message, String topic, int partition, long offset) throws Exception { try { // 提取消息时间戳 Long timestamp = Long.valueOf(topic.split("-")[1]); // 构造一个带时间戳的元组 return (T) Tuple2.of(new String(messageKey), new String(message), timestamp); } catch (Exception e) { // 如果提取时间戳失败,则打印一条日志并跳过该条消息 System.err.println("Skip invalid message: " + new String(message)); return null; } } } } ``` 上述示例代码中,我们通过自定义 `LogAndSkipOnInvalidTimestamp` 类来实现了 `KafkaDeserializationSchema` 接口,并在其中提取了 Kafka 消息的日志时间戳。在 `deserialize` 方法中,我们将 Kafka 消息转换为一个带时间戳的元组,并在返回时进行了类型转换。 在 `main` 函数中,我们通过 `new LogAndSkipOnInvalidTimestamp<>()` 来设置了 `timestamp.extractor` 参数,并将 `timestamp.extractor.watermark.delay-ms` 参数设置为 0。这样就可以在 Flink SQL 中使用带时间戳的元组来进行数据处理了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值