kafka时间戳的详解及使用

分析记录一次线上问题

发现有个别的topic 数据过期不清理 topic retention设置是10d server等日志也没发现异常日志

现象

  • 磁盘使用率告警 查看磁盘分区大小 发现了几个特别大
  • 去分区下面查看segment 发现有超过10d前的都还保留topic/partition/segement
  • 查看server日志发现从最老segment的那天开始就没有deletion日志了
  • 有新的segment生成
  • log clean线程还在

Topic的清理策略

cleanup.policy: delete

kafka log的清理策略有两种:delete,compact, 默认是delete

DUMP文件

bin/kafka-run-class.sh kafka.tools.DumpLogSegments --files 0000000000001190.timeindex --print-data-log
或者
bin/kafka-dump-log --files 00000000001895067862.timeindex --print-data-log
timestamp: 1859915778000000 offset: 1996
timestamp: 1859915778000003 offset: 2083

这些时间戳转换后时间是个未来的非常大的时间!!!

修复方式见下文:

sh bin/kafka-delete-records.sh --bootstrap-server xxxx --offset-json-file config/offset-
json-file.json

offset-json-file.json

{"partitions":
[{"topic": "test1", "partition": 0,
"offset": 1024}],
"version":1
}

# 从最开始的地方删除消息到 1024的offset

问题分析

概述

Kafka从0.10.0.0版本起,在消息内新增加了个timestamp字段,
在Kafka 0.10.1.0以前(不包含0.10.1.0),对于一个Topic而言,其Log Segment是由一个.log文档和一个.index文档组合而成,分别用来存储具体的消息数据和对应的偏移量
从Kafka 0.10.1.0开始,对于日志文档,新增一个.timeindex文档,即每个Segment分别由.log、.index和.timeindex这三个文档组成。


kafka时间戳的作用

基于时间戳的日志切分策略
基于时间戳的日志清除策略
根据时间戳来定位消息:之前的索引文件是根据offset信息的,从逻辑语义上并不方便使用,引入了时间戳之后,Kafka支持根据时间戳来查找定位消息

kafka 参数

message.timestamp.type: 定义消息中的时间戳是消息创建时间还是日志附加时间。

值应该是“CreateTime”或“LogAppendTime”, 默认为:CreateTime

  • LogAppendTime

        为 ingestion-time 不可以自定义指定时间,系统自动生成当前producer时间

  • CreateTime event-time

        可以自定义自定timestamp,如果不指定则默认为系统自动生成当前producer时间,即LogAppendTime时间

如下:

如果为CreateTime则会生效,若为LogAppendTime则不会生效
producer.send(new ProducerRecord<String, String> ("test.5",null,1000000000000L,null,value)).get();
# 1000000000000L为timestamp

配置方式

1)在broker的配置文件指定

message.timestamp.type=CreateTime
或
message.timestamp.type=LogAppendTime

2)创建topic时指定 

  • kafka-topics.sh --zookeeper 127.0.0.1:2181/kafka \
    --create \
    --topic test.4 \
    --partitions 1 --replication-factor 1 \
    --config message.timestamp.type=CreateTime
    或
    kafka-topics.sh --zookeeper 127.0.0.1:2181/kafka \
    --create \
    --topic test.4 \
    --partitions 1 --replication-factor 1 \
    --config message.timestamp.type=LogAppendTime

message.timestamp.difference.max.ms:

broker接收消息时所允许的时间戳与消息中指定的时间戳之间的最大差异。

  • 如果message.timestamp.type=CreateTime,则如果时间戳的差异超过此阈值,则将拒绝消息。
  • 如果message.timestamp.type=LogAppendTime,则忽略此配置。默认为Long.MAX_VALUE 

关于从ConsumerRecord获取时间戳为-1的说明
部分源码为:
ConsumerRecord.java

/**
     * Creates a record to be received from a specified topic and partition (provided for
     * compatibility with Kafka 0.9 before the message format supported timestamps and before
     * serialized metadata were exposed).
     *
     * @param topic The topic this record is received from
     * @param partition The partition of the topic this record is received from
     * @param offset The offset of this record in the corresponding Kafka partition
     * @param key The key of the record, if one exists (null is allowed)
     * @param value The record contents
     */
    public ConsumerRecord(String topic,
                          int partition,
                          long offset,
                          K key,
                          V value) {
        this(topic, partition, offset, NO_TIMESTAMP, TimestampType.NO_TIMESTAMP_TYPE,
                NULL_CHECKSUM, NULL_SIZE, NULL_SIZE, key, value);
    }


RecordBatch.java

public interface RecordBatch extends Iterable<Record> {

    /**
     * The "magic" values
     */
    byte MAGIC_VALUE_V0 = 0;
    byte MAGIC_VALUE_V1 = 1;
    byte MAGIC_VALUE_V2 = 2;

    /**
     * The current "magic" value
     */
    byte CURRENT_MAGIC_VALUE = MAGIC_VALUE_V2;

    /**
     * Timestamp value for records without a timestamp
     */
    long NO_TIMESTAMP = -1L;
    ...


TimestampType.java

public enum TimestampType {
    NO_TIMESTAMP_TYPE(-1, "NoTimestampType"), CREATE_TIME(0, "CreateTime"), LOG_APPEND_TIME(1, "LogAppendTime");
    ...

为了兼容Kafka 0.9(包含)以前的版本,如果为kafka0.9之前的无时间戳的版本,则返回的timestamp则为 -1

参考:

kafka时间戳的详解及使用

Kafka日志清理策略,compact和delete

Kafka中数据清理、日志压缩、日志删除、保留策略
 

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
@KafkaListener是Spring Kafka提供的注解,用于标识一个方法作为Kafka消息的监听器。它可以与其他注解一起使用,以配置和定制监听器的行为。 @KafkaListener注解的用法如下所示: - id属性用于指定监听器的唯一标识符。 - idIsGroup属性用于指定id是否作为消费者组的一部分。 - topics属性用于指定监听的主题。 - containerFactory属性用于指定用于创建监听容器的工厂。 - concurrency属性用于指定并发消费者的数量。 - clientIdPrefix属性用于指定消费者的客户端ID前缀。 - groupId属性用于指定消费者组的ID。 - properties属性用于指定其他Kafka消费者的属性。 - errorHandler属性用于指定错误处理器。 除了基本的用法外,@KafkaListener还可以与其他注解一起使用,以进一步定制监听器的行为。例如,可以使用@Payload注解指定消息的有效负载类型,以及使用@Valid注解验证有效负载对象。 要使用@KafkaListener注解,您需要在Spring Kafka配置类中添加@Bean注解来创建KafkaListenerContainerFactory bean,并在您的监听器方法上添加@KafkaListener注解。 您还可以使用KafkaListenerEndpointRegistry来获取已注册的所有监听器容器。这可以在需要动态管理和操作监听器时非常有用。 总结起来,@KafkaListener注解提供了一个方便的方式来创建Kafka消息的监听器,并可以使用各种属性和其他注解来定制它们的行为。同时,使用KafkaListenerEndpointRegistry可以方便地管理和操作已注册的监听器容器。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [@KafkaListener详解使用](https://blog.csdn.net/h4241778/article/details/122416366)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [【spring-kafka】@KafkaListener详解使用](https://blog.csdn.net/u010634066/article/details/109803987)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

未来在这儿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值