kafka-12-Kafka消息时间戳kafka message timestamp

参考Kafka消息时间戳(kafka message timestamp)

1 Kafka消息的时间戳

在消息中增加了一个时间戳字段和时间戳类型。
目前支持的时间戳类型有两种:CreateTime和LogAppendTime。
前者表示producer创建这条消息的时间;
后者表示broker接收到这条消息的时间(严格来说,是leader broker将这条消息写入到log的时间)。

2 客户端消息格式的变化

ProducerRecord:增加了timestamp字段,允许producer指定消息的时间戳,如果不指定的话使用producer客户端的当前时间。
ConsumerRecord:增加了timestamp字段,允许消费消息时获取到消息的时间戳。

2.1 获取时间戳

from kafka import KafkaConsumer
global false, null, true
false = null = true = ''

import time
def ms_tostamp(stampint):
    c = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(stampint/ 1000)))
    return c + "." + str(stampint)[-3:]



consumer = KafkaConsumer(bootstrap_servers=['10.80.62.52:9092'], auto_offset_reset='latest', group_id="group1")
consumer.subscribe('yourtest')
for msg in consumer:

    try:
        if msg.value is not None:
            print(ms_tostamp(msg.timestamp))
            data_json = msg.value.decode()
            print(data_json)
    except Exception as e:
        print(e)
print("finish")

输出
2022-02-22 14:32:26.291
aa

2.2 获取最新偏移量的消息时间

from kafka import KafkaConsumer, TopicPartition
global false, null, true
false = null = true = ''

import time
def ms_tostamp(stampint):
    c = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(stampint/ 1000)))
    return c + "." + str(stampint)[-3:]


topic = 'topicname'
consumer = KafkaConsumer(bootstrap_servers=['IP:9092'])

# (1)获取指定分区的最新偏移量
topic_offset_dict = consumer.end_offsets([TopicPartition(topic, 0)])
newoffset = topic_offset_dict[TopicPartition(topic, 0)]
print("最新偏移量",newoffset)
# (2)手动指定分区给consumer去消费
consumer.assign([TopicPartition(topic, 0)])
# (3)针对分区,从指定抓取的偏移量处开始消费
# newoffset-1是因为newoffset的数据还未进来,减去1才是最新的数据
consumer.seek(TopicPartition(topic, 0), newoffset-1)
for msg in consumer:
    try:
        if msg.value is not None:
            print("消息时间",ms_tostamp(msg.timestamp))
            print("本条offset",msg.offset)
            data_json = msg.value.decode()
            print("消息内容",data_json)
            break # 取到一条消息就退出
    except Exception as e:
        print(e)

print("finish")
consumer.close()

输出

最新偏移量 67661482
消息时间 2022-02-22 16:15:06.744
本条offset 67661481
消息内容 message
finish

3 监控指定topic的最新消息时间

from kafka import KafkaConsumer, TopicPartition
global false, null, true
false = null = true = ''

import time
def ms_tostamp(stampint):
    c = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(int(stampint/ 1000)))
    return c + "." + str(stampint)[-3:]




consumer = KafkaConsumer(bootstrap_servers=['10.26.10.113:9092'])
#方式一指定topic列表
topics = ['SB_01',
          'SB_02',
          'SB_03',
          'SB_50',
          'SB_20',
          'SB_30',
          'SB_08'
          ]
def get_topic_msgNewTime(topics):
    try:
        for topic in topics:
            # (1)获取指定分区的最新偏移量
            topic_offset_dict = consumer.end_offsets([TopicPartition(topic, 0)])
            newoffset = topic_offset_dict[TopicPartition(topic, 0)]
            # print("最新偏移量",newoffset)
            # (2)手动指定分区给consumer去消费
            consumer.assign([TopicPartition(topic, 0)])
            # (3)针对分区,从指定抓取的偏移量处开始消费
            # newoffset-1是因为newoffset的数据还未进来,减去1才是最新的数据
            consumer.seek(TopicPartition(topic, 0), newoffset-1)
            for msg in consumer:
                if msg.value is not None:
                    newtime_str = ms_tostamp(msg.timestamp)
                    print(topic,"最新消息时间",newtime_str)
                    # print("本条offset",msg.offset)
                    # data_json = msg.value.decode()
                    # print("消息内容",data_json)
                    break # 取到一条消息就退出
    except Exception as e:
        print(e)
get_topic_msgNewTime(topics)
consumer.close()
print("finish")

输出

SB_01 最新消息时间 2022-02-22 16:37:09.234
SB_02 最新消息时间 2022-02-22 16:34:39.021
SB_03 最新消息时间 2022-02-22 16:35:05.777
SB_50 最新消息时间 2022-02-22 16:30:42.775
SB_20 最新消息时间 2022-02-22 16:37:20.060
SB_30 最新消息时间 2022-02-22 16:37:20.337
SB_08 最新消息时间 2022-02-22 16:35:35.935
finish

4 拉取指定时间段内的消息

启动kafka

systemctl start zookeeper
systemctl start kafka

在这里插入图片描述
一般来说我们都使用Kafka来记录用户的操作记录以便后续分析。但是通常使用的时候需要按天来统计每天的去重用户数、点击量之类的。这个时候如果直接拉某个topic的数据的话,就需要判断每个消息的时间戳,还要兼顾把所有的Partition都拉完才能保证数据的完整。

因此如果能只拉取某一个时间段内的消息,就能极大的简化后续的处理逻辑。为了实现这个目的借助于根据时间戳获取Partition内部偏移的方法,获取两个时间点在Partition内部的偏移,然后从第一个时间点的偏移开始拉取指定Partition的消息,当偏移超过第二个时间点的偏移的时候取消订阅。逐个partition操作拉全topic所有的数据。

#encoding:utf8
from kafka import KafkaConsumer, TopicPartition
from datetime import datetime
import time
consumer = KafkaConsumer(bootstrap_servers=['192.168.1.10:9092'])
topic = "dbtest"

# 字符串时间戳转换为整数时间戳,毫秒
def tostamp_int(timestr):
    datetime_obj = datetime.strptime(timestr, "%Y-%m-%d %H:%M:%S.%f")
    obj_stamp = int(time.mktime(datetime_obj.timetuple()) * 1000.0 + datetime_obj.microsecond / 1000.0)
    return obj_stamp

st_str = "2022-05-31 17:33:53.000"
st_int = tostamp_int(st_str)

end_str = "2022-05-31 17:35:10.000"
end_int = tostamp_int(end_str)

print(st_str,st_int)

tp = TopicPartition(topic=topic, partition=0)

# 查询开始时间的针对于某个partition的偏移
start_offset = consumer.offsets_for_times({tp:st_int})
print(start_offset)

# 查询结束时间的针对于某个partition的偏移
end_offset = consumer.offsets_for_times({tp:end_int})
print(end_offset)
# 从拉取指定partition的offset开始拉取数据
consumer.assign([tp])
consumer.seek(tp,start_offset[tp][0])
for msg in consumer:
    print(msg.value.decode(),msg.offset)
    offset = msg.offset
    print(offset,end_offset[tp][0])
    if offset+1 > end_offset[tp][0]:
    # 如果超过当前partition的偏移之后不再继续订阅当前的topic
        consumer.close()
        break
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

皮皮冰燃

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

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

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

打赏作者

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

抵扣说明:

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

余额充值