小言_互联网的博客

kafka时间戳的详解及使用

415人阅读  评论(0)

分析记录一次线上问题

发现有个别的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文件


  
  1. bin/kafka-run-class.sh kafka.tools.DumpLogSegments --files 000000000000119 0.timeindex -- print-data- log
  2. 或者
  3. bin/kafka- dump- log --files 00000000001895067862.timeindex -- print-data- log

  
  1. timestamp: 1859915778000000 offset: 1996
  2. timestamp: 1859915778000003 offset: 2083

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

修复方式见下文:


  
  1. sh bin /kafka-delete-records.sh --bootstrap-server xxxx --offset-json-file config /offset-
  2. json- file.json
  3. offset-json-file.json
  4. { "partitions":
  5. [{ "topic": "test1", "partition": 0,
  6. "offset": 1024}],
  7. "version": 1
  8. }
  9. # 从最开始的地方删除消息到 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时间

如下:


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

配置方式

1)在broker的配置文件指定


  
  1. message.timestamp. type =CreateTime
  2. message.timestamp. type =LogAppendTime

2)创建topic时指定 

  • 
        
    1. kafka-topics.sh --zookeeper 127.0.0.1: 2181 /kafka \
    2. --create \
    3. --topic test. 4 \
    4. --partitions 1 --replication-factor 1 \
    5. --config message.timestamp. type =CreateTime
    6. kafka-topics.sh --zookeeper 127.0.0.1: 2181 /kafka \
    7. --create \
    8. --topic test. 4 \
    9. --partitions 1 --replication-factor 1 \
    10. --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


  
  1. / **
  2.       * Creates a record to be received from a specified topic and partition (provided for
  3.       * compatibility with Kafka 0.9 before the message format supported timestamps and before
  4.       * serialized metadata were exposed).
  5.       *
  6.       * @param topic The topic this record is received from
  7.       * @param partition The partition of the topic this record is received from
  8.       * @param offset The offset of this record in the corresponding Kafka partition
  9.       * @param key The key of the record, if one exists ( null is allowed)
  10.       * @param value The record contents
  11.       * /
  12.     public ConsumerRecord( String topic,
  13.                           int partition,
  14.                           long offset,
  15.                           K key,
  16.                           V value) {
  17.         this(topic, partition, offset, NO_TIMESTAMP, TimestampType. NO_TIMESTAMP_ TYPE,
  18.                 NULL_CHECKSUM, NULL_ SIZE, NULL_ SIZE, key, value);
  19.     }


RecordBatch.java


  
  1. public interface RecordBatch extends Iterable < Record > {
  2.     / **
  3.       * The "magic" values
  4.       * /
  5.     byte MAGIC_ VALUE_V 0 = 0;
  6.     byte MAGIC_ VALUE_V 1 = 1;
  7.     byte MAGIC_ VALUE_V 2 = 2;
  8.     / **
  9.       * The current "magic" value
  10.       * /
  11.     byte CURRENT_MAGIC_ VALUE = MAGIC_ VALUE_V 2;
  12.     / **
  13.       * Timestamp value for records without a timestamp
  14.       * /
  15.     long NO_TIMESTAMP = - 1L;
  16.     ...


TimestampType.java


  
  1. public enum TimestampType {
  2.     NO_TIMESTAMP_ TYPE(- 1, "NoTimestampType"), CREATE_ TIME( 0, "CreateTime"), LOG_APPEND_ TIME( 1, "LogAppendTime");
  3.     ...

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

参考:

kafka时间戳的详解及使用

Kafka日志清理策略,compact和delete

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


转载:https://blog.csdn.net/weishuai90/article/details/128821742
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场