【基础】Kafka -- 日志存储

Kafka -- 日志存储

  • 日志文件目录
  • 日志索引
    • 偏移量索引
    • 时间戳索引
  • 日志清理
    • 日志删除
      • 基于时间
      • 基于日志大小
      • 基于日志起始偏移量
    • 日志压缩

日志文件目录

Kafka 中的消息以主题为单位进行基本归类,而每个主题又可以划分为一个或者多个分区。在不考虑多副本的情况下,每个分区对应一个日志 Log。为防止日志过大,Kafka 又引入了日志分段 LogSegment 的概念,即将大的日志文件均分为多个较小的文件,便于消息的维护和清理。

Log 在物理上以文件夹的形式存在,而每个 LogSegment 对应于磁盘上的一个日志文件和两个索引文件,以及可能存在的其他功能文件,如下图所示:

在这里插入图片描述

向 Log 中追加消息是按顺序写入的,只有最后一个 LogSegment 才能执行写入操作,因此最新的一个 LogSegment 也称为 activeSegment。随着消息不断的写入,当 activeSegment 满足一定限制条件时,就会创建新的 activeSegment。LogSegment 的切分包含以下几个条件:

  • 当前 LogSegment 问价文件的大小超过了 broker 端参数log.segment.bytes配置的值,该参数默认 1GB;

  • 当前 LogSegment 中消息的最大时间戳与当前系统时间的时间戳的差值大于log.roll.hourslog.roll.ms的值(若同时配置则后者优先级高)。默认情况下只配置了后者,其值为 168(7 天);

  • 偏移量索引文件或时间戳索引文件的大小达到 broker 端参数log.index.size.max.bytes的值,该参数默认为 10 MB;

  • 新增消息的偏移量与当前 LogSegment 的偏移量之间的差值大于Integer.MAX_VALUE,即要追加消息的偏移量无法转换为相对偏移量;

为了便于消息的检索,每个 LogSegment 都对应着两个索引文件:偏移量索引文件(以.index为后缀)和时间戳索引文件(以.timeindex为后缀)。另外,每个 LogSegment 都有一个基准偏移量 baseOffset,用于表示当前 LogSegment 中第一条消息的 offset。偏移量是一个 64 位的长整型数,日志以及索引文件都是以基准偏移量命名的,名称长度固定为 20 位,不足的位数以 0 补充。查看 LogSegment 的内容如下所示:

在这里插入图片描述

日志索引

每个日志分段文件对应了两个索引文件,用于提高查找消息的效率:

  • 偏移量索引用于建立消息偏移量 offset 到物理地址之间的映射关系;

  • 时间戳索引根据指定的时间戳来查找对应的偏移量信息;

Kafka 中的索引以稀疏索引的方式来构造消息的索引,每当写入一定量的消息时,偏移量索引和时间戳索引则分别增加一个偏移量索引项和时间戳索引项。该值由 broker 端参数log.index.interval.bytes指定,默认为 4096,即 4KB。

偏移量索引

偏移量索引的格式如下:

relativeOffsetposition
4B4B

每个索引项占据 8 个字节,分为两部分:

  • relativeOffset:相对偏移量,表示消息当对于 baseOffset 的偏移量,占用 4 个字节。当前索引的文件名即 baseOffset;

  • position:物理地址,即消息在日志分段文件中对应的物理地址;

消息的绝对偏移量 offset 占用 8 个字节,此处采用占据 4 个字节的相对偏移量以减少索引文件占据的空间,relativeOffset = offset - baseOffset。

索引和日志的对应关系如下所示:

在这里插入图片描述

倘若存在下图所示的几个分段日志文件:

在这里插入图片描述

若要查找偏移量为 268 的消息:

  • 首先需要定位到 baseOffset 为 251 的日志分段。Kafka 的每一个日志对象中都采用了 ConcurrentSkipListMap (跳跃表)来存储各个日志分段,每个日志分段的 baseOffset 作为 key 用于快速查找。

  • 确定日志分段文件后再计算相对偏移量=268-251=17,利用二分查找快速定位到消息的 position。

  • 最后根据 position 定位到日志文件的相应位置查询目标消息。

时间戳索引

时间戳索引的格式如下:

timestamprelativeOffset
8B4B

每个索引项占据 12 个字节,分为两部分:

  • timestamp:当前日志分段的最大时间戳;

  • relativeOffset:时间戳所对应的消息的相对偏移量;

时间戳索引、偏移量索引与日志的对应关系如下所示:

在这里插入图片描述

若要查找目标时间戳为 1526384718288 开始的消息:

  • 首先需要依次对比日志分段中的最大时间戳与目标时间戳,直到找到最大时间戳不小于目标时间戳的日志分段文件;

  • 确定日志分段文件后利用二分法查找不大于目标时间戳的最大索引项,获取其相对偏移量;

  • 在偏移量索引文件中使用二分法查找不大于上一步查到的相对偏移量的最大索引项,获取物理位置 position;

  • 在步骤一的日志分段文件中,从上一步查询到的物理位置处开始查找不小于目标时间戳的消息;

日志清理

Kafka 的消息存储在磁盘当中,为控制磁盘占用空间的不断增加,其提供了两种日志清理策略:

  • 日志删除(Log Retention):按照一定的保留策略直接删除不符合条件的日志分段;

  • 日志压缩(Log Compaction):针对每个消息的 key 进行整合,对于 key 相同的不同 value 值,只保留最新的版本;

通过 broker 端参数log.cleanup.policy可以设置日志的清理策略,默认值为 “delete”,即采用删除策略。设置为 “compact” 即采用压缩策略。还可以设置为 “delete,compact” 以同时支持删除和压缩策略。注意,还需要将log.cleaner.enable设置为 true,默认为 true。

日志清理的细粒度可以控制到主题级别。

日志删除

Kafka 日志管理器中存在一个周期性检测和删除不符合保留条件的日志分段文件的任务,该任务的检测周期可以通过 broker 端参数log.retention.check.interval.ms来配置,默认值为 300000,即 5 分钟。

日志分段的保留策略有 3 种:基于时间、基于日志大小以及基于日志起始偏移量。

基于时间

在该策略中,日志删除任务会检查当前日志文件中是否存在保留时间超过所设定阈值 retentionMs 以寻找可删除的日志分段文件集合 deletableSegments。如下图:

在这里插入图片描述

其中,retentionMs 可以通过 broker 端参数log.retention.hourslog.retention.minutes以及log.retention.ms来配置,各参数优先级按顺序依次增高。Kafka 默认配置log.retention.hours为 168,即 7 天。

若全部的日志分段都已经过期,则首先会切分出一个新的活跃日志分段 activeSegment,然后再执行删除操作。删除时,首先将 Log 对象维护的日志分段跳跃表中移除待删除的日志分段,以保证不会有线程对这些日志分段执行读取操作。然后再将待删除的日志分段及其索引文件标记“.deleted”的后缀。最后交由一个延迟任务执行文件的删除,该任务的延迟执行时间由file.delete.delay.ms参数配置,默认值为 1 分钟。

基于日志大小

在该策略中,日志删除任务会检查当前日志分段文件的大小是否超过设定的阈值 retentionSize 以查找可删除的日志分段文件集合 deletableSegments。如下图:

在这里插入图片描述

其中,retentionMs 可以通过 broker 端参数log.retention.bytes来配置,默认值为 -1,表示无穷大。

查询到可删除的日志分段文件集合 deletableSegments 后,其删除过程与基于时间策略的删除过程相同。

基于日志起始偏移量

在该策略中,日志删除任务会检查当前日志分段文件的的下一日志起始分段文件的起始偏移量 baseOffset 是否小于等于 logStartOffset 以查找可删除的日志分段文件集合 deletableSegments。如下图:

在这里插入图片描述

其中,logStartOffset 的值可以通过 DeleteRecordsRequest 请求、日志的清理和截断等操作进行修改。

查询到可删除的日志分段文件集合 deletableSegments 后,其删除过程与基于时间策略的删除过程相同。

日志压缩

日志压缩是另外一种清理过时数据的方式,其对于具有相同 key 的不同 value,只保留 key 中最新的 value 值,如下图所示。若应用只关心 key 对应的最新 value 值,则可以开启日志压缩的功能。

在这里插入图片描述

在日志压缩前后,日志分段文件中的每条消息的偏移量与写入时的偏移量保持一致,只是日志压缩后的偏移量不再是连续的。

在 Kafka 日志的存放目录当中,存在着名为“cleaner-offset-checkpoint”的文件,该文件用于记录每个主题中的每个分区中已清理的偏移量。文件中记录的 cleaner checkpoint 可以将日志划分为两部分:已经清理过的 clean 部分和未清理过的 dirty 部分,如下图。

在这里插入图片描述

其中,dirty 部分的消息偏移量是逐一递增的,而 clean 部分的消息偏移量是不连续的。firstDirtyOffset 表示 dirty 部分的起始偏移量,firstUncleanableOffset 是 dirty 部分的终止偏移量。activeSegment 不会参与日志压缩的过程。

此外,Kafka 支持通过参数log.cleaner.min.compaction.lag.ms配置消息被压缩清理前的最小保留时间,默认为 0,即默认情况下 firstUncleanableOffset 等于 activeSegment 的 baseOffset。

注意:日志压缩是针对 key 的,故在使用时应注意每个消息的 key 不为 null。每个 broker 会启动log.cleaner.thread所配置个数的日志清理线程负责执行清理任务,这些线程会选择污浊率(=dirty日志大小/(clean日志大小+dirty日志大小))最大的日志文件进行清理。为防止日志的频繁清理,可以使用参数clean.cleanable.ratio来限定可进行清理操作的最小污浊率,默认值为 0.5。

在执行清理操作时,Kafka 日志清理线程会使用 SkimpyOffsetMap 对象来构建 key 与 offset 的映射关系表。清理过程需遍历日志文件两次:

  • 第一次遍历将每一个 key 和最后出现的 offset 保存在 SkimpyOffsetMap 对象中;

  • 第二次遍历判断每一个消息的 offset,将其与消息对应的 kay 在 SkimpyOffsetMap 中存储的值作比较,若前者大于后者则保留,反之进行清理;

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【MySQL】插入文件路径,反斜杠消失

系列文章 C#底层库–MySQL脚本自动构建类(insert、update语句生成) 本文链接:https://blog.csdn.net/youcheng_ge/article/details/129179216 C#底层库–MySQL数据库访问操作辅助类(推荐阅读) 本文链接:h…

如何优雅的写个try catch的方式!

软件开发过程中,不可避免的是需要处理各种异常,就我自己来说,至少有一半以上的时间都是在处理各种异常情况,所以代码中就会出现大量的try {...} catch {...} finally {...} 代码块,不仅有大量的冗余代码,而…

07 【Sass语法介绍-控制指令】

1.前言 Sass 为我们提供了很多控制指令,使得我们可以更高效的来控制样式的输出,或者在函数中进行逻辑控制。本节内容我们就来讲解什么是 Sass 控制指令?它能用来做什么?它将使你更方便的编写 Sass 。 2.什么是 Sass 控制指令 控…

Dockere-Compose迁移Gitea部署

Dockere-Compose迁移Gitea部署 ps: 江湖不是打打杀杀,江湖是人情事故。 解释: Gitea:类似于Git的代码版本管理工具。Docker:Docker-Compose: Docker命令: 查看镜像:docker images 删除镜像…

2023年江苏专转本成绩查询步骤

2023年江苏专转本成绩查询时间 2023年江苏专转本成绩查询时间预计在5月初,参加考试的考生,可以关注考试院发布的消息。江苏专转本考生可在规定时间内在省教育考试院网,在查询中心页面中输入准考证号和身份证号进行查询,或者拨…

【u盘提示:驱动器未格式化】如何解决?

u盘虽然使用很方便,可随时拷贝资料到任何有电脑的地方,但它的问题也是比较多的,其中u盘提示驱动器未格式化故障最让人心虚,因为已经无法打开u盘了,里面的资料怎么办,很重要的怎么办,所以今天就教…

LSSANet:一种用于肺结节检测的长、短切片感知网络

文章目录 LSSANet: A Long Short Slice-Aware Network for Pulmonary Nodule Detection摘要方法Long Short Slice GroupingLong Short Slice-Aware Network 实验结果 LSSANet: A Long Short Slice-Aware Network for Pulmonary Nodule Detection 摘要 提出了一个长短片感知网…

《Spring MVC》 第六章 MVC类型转换器、格式化器

前言 介绍MVC类型转换器、格式化器 1、使用场景 <form th:action"{/user/register}" method"post">用户名&#xff1a;<input type"text" name"userName"/><br/>密码&#xff1a;<input type"password&q…

【Access】win 10 / win 11:Access 下载、安装、使用教程(「管理信息系统」实践专用软件)

目录 一、前言 二、卸载 Office 三、下载 Office Tool Plus 四、安装 Office&#xff08;内含 Access&#xff09; &#xff08;1&#xff09;启动 Office Tool Plus &#xff08;2&#xff09;部署 &#xff08;3&#xff09;安装 Office&#xff08;内含 Access&#…

【Arduino SD卡和数据记录教程】

【Arduino SD卡和数据记录教程】 1. 前言2. 工作原理3. Arduino SD 卡模块代码4. Arduino SD卡数据记录1. 前言 在本Arduino教程中,我们将学习如何将SD卡模块与Arduino板一起使用。此外,结合DS3231实时时钟模块,我们将制作一个数据记录示例,将温度传感器的数据存储到SD卡中…

Vue3技术7之toRaw与markRaw、customRef、provide与inject、响应式数据的判断、组合式API的优势分析

Vue3技术7 toRaw与markRawtoRawApp.vueDemo.vue markRawDemo.vue 总结 customRefApp.vue总结 provide与inject目录结构App.vueChild.vueSon.vue总结 响应式数据的判断App.vue总结 组合式API的优势配置式的API存在的问题组合式API的优势 toRaw与markRaw toRaw App.vue <te…

H7-TOOL的CANFD Trace全解析功能制作完成,历时一个月(2023-04-28)

为了完成这个功能&#xff0c;差不多耗费了一个月时间&#xff0c;精神状态基本已经被磨平了。 当前已经支持&#xff1a; 1、LUA小程序控制&#xff0c;使用灵活。 2、采用SWD接口直接访问目标板芯片的CANFD外设寄存器和CANFD RAM区实现&#xff0c;支持USB&#xff0c;以太网…

Paimon: Streaming data lake 数据湖项目的后起之秀

什么是Paimon? Paimon的官网介绍是&#xff1a;Streaming data lake platform with high-speed data ingestion, changelog tracking and efficient real-time analytics. Paimon 是流数据湖平台&#xff0c;具有高速数据摄取、变更日志跟踪和高效的实时分析能力 数据湖是大…

Vue 路由

文章目录 Vue 路由安装简单实例NPM 路由实例 Vue 路由 本章节我们将为大家介绍 Vue.js 路由。 Vue.js 路由允许我们通过不同的 URL 访问不同的内容。 通过 Vue.js 可以实现多视图的单页Web应用&#xff08;single page web application&#xff0c;SPA&#xff09;。 Vue.js…

万字长文 - Nature 综述系列 - 给生物学家的机器学习指南 1

生物数据的规模不断扩大和固有复杂性促使越来越多的人在生物学中使用机器学习来构建相关生物过程的信息和预测模型。所有机器学习技术都是把数据拟合到模型&#xff0c;然而&#xff0c;具体方法千差万别&#xff0c;乍一看似乎令人困惑。在这篇综述中&#xff0c;我们旨在向读…

绩效管理系统有哪些推荐?

绩效管理系统有哪些推荐&#xff1f;市面上的绩效管理系统五花八门&#xff0c;这就来给大家推荐几款优质的&#xff01; 一、如何选择绩效管理系统 在选择绩效管理系统之前&#xff0c;需要先考虑以下几个问题&#xff1a; 了解你的企业目标和需求&#xff1a;在选择绩效管…

( 栈和队列) 225. 用队列实现栈 ——【Leetcode每日一题】

❓225. 用队列实现栈 难度&#xff1a;简单 请你仅使用两个队列实现一个后入先出&#xff08;LIFO&#xff09;的栈&#xff0c;并支持普通栈的全部四种操作&#xff08;push、top、pop 和 empty&#xff09;。 实现 MyStack 类&#xff1a; void push(int x) 将元素 x 压入…

shiro

1 什么是Shiro Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的 API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。 1.2 与Spring Security的对比 Shiro&#xff1a; Shi…

【搭建博客】宝塔面板部署Typecho博客,并发布上线访问

目录 前言 1.安装环境 2.下载Typecho 3.创建站点 4.访问Typecho 5.安装cpolar 6.远程访问Typecho 7.固定远程访问地址 8.配置typecho 前言 Typecho是由type和echo两个词合成的&#xff0c;来自于开发团队的头脑风暴。Typecho基于PHP5开发&#xff0c;支持多种数据库&…

ubuntu22.04安装ROS2

ubuntu22.04安装ROS2 0.前言一、安装ROS21.首先将本地的编码格式修改为utf-82.添加ROS2 GPG key3.安装ROS24.设置环境变量 二、简单测试1.Hello ROS&#xff01;2.ROS Turtle 三、总结 0.前言 最近也没找到什么特别感兴趣的小项目&#xff0c;不过偶然间看见ROS2这个东西&#…