Kafka服务端日志详解

文章目录

  • 服务端日志
    • Topic消息存储方式
      • 主体介绍
      • log文件追加记录消息
      • index和timeindex索引文件
    • 日志文件清理
    • Kafka的文件高效读写机制
      • Kafka的文件结构
      • 顺序写磁盘
      • 零拷贝
    • 合理配置刷盘频率
    • 客户端消费进度管理

服务端日志

Kafka的日志信息是通过conf/server.properties文件中的log.dirs配置项来配置的

在这里插入图片描述



Topic消息存储方式

主体介绍

进入到上方配置文件中指定的目录下查看,topic的数据都是以topic名 + partition下标的命名方式保存的

在这里插入图片描述



我们现在进入其中一个partition目录

在这里插入图片描述



  • .index

    日志索引文件,采用的稀疏索引提高查询效率,记录的是消息偏移量offset 和 该消息在.log文件中的位置position

  • .log

    消息保存在.log文件中,是以二进制的方式保存的。可以通过.index和.timeindex两个索引文件加速查找消息

    文件大小是(log.segment.bytes参数设定)默认1GB,新文件名是第一条消息的offset.log

  • .timeindex

    日志索引文件,采用的也是稀疏索引结构,每隔一段时间保存一条索引记录,记录的是消息产生的时间戳timestamp和消息偏移量offset

  • .snapshot

    快照,可以理解为一个备份文件

  • leader-epoch-checkpoint

    Leader partition新上任就会往该文件中写入一个epoch,来保证HW的一致性

  • partition.metadata

    保存着该partition对应的topic_id



最后两个文件可以直接查看,就记录的一些简单的信息

[root@worker1 disTopic-0]# cat leader-epoch-checkpoint 
0
3
5 0
9 6
14 18[root@worker1 disTopic-0]# cat partition.metadata 
version: 0
topic_id: rDUdZBO7RH2GNPgdRXk7Tw



而前三个文件是以二进制的方式保存的,需要通过Kafka提供的kafka-dump-log.sh来查看文件内容,如下所示

# 保存的是消息产生的时间戳 和 消息offset
[root@worker3 testTopic-0]# kafka-dump-log.sh --files 00000000000000000000.timeindex
Dumping 00000000000000000000.timeindex
timestamp: 1723254597947 offset: 51
timestamp: 1723254598224 offset: 102
timestamp: 1723254598501 offset: 152
timestamp: 1723254598816 offset: 201
timestamp: 1723254599085 offset: 250# 保存是的消息的offset 和 该消息在.log文件中对应的position位置
[root@worker3 testTopic-0]# kafka-dump-log.sh --files 00000000000000000000.index
Dumping 00000000000000000000.index
offset: 51 position: 4160
offset: 102 position: 8324
offset: 152 position: 12428
offset: 201 position: 16544
offset: 250 position: 20660
offset: 299 position: 24776# 每一条记录保存的是一批消息信息,只不过我下面刚好都只保存一条消息
[root@worker3 testTopic-0]# kafka-dump-log.sh --files 00000000000000000000.log
baseOffset: 50 lastOffset: 50 count: 1 baseSequence: 0 lastSequence: 0 producerId: 5001 producerEpoch: 0 partitionLeaderEpoch: 0 isTransactional: false isControl: false deleteHorizonMs: OptionalLong.empty position: 4080 CreateTime: 1723254597907 size: 80 magic: 2 compresscodec: none crc: 672861010 isvalid: true
baseOffset: 51 lastOffset: 51 count: 1 baseSequence: 1 lastSequence: 1 producerId: 5001 producerEpoch: 0 partitionLeaderEpoch: 0 isTransactional: false isControl: false deleteHorizonMs: OptionalLong.empty position: 4160 CreateTime: 1723254597947 size: 80 magic: 2 compresscodec: none crc: 3136762717 isvalid: true
baseOffset: 52 lastOffset: 52 count: 1 baseSequence: 2 lastSequence: 2 producerId: 5001 producerEpoch: 0 partitionLeaderEpoch: 0 isTransactional: false isControl: false deleteHorizonMs: OptionalLong.empty position: 4240 CreateTime: 1723254597951 size: 80 magic: 2 compresscodec: none crc: 3076149845 isvalid: true



log文件追加记录消息

  • .log文件是以追加的方式写入新的消息日志。position表示写入位置,size表示消息的总长度,通过这两个值就能从一段二进制中获取到一条具体的消息。
  • Kafka中的消息日志,只允许追加,不允许删除和修改。
  • log文件的固定大小是log.segment.bytes参数设定,默认1GB。新创建的文件是以写入第一条消息的offset作为的文件名



index和timeindex索引文件

index和timeindex索引文件目的都是为了加快从log文件中读取消息的效率,如下图所示,

在这里插入图片描述



  • index和timeindex文件是以相对偏移量的方式建立的log消息日志数据索引

    比如说0000.index和 0947.index索引文件中的内容offset都是以0开始计数的,使用的是第一条消息的相对偏移量,而消息绝对偏移量=文件名+相对偏移量

  • index和timeindex文件采用的是类似于数据的跳表,并不是每一条消息都会记录一条索引。

    log.index.interval.bytes决定.log文件中产生多少大小的消息就生成一条index记录 官网 服务端的参数说明

    log.index.interval.bytes
    The interval with which we add an entry to the offset indexType:	int
    Default:	4096 (4 kibibytes)
    



index文件的作用类似于数据结构中的跳表,他的作用是用来加速查询log文件的效率。而timeindex文件的作用则是用来进行一些跟时间相关的消息处理。比如文件清理。



日志文件清理

Kafka为了防止过多的日志文件给服务器带来过大的压力,他会定期删除过期的log文件。



判断那些日志文件过期了

  • log.retention.check.interval.ms

    定时检测文件是否过期。默认是 300000毫秒,也就是五分钟。 在检查文件是否超时时,是以每个.timeindex中最大的那一条记录为准。

  • log.retention.hours , log.retention.minutes, log.retention.ms 。

    这一组参数表示文件保留多长时间。默认生效的是log.retention.hours,默认值是168小时,也就是7天。如果设置了更高的时间精度,以时间精度最高的配置为准。

官网 服务端的参数说明

# 日志清除程序检查是否有日志符合删除条件的频率(以毫秒为单位)
log.retention.check.interval.ms
Type:	long
Default:	300000 (5 minutes)# 在删除日志文件之前保留它的小时数(以小时为单位),仅次于log.retention.ms属性
log.retention.hours
Type:	int
Default:	168# 在删除日志文件之前保留日志文件的分钟数(以分钟为单位),仅次于log.retention.ms属性。如果没有设置,则使用log.retention.hours中的值
log.retention.minutes
Type:	int
Default:	null# 日志文件删除前保留的毫秒数(以毫秒为单位),如果未设置,则使用log.retention.minutes中的值。如果设置为-1,则不应用时间限制。
log.retention.ms
Type:	long
Default:	null



过期的日志文件如何处理

# 日志清理策略。有两个选项,delete表示删除日志文件。 compact表示压缩日志文件。
log.cleanup.policy
Type:	list
Default:	delete
Valid Values:	[compact, delete]# 日志删除前的最大容量
# 当log.cleanup.policy选择delete时  当总的日志文件大小超过这个阈值后,就会删除最早的日志文件。默认是-1,表示无限大。
log.retention.bytes
Type:	long
Default:	-1



Kafka的文件高效读写机制

Kafka的文件结构

kafka的数据文件结构可以加速日志文件的读取。

Topic下的多个partition采用的是单独记录日志文件,这样加快了topic下的数据读取

通过.index索引文件的稀疏索引结构,进一步加快日志检索速度。



顺序写磁盘

对每个Log文件,Kafka会提前规划固定的大小,这样在申请文件时,可以提前占据一块连续的磁盘空间。

Kafka的log文件只能以追加的方式往文件的末端添加(这种写入方式称为顺序写)



零拷贝

零拷贝是Linux操作系统提供的一种IO优化机制,而Kafka大量的运用了零拷贝机制来加速文件读写。

零拷贝就是配合内核态的复制机制,减少用户态和内核态之间的内容拷贝

传统的一次硬件IO是这样工作的。如下图所示:

在这里插入图片描述



零拷贝主要有两种实现机制

1、mmap文件映射机制

不再将整个文件复制进用户态,而是用户态只持有一个文件的映射信息,通过这个映射信息控制内核态的文件读写。

java中大量使用该方式 ,可以参考下JDK中的DirectByteBuffer实现机制

适用于文件不超过2G的文件,所以Kafka将日志文件设计成1G

在这里插入图片描述



2、sendfile文件传输机制

用户态连文件索引都不读取,直接向内核态发送一个sendfile指令,让内核态去进行文件拷贝

例如当Consumer要从Broker上poll消息时,Broker不需要对消息进行任何的加工,用户态就只需要往内核态发一个sendfile指令,而不需要有任何的数据拷贝过程。Kafka大量的使用了sendfile机制,用来加速对本地数据文件的读取过程。

在这里插入图片描述

JDK中8中java.nio.channels.FileChannel类提供了transferTo和transferFrom方法,底层就是使用了操作系统的sendfile机制。



合理配置刷盘频率

应用程序读取文件是从内核态的pageCache中读取的,保存文件是最终只能保存到pageCache中,应用程序不能直接操作pageCache。而pageCache中的数据如果还没有来得及刷盘持久化到磁盘,服务器忽然非正常断电,那么pageCache中的数据就会丢失。

应用程序唯一能做的就是频繁的调用OS提供的fsync()通知OS进行刷盘操作,但是则会降低应用的执行性能。所以应用程序需要在数据安全和高性能上做取舍。

Kafka在服务端设计了几个参数,来控制刷盘的频率:

这里可以看到,Kafka为了最大化性能,默认是将刷盘操作交由了操作系统进行统一管理。

# 多长时间进行一次强制刷盘。默认是Long.MAX。
flush.ms
Type:	long
Default:	9223372036854775807
Valid Values:	[0,...]# 表示当同一个Partiton的消息条数积累到这个数量时,就会申请一次刷盘操作。默认是Long.MAX。
log.flush.interval.messages
Type:	long
Default:	9223372036854775807
Valid Values:	[1,...]#当一个消息在内存中保留的时间,达到这个数量时,就会申请一次刷盘操作。他的默认值是空。如果这个参数配置为空,则生效的是下一个参数。
log.flush.interval.ms
Type:	long
Default:	null# 日志刷新程序检查是否需要将日志刷新到磁盘的频率(以毫秒为单位),默认也是Long.MAX。
log.flush.scheduler.interval.ms
Type:	long
Default:	9223372036854775807



客户端消费进度管理

消费者消费消息的进度被保存在一个名称为__consumer_offsets内置的topic中,该topic默认会创建50个分区partition

在这里插入图片描述



该topic在zookeeper也能查看到相应的信息,只不过zookeeper上只是简单记录了partition的Leader和ISR列表,并没有看见真实消费者的消费进度

在这里插入图片描述



既然这也是一个topic下的partition,我们启动一个消费者来消费其中的消息看看

可以看到下面记录的消息内容就是一个key-value的格式,key为消费者组+topic+partition 而value保存则offset和一些元数据信息

也就是说这里记录了消费者组在某个topic下的partition的消息消费偏移量offset

[root@worker1 ~]# kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic __consumer_offsets --from-beginning --formatter "kafka.coordinator.group.GroupMetadataManager\$OffsetsMessageFormatter"[test,disTopic,0]::OffsetAndMetadata(offset=6, leaderEpoch=Optional[5], metadata=, commitTimestamp=1723081907174, expireTimestamp=None)
[test,disTopic,3]::OffsetAndMetadata(offset=6, leaderEpoch=Optional[7], metadata=, commitTimestamp=1723081907275, expireTimestamp=None)
[test,disTopic,1]::OffsetAndMetadata(offset=3, leaderEpoch=Optional[1], metadata=, commitTimestamp=1723081907275, expireTimestamp=None)
[test,disTopic,2]::OffsetAndMetadata(offset=11, leaderEpoch=Optional[4], metadata=, commitTimestamp=1723081907275, expireTimestamp=None)
[test,disTopic,0]::OffsetAndMetadata(offset=6, leaderEpoch=Optional[5], metadata=, commitTimestamp=1723081907275, expireTimestamp=None)
[test,disTopic,3]::OffsetAndMetadata(offset=6, leaderEpoch=Optional[7], metadata=, commitTimestamp=1723081907377, expireTimestamp=None)
[test,disTopic,1]::OffsetAndMetadata(offset=3, leaderEpoch=Optional[1], metadata=, commitTimestamp=1723081907377, expireTimestamp=None)



而这些Offset数据,其实也是可以被消费者修改的,在之前章节已经演示过消费者如何从指定的位置开始消费消息。而一旦消费者主动调整了Offset,Kafka当中也会更新对应的记录。

另外,这个系统Topic里面的数据是非常重要的,因此Kafka在消费者端也设计了一个参数来控制这个Topic应该从订阅关系中剔除。

public static final String EXCLUDE_INTERNAL_TOPICS_CONFIG = "exclude.internal.topics";
private static final String EXCLUDE_INTERNAL_TOPICS_DOC = "Whether internal topics matching a subscribed pattern should " +"be excluded from the subscription. It is always possible to explicitly subscribe to an internal topic.";
public static final boolean DEFAULT_EXCLUDE_INTERNAL_TOPICS = true;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/401336.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

互联网红利消退,AI 大模型接棒新红利

在科技发展的浪潮中,互联网曾经是推动经济增长和社会变革的强大引擎,为无数企业和个人带来了巨大的红利。然而,随着时间的推移,互联网红利似乎正在逐渐消退,而与此同时,AI 大模型正以其强大的创新能力和广泛…

搜索旋转排序数组

搜索旋转排序数组 没思路。 看了下全网的思路,一个个来o,多做点题就知道了二分不仅仅只能用在有序的数组中。 这道题很关键的一个值就是nums[0]。 法一:先用二分找到旋转点,旋转点两边都是的,判断要搜索的值在哪边,…

玩转haproxy --花十分钟看看,全是干货

Haproxy是一款开源集群软件(在上一篇文章中提到过集群的相关知识,往期点击http://t.csdnimg.cn/qWtQG)是法国开发者 威利塔罗(Willy Tarreau) 在2000年使用C语言开发的,是一款具备高并发(万级以上)、高性能的TCP和HTTP负载均衡器 …

Linux Day1 系统编程和文件操作

系统编程内容 文件I/O (输入/输出): 1)使用标准库函数如fopen, fclose, fread, fwrite, fgetc, fputc, fgets, fprintf, fscanf等进行文件操作。 2)使用open, close, read, write等系统调用来实现底层文件操作。 进程管理: 1)使用fork, e…

安卓用户专属福利:OfficeSuite中文高级版,让你的工作更轻松!

OfficeSuite – 世界顶级移动办公软件!Google Play商店下载最多的办公软件应用,迄今为止,智能手机平台上,功能最强大、兼容性最好的移动Office办公套件。创建,查看和编辑Word,Excel和PowerPoint文档&#x…

ThinkPHP5漏洞分析之代码执行

漏洞概要 本次漏洞存在于 ThinkPHP 的缓存类中。该类会将缓存数据通过序列化的方式,直接存储在 .php 文件中,攻击者通过精心构造的 payload ,即可将 webshell 写入缓存文件。缓存文件的名字和目录均可预测出来,一旦缓存目录可访问…

python自动化笔记:os模块和异常处理

目录 一、os模块1.1、常用方法1.2、其他方法(了解即可) 二、异常处理 try except2.1、语法格式1:2.2、语法格式2:指定异常类别,捕获异常2.3、语法格式3:try-finally 语句无论是否发生异常都将执行最后的代码…

SQL每日一练-0814

今日SQL题难度:🌟☆☆☆☆☆☆☆☆☆ 1、题目要求 找出每个部门中薪资最高的员工显示部门ID、部门名称、员工ID、员工姓名以及对应的薪资 2、表和虚拟数据 现有两个表:Employees 和 Departments,记录了员工和部门信息。…

【机器学习】ImageNet的基本概念以及如何使用ImageNet数据集

引言 ImageNet是一个大型的图像数据库,它根据WordNet的层级结构(目前仅限于名词)组织,其中每个层级节点都由成百上千张图像来描绘。这个项目对计算机视觉和深度学习研究的发展起到了重要作用 文章目录 引言一、ImageNet的基本概念…

一次sql请求,返回分页数据和总条数

日常搬砖,总少不了需要获取分页数据和总行数。 一直以来的实践是编码两次sql请求,分别拉分页数据和totalCount。 最近我在思考: 常规实践为什么不是 在一次sql请求中中执行多次sql查询或多次更新,显而易见的优势: ① 能…

Halcon 算子汇总

gen_tuple_const(1000,1.5) 生成一个长度为1000,里面每一个数组元素都为1.5的数组 gen_tuple_const(100,chr(ord(a) 1)) 生成一个长度为100,里面每一个数组元素都为b的数组 ord函数是库函数,用于获取字符的ASCII值 chr(ord(a) 1) 结…

8.13-LVS的nat模式+DR模式

LVS 一、nat模式 1.角色 主机名ip地址功能web01192.168.2.101rsweb02192.168.2.102realserveenat内网:192.168.2.103 外网:192.168.2.120directorserver,ntpdns192.168.2.105dns 2..web服务器 [rootweb01 ~]# yum -y install nginx ​ [rootweb01 ~]# echo "web01&qu…

【14】二叉树的Morris等

目录 一.树形dp套路 二.派对的最大快乐值 三.Morris遍历 morris先序遍历 morris中序遍历 moris后序遍历 判断是不是搜索二叉树 四.额外习题 一.树形dp套路 情况1:最大距离,节点X不参与。 > 左树最大距离 or 右树最大距离 情况2:最…

html编写贪吃蛇页面小游戏(可以玩)

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>贪吃蛇小游戏</title><style>body {…

【软件逆向】第2课,软件逆向安全工程师之区分应用32位和64位,每天5分钟学习逆向吧!

目标学习使用StudyPE区分应用 在软件逆向中区分应用类型是关键性的一部分 &#xff0c;只有区分类型后才能选择对应工具进行后续处理。 1.打开StudyPE工具。 2.将我们需要逆向的软件&#xff0c;拖拽到StudyPE中&#xff0c;查看应用信息。 以上用一款视觉AI软件举例&#…

Java设计模式-原型模式-一次性理解透

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1. 前言2. 原型模式的主要角色2.1 原型接口或抽象类2.2 具体原型类2.3 客户端2.4 克隆方法 3. 原型模式使用场景3.1 创建对象是昂贵的3.2 对象的变化3.3 动态配置3.…

【STM32】DMA数据转运(存储器到存储器)

本篇博客重点在于标准库函数的理解与使用&#xff0c;搭建一个框架便于快速开发 目录 DMA简介 DMA时钟使能 DMA初始化 转运起始和终止的地址 转运方向 数据宽度 传输次数 转运触发方式 转运模式 通道优先级 DMA初始化框架 选择开启DMA通道 更改转运次数 DMA应用…

【第二节】80x86汇编-寄存器和标志位

目录 前言 一、汇编相关概念 1.1 数据表示与类型 1.2 汇编语言的构成 1.3 存储器及指令、数据 1.4 存储单元 1.5 CPU对存储器的读写操作 1.6 CPU读写内存单元的过程 1.7 intel CPU发展 1.8 8086 内部结构 二、寄存器 2.1 寄存器概览 2.2 32位寄存器 2.3 16位寄存器…

三维建模软件:地理信息与遥感领域的智慧构建者

在地理信息与遥感技术的广阔舞台中&#xff0c;建模软件如同一位卓越的建筑师&#xff0c;以数据为砖瓦&#xff0c;智慧为水泥&#xff0c;构建出一个又一个又一个逼真、动态的虚拟世界。本文将深入探究其技术核心、应用实例、未来趋势&#xff0c;揭示建模软件如何在地理信息…

《爱情,到此为止》票房大卖 贾斯汀巴尔多尼与布莱克莱弗利的矛盾升级 是真的还是炒作

布蕾克莱弗利&#xff0c;贾斯汀巴尔多尼 布莱克莱弗利凭借电影《我们的末日》在周末取得了票房成功&#xff0c;首映票房收入达 5000 万美元。在电影院困难时期&#xff0c;这是一个了不起的成就&#xff0c;但没有人谈论这一胜利——粉丝们对她与导演兼联合主演贾斯汀巴尔多…