【kafka系列】日志存储设计 消息写入、读取

目录

日志存储设计

1. 日志存储的目录结构

2. 日志内容格式设计

3. 日志索引设计

4. 设计优势

消息写入流程

示例

流程图

消息读取流程

示例

关键设计细节

流程图


日志存储设计

Kafka的日志存储是其高吞吐、持久化能力的核心设计,其结构包含目录组织消息格式索引设计三部分。


1. 日志存储的目录结构
  • 分区目录:每个Topic分区对应一个目录,命名格式为<topic>-<partition>,例如orders-0
  • Segment文件:每个分区目录下包含多个日志段(Segment),每个段由两个文件组成:
    • .log文件:存储实际消息(如00000000000000000000.log),文件名基于基准位移(Base Offset),即该段第一条消息的Offset。
    • .index文件:稀疏索引文件(如00000000000000000000.index),记录Offset到物理位置的映射。
  • 活跃段(Active Segment):当前正在写入的Segment,文件名格式为<nextOffset>.log,例如新段的第一条消息Offset为100,则文件名为00000000000000000100.log

源码关键类

  • Log:管理分区的所有Segment(ConcurrentNavigableMap<Long, LogSegment>)。
  • LogSegment:封装单个Segment的.log和.index文件操作。

2. 日志内容格式设计

Kafka消息以**批次(RecordBatch)**为单位存储,每个批次包含多条消息,减少I/O开销。单条消息格式如下:

RecordBatch Header:Base Offset (int64)Length (int32)Partition Leader Epoch (int32)Magic (int8)CRC (int32)Attributes (int16)Last Offset Delta (int32)First Timestamp (int64)Max Timestamp (int64)Producer ID (int64)Producer Epoch (int16)Base Sequence (int32)Records Count (int32)Record (多条):Length (varint)Attributes (int8)Timestamp Delta (varint)Offset Delta (varint)Key (varint bytes)Value (varint bytes)Headers (varint array)

特点

  • 紧凑二进制格式:通过变长类型(varint)和位移差值(Delta)压缩空间。
  • 批量写入:多个Record打包成RecordBatch,减少网络和磁盘I/O。
  • 幂等与事务支持:通过Producer IDEpochSequence字段实现。

3. 日志索引设计
  • 稀疏索引(Sparse Index):.index文件不记录每条消息的Offset,而是每隔一定消息量(如4KB)记录一个索引项。
  • 索引项结构:每个索引项占8字节,包含两个字段:
    • Relative Offset:相对于基准位移的差值(4字节)。
    • Physical Position:对应.log文件中的物理位置(4字节)。

索引查询流程(源码见OffsetIndex类):

  1. 根据目标Offset,通过二分查找找到最近的索引项。
  2. 从.log文件的对应位置开始顺序扫描,直到找到目标消息。

4. 设计优势
  • 高效查询:稀疏索引+顺序扫描平衡了索引大小与查询速度。
  • 快速扩容:Segment文件按基准Offset分割,易于清理旧数据和扩展新文件。
  • 高吞吐:批量写入、页缓存、零拷贝等技术最大化磁盘和网络效率。

通过这种设计,Kafka在保证消息持久化的同时,实现了百万级TPS的吞吐能力。


消息写入流程

示例

生产者发送一条消息{"order_id": 1001}到Topic orders的Partition 0。

写入流程

  1. 选择分区:根据Partitioner确定消息写入orders-0
  2. 追加到活跃段
    • Broker将消息封装为RecordBatch,追加到当前活跃段(如00000000000000001000.log)。
    • 更新对应的索引文件00000000000000001000.index(每隔4KB或一定时间写入索引项)。
  1. 刷盘策略:根据log.flush.interval.messageslog.flush.interval.ms决定何时将数据从页缓存刷到磁盘。

源码关键方法

  • Log.append():处理消息追加。
  • LogSegment.append():写入.log文件并更新索引。

流程图


消息读取流程

示例

消费者请求读取Offset为1005的消息。

1. 消费者发送FetchRequest:请求包含目标Topic、Partition和Offset(例如Offset=1005)。
2. Broker验证Offset有效性

  • 检查Offset是否在LogStartOffset(日志起始位移)和HighWatermark(已提交消息的最大位移)之间。
  • 若Offset无效(如小于LogStartOffset或大于HighWatermark),返回错误OFFSET_OUT_OF_RANGE
  1. 定位Segment文件
    • Broker根据Offset值,在分区的Log对象中通过二分查找找到对应的LogSegment
    • 具体逻辑:在LogSegments(一个有序的ConcurrentNavigableMap)中调用floorEntry(Offset),找到基准Offset ≤ 目标Offset的Segment。
    • 示例:Offset=1005 → 找到基准Offset=1000的Segment(文件00000000000000001000.log)。
  1. 加载索引文件
    • 打开对应Segment的.index文件(稀疏索引),通过内存映射(MappedByteBuffer)加载到内存。
  1. 解析Offset并查询索引
    • 计算相对Offset目标Offset - 基准Offset(如1005 - 1000 = 5)。
    • .index文件中二分查找最接近且≤相对Offset的索引项。
    • 示例:索引项可能为[4 → 4096](相对Offset=4,对应.log文件的物理位置4096字节)。
  1. 定位消息物理位置
    • 根据索引项中的物理位置(4096),从.log文件的该位置开始顺序扫描
    • 逐条解析消息头中的Offset,直到找到目标Offset=1005的消息。
  1. 操作系统缓存与文件缓存
    • 页缓存(Page Cache):Kafka依赖操作系统的页缓存机制,.log.index文件会被缓存到内存,后续读取直接从内存访问,避免磁盘I/O。
    • 内存映射(Memory-Mapped Files):索引文件通过MappedByteBuffer映射到内存,加速索引查询。
  1. 返回消息数据
    • 将找到的消息数据封装为FetchResponse返回给消费者,消息内容可能直接从页缓存中读取(零拷贝优化)

关键设计细节

1. Offset解析与索引查询

  • 相对Offset计算
    索引文件中存储的是相对于Segment基准Offset的差值(如基准Offset=1000,索引项中的相对Offset=5 → 实际Offset=1005)。
  • 稀疏索引优化
    索引文件仅记录部分Offset(如每隔4KB),通过二分查找快速定位到近似位置,再顺序扫描少量数据。

2. 文件定位与缓存机制

  • Segment文件定位
    LogSegments使用ConcurrentNavigableMap维护所有Segment,floorEntry(Offset)方法通过跳表(Skip List)快速查找。
  • 操作系统缓存
    • 页缓存:Kafka的.log文件读写完全依赖操作系统的页缓存,消息读取时直接从内存访问,避免磁盘寻址。
    • 内存映射文件:.index文件通过FileChannel.map()映射到内存,索引查询几乎无磁盘I/O。

3. 顺序扫描优化

  • 批量读取:从.log文件的物理位置开始,按块(如8KB)读取数据,减少小文件I/O次数。
  • 零拷贝(Zero-Copy)
    消息数据通过FileChannel.transferTo()直接从页缓存发送到网络Socket,无需经过用户态(源码见FileRecords.writeTo())。

流程图


 


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

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

相关文章

复杂电磁环境下无人机自主导航增强技术研究报告——地磁匹配与多源数据融合方法,附matlab代码

本文给出介绍和matlab程序&#xff0c;来实现地磁辅助惯性导航仿真验证&#xff0c;包含地磁基准图构建、飞行轨迹生成、INS误差建模、地磁匹配定位及多源数据融合等模块。通过对比分析验证地磁匹配修正惯性导航累积误差的有效性&#xff0c;可视化显示卫星拒止环境下的航迹修正…

springboot项目读取 resources 目录下的文件的9种方式

1. 使用 ClassLoader.getResourceAsStream() 方法 InputStream inputStream getClass().getClassLoader().getResourceAsStream(“file.txt”); 2.使用 Class.getResourceAsStream() 方法 InputStream inputStream getClass().getResourceAsStream(“/file.txt”); 3.使用 Re…

基于SSM+uniapp的鲜花销售小程序+LW示例参考

1.项目介绍 系统角色&#xff1a;管理员、商户功能模块&#xff1a;用户管理、商户管理、鲜花分类管理、鲜花管理、订单管理、收藏管理、购物车、充值、下单等技术选型&#xff1a;SSM&#xff0c;Vue&#xff08;后端管理web&#xff09;&#xff0c;uniapp等测试环境&#x…

硕成C语言22【一些算法和数组的概念】

1.求水仙花数 #include <stdio.h>int main() {//求水仙花数&#xff1a;1.三位数 2.个位的立方十位的立方百位的立方该数int unit, tens, hundreds;for (int i 100; i < 1000; i)//i表示该水仙花数{unit i / 1 % 10;tens i / 10 % 10;hundreds i / 100 % 10;if (…

游戏引擎学习第101天

回顾当前情况 昨天的进度基本上完成了所有内容&#xff0c;但我们还没有进行调试。虽然我们在运行时做的事情大致上是对的&#xff0c;但还是存在一些可能或者确定的bug。正如昨天最后提到的&#xff0c;既然现在时间晚了&#xff0c;就不太适合开始调试&#xff0c;所以今天我…

无人机航迹规划:互联银行系统优化(Connected Banking System Optimizer,CBSO)求解无人机路径规划MATLAB

一、互联银行系统优化算法 互联银行系统优化&#xff08;Connected Banking System Optimizer&#xff0c;CBSO&#xff09;算法是2024年由Mehrdad Nemati等人提出的一种智能优化算法&#xff0c;其灵感来源于银行系统之间的连接和交易过程。在银行系统中&#xff0c;核心银行…

【清晰教程】通过Docker为本地DeepSeek-r1部署WebUI界面

【清晰教程】本地部署DeepSeek-r1模型-CSDN博客 目录 安装Docker 配置&检查 Open WebUI 部署Open WebUI 安装Docker 完成本地DeepSeek-r1的部署后【清晰教程】本地部署DeepSeek-r1模型-CSDN博客&#xff0c;通过Docker为本地DeepSeek-r1部署WebUI界面。 访问Docker官…

css简介

一.css-网页的美容师 css也是一种标记语言&#xff0c;主要用于设置HTML页面中的文本内容(字体大小对齐方式)&#xff0c;图片外形&#xff08;宽高 边框样式 边距等&#xff09;以及版面的布局和外观显示样式。 二.css语法规范 css规则由两个主要的部分构成:选择器以及一条…

Postman如何流畅使用DeepSeek

上次写了一篇文章是用chatBox调用api的方式使用DeepSeek&#xff0c;但是实际只能请求少数几次就不再能给回响应。这回我干脆用最原生的方法Postman调用接口请求好了。 1. 通过下载安装Postman软件 postman下载(https://pan.quark.cn/s/c8d1c7d526f3)&#xff0c;包含7.0和10…

DC-6靶机渗透测试全过程

目录 前期准备 一、渗透测试 1.IP地址查询 2.端口信息搜寻 3.网页信息搜集 wappalyzer WPScan 反弹shell graham用户 反弹出jens的shell nmap提权 二、总结 前期准备 攻击机&#xff1a; kali windows11 靶机&#xff1a;DC-6靶机&#xff08;调至NAT模式&#xff0…

以若依移动端版为基础,实现uniapp的flowable流程管理

1.前言 此代码是若依移动端版为基础&#xff0c;实现flowable流程管理&#xff0c;支持H5、APP和微信小程序三端。其中&#xff0c;APP是在安卓在雷电模拟器环境下完成的&#xff0c;其他环境未测试&#xff0c;此文章中所提及的APP均指上述环境。移动端是需要配合若依前后端分…

C++ Primer 返回值和return语句

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

dma_ddr 的编写 通过mig控制ddr3

此外还有别的模块 本模块是 其中一个 timescale 1ns/1ps module dma_ctrl (input wire ui_clk , //100MHZ 用户时钟input wire ui_rst_n ,//写fifo的写端口 input wire wf_wr_clk , //由数据产生模块的时…

【15】思科AireOS:创建使用 PSK 认证的 WLAN

1. 概述 在 Cisco AireOS 无线局域网控制器(WLC)上,您可以配置基于预共享密钥(PSK)的 WLAN,以提供无线访问。PSK 认证是一种 WPA2/WPA3 个人模式下常用的认证方式,适用于家庭或小型企业环境。 本指南将详细介绍如何在 Cisco AireOS WLC 上配置 PSK 认证的 WLAN,并确保…

基于css实现正六边形的三种方案

方案一&#xff1a;通过旋转三个长方形生成正六边形 分析&#xff1a; 如下图所示&#xff0c;我们可以通过旋转三个长方形来得到一个正六边形。疑问&#xff1a; 1. 长方形的宽高分别是多少&#xff1f; 设正六边形的边长是100&#xff0c;基于一些数学常识&#xff0c;可以…

Python用PyMC3马尔可夫链蒙特卡罗MCMC对疾病症状数据贝叶斯推断

全文链接&#xff1a;https://tecdat.cn/?p39937 本文聚焦于马尔可夫链蒙特卡罗&#xff08;MCMC&#xff09;方法在贝叶斯推断中的Python实现。通过介绍MCMC的基础原理、在贝叶斯推断中的应用步骤&#xff0c;展示了其在解决复杂分布采样问题上的强大能力。同时&#xff0c;借…

linux--关于makefile

makefile文件 可以指定编译顺序&#xff0c;这样方便一个项目的多个文件要编译的挨个操作的麻烦。 makefile文件的命名&#xff1a;makefile 或者 Makefile 必须是这俩&#xff0c;系统才能识别 规则的书写语法如下&#xff1a; 一个makefile内可以有多个规则 目标:依赖a 依…

何须付费免费它不香吗

聊一聊 又是一年开学季。 开学了发一些应时期的小软件。 今天给大家分享一款学校班级课程表工具。 这款工具可以投放在学校电子大屏上。 支持学校的白板软件。 软件介绍 学校班级课程表 工具界面清爽&#xff0c;信息能一目了然。 虽然看感觉功能简单&#xff0c;但每个…

day10后期软件

美图秀秀&#xff1a;美拍拼图、Facetune&#xff1a;面部重塑、泼辣修图&#xff1a;手机中的PS Lightroom&#xff1a;精致调色 想法类&#xff1a; 玩创意特效 PicsArt:很强大 排版类&#xff1a;精美杂志风 MOLDIV&#xff1a;无损排版&#xff1b;天天P图&#xff1a…

用大模型学大模型03-数学基础 概率论 条件概率 全概率公式 贝叶斯定理

要深入浅出地理解条件概率与贝叶斯定理&#xff0c;可以从以下几个方面入手&#xff0c;结合理论知识和实例进行学习&#xff1a; 贝叶斯定理与智能世界的暗语 条件概率&#xff0c;全概率公式与贝叶斯公式的推导&#xff0c;理解和应用 拉普拉斯平滑 贝叶斯解决垃圾邮件分类 …