Apache BookKeeper Ledger 的底层存储机制解析

news2025/4/9 11:11:30

Apache BookKeeper 的 ledger(账本)是其核心数据存储单元,底层存储机制结合了日志追加(append-only)、分布式存储和容错设计。Ledger 的数据存储在 Bookie 节点的磁盘上,具体实现涉及 Journal(日志)和 Ledger Storage(账本存储)两个部分。以下是 ledger 底层存储数据的详细机制:


Ledger 存储的整体架构

  1. 分布式存储
    • 一个 ledger 的数据分布在多个 Bookie 节点上(由 ensembleSize 定义,例如 3 个节点)。
    • 每个 Bookie 负责存储 ledger 的一部分或全部数据(取决于 writeQuorum 配置)。
  2. 两阶段存储
    • Journal:实时记录写入操作的事务日志,确保数据持久化。
    • Ledger Storage:长期存储账本数据,优化读取性能。
  3. 文件系统
    • 数据直接存储在 Bookie 节点的本地文件系统中(例如 ext4、XFS),没有额外的数据库层。

底层存储的实现细节

1. Journal(日志)
  • 作用
    • Journal 是 ledger 数据写入的第一步,用于保证数据持久性和一致性。
    • 每次写入条目(entry)时,先追加到 Journal,确保即使系统崩溃也能恢复。
  • 存储位置
    • 配置项 journalDirectory 指定路径(例如 /bookkeeper/journal)。
    • 每个 Bookie 节点独立维护自己的 Journal。
  • 文件结构
    • Journal 由多个日志文件组成,按时间或大小滚动(rollover)。
    • 文件名格式:journal.<timestamp>(例如 journal.1698765432100)。
    • 每个文件是一个顺序追加的二进制文件。
  • 写入过程
    1. 客户端发送条目到 Bookie。
    2. Bookie 将条目序列化为二进制格式,包含:
      • Ledger ID:账本标识。
      • Entry ID:条目序列号。
      • Data:实际数据内容。
    3. 追加到当前 Journal 文件。
    4. 可配置 journalSyncData=true(默认),调用 fsync 强制刷盘,确保数据持久化。
    5. 返回确认(ACK)给客户端。
  • 性能优化
    • Journal 使用顺序写入,适合高吞吐量。
    • 建议将 journalDirectory 放在高速磁盘(例如 SSD)上。
2. Ledger Storage(账本存储)
  • 作用
    • Journal 确认后,数据异步写入 Ledger Storage,用于长期存储和读取。
  • 存储位置
    • 配置项 ledgerDirectories 指定路径(例如 /bookkeeper/ledgers)。
    • 可以配置多个目录(例如 /disk1/ledgers, /disk2/ledgers),分散 I/O 负载。
  • 文件结构
    • Ledger 数据按 ledger 分片存储,目录结构:
    • /bookkeeper/ledgers/
      ├── current/          # 当前活跃的账本文件
      │   ├── 00000001.log  # Ledger ID 1 的数据文件
      │   ├── 00000002.log  # Ledger ID 2 的数据文件
      ├── recovered/        # 崩溃恢复后的文件
      └── compacted/        # 压缩后的文件(可选)

    • 每个 .log 文件对应一个 ledger,包含该 ledger 的所有条目。
  • 写入过程
    1. Journal 写入成功后,条目放入内存缓冲区(EntryLogger)。
    2. 缓冲区满或达到刷新间隔(ledgerStorage_flushInterval)时,异步写入 .log 文件。
    3. 数据按 Entry ID 顺序存储,文件格式为二进制。
  • 索引
    • 为了快速定位条目,BookKeeper 维护一个索引。
    • 配置项 indexDirectories 指定路径(默认与 ledgerDirectories 相同)。
    • 默认使用文件系统索引(FileInfo),可选配置 RocksDB(dbStorage_rocksDB_* 参数)提高性能。
    • 索引记录每个 Entry ID 在 .log 文件中的偏移量。
3. 数据分布
  • Ensemble
    • 一个 ledger 的数据分布在 ensembleSize 个 Bookie 上。
    • 例如,ensembleSize=3,数据可能存储在 bookie1、bookie2、bookie3。
  • Write Quorum
    • 每次写入,数据完整存储在 writeQuorumSize 个 Bookie 上。
    • 如果 writeQuorum < ensembleSize,不同条目可能分布在不同的 Bookie 子集。
  • 副本
    • 每个条目在多个 Bookie 上有副本(由 writeQuorum 控制),提供容错性。

数据写入的完整流程

以 ensembleSize=3, writeQuorum=3, ackQuorum=2 为例:

  1. 客户端
    • 创建 ledger,分配 Ledger ID=1,选择 bookie1、bookie2、bookie3 作为 ensemble。
    • 发送条目 entry1 到 3 个 Bookie。
  2. Bookie
    • bookie1:写入 /journal/journal.<timestamp>,返回 ACK。
    • bookie2:写入 /journal/journal.<timestamp>,返回 ACK。
    • bookie3:写入 /journal/journal.<timestamp>,返回 ACK(可能稍慢)。
    • 客户端收到 2 个 ACK(满足 ackQuorum=2),写入成功。
  3. 异步存储
    • 每个 Bookie 将 entry1 从 Journal 移到 /ledgers/current/00000001.log。
    • 更新索引,记录 entry1 的偏移量。

数据读取

  • 读取流程
    1. 客户端指定 Ledger ID 和 Entry ID。
    2. Bookie 从索引查找条目位置。
    3. 从 .log 文件读取数据返回。
  • 容错
    • 如果某个 Bookie 不可用,客户端从其他副本读取(需要至少 ackQuorum 个副本可用)。

存储特性

  1. 追加式存储
    • Ledger 只支持追加写入(append-only),不支持修改或删除。
    • 删除 ledger 需要关闭并通过 ZooKeeper 删除元数据。
  2. 纠删码(Erasure Coding)
    • 默认不使用纠删码,而是完整副本存储。
    • 可通过配置启用纠删码(实验性功能),减少存储开销。
  3. 持久性
    • Journal 的 fsync 保证写入持久化。
    • Ledger Storage 异步写入,依赖 Journal 恢复一致性。

崩溃恢复

  • Journal 回放
    • Bookie 重启时,检查 Journal 文件,恢复未写入 Ledger Storage 的条目。
    • 恢复后,数据移到 recovered/ 目录。
  • 一致性
    • 只要 ackQuorum 个 Bookie 存活,数据不会丢失。

性能优化

  1. 分离存储
    • 将 journalDirectory 和 ledgerDirectories 放在不同磁盘(例如 SSD 和 HDD),提高 I/O 性能。
  2. 批量写入
    • Journal 支持批量 fsync,减少磁盘同步开销。
  3. 索引优化
    • 使用 RocksDB 替代默认文件索引,加速查找。

总结

Ledger 的底层存储机制:

  • Journal:顺序写入事务日志,保证持久性,存储在 journalDirectory。
  • Ledger Storage:异步存储账本数据,分布在 ledgerDirectories 的 .log 文件中。
  • 索引:记录条目偏移量,存储在 indexDirectories。
  • 分布式:数据按 ensembleSize 分布在多个 Bookie,副本数由 writeQuorum 控制。

这种设计结合了高吞吐量(顺序写入)、低延迟(异步存储)和容错性(多副本),非常适合分布式日志存储需求。你的 Go Demo 数据最终存储在 3 个 Bookie 的 Journal 和 Ledger 文件中,具体路径取决于 Docker Compose 的卷配置

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从代码上深入学习GraphRag

网上关于该算法的解析都停留在大概流程上&#xff0c;但是具体解析细节未知&#xff0c;由于代码是PipeLine形式因此阅读起来比较麻烦&#xff0c;本文希望通过阅读项目代码来解析其算法的具体实现细节&#xff0c;特别是如何利用大模型来完成图谱生成和检索增强的实现细节。 …

【Redis】通用命令

使用者通过redis-cli客户端和redis服务器交互&#xff0c;涉及到很多的redis命令&#xff0c;redis的命令非常多&#xff0c;我们需要多练习常用的命令&#xff0c;以及学会使用redis的文档。 一、get和set命令&#xff08;最核心的命令&#xff09; Redis中最核心的两个命令&…

微前端随笔

✨ single-spa&#xff1a; js-entry 通过es-module 或 umd 动态插入 js 脚本 &#xff0c;在主应用中发送请求&#xff0c;来获取子应用的包&#xff0c; 该子应用的包 singleSpa.registerApplication({name: app1,app: () > import(http://localhost:8080/app1.js),active…

C++中的浅拷贝和深拷贝

浅拷贝只是将变量的值赋予给另外一个变量&#xff0c;在遇到指针类型时&#xff0c;浅拷贝只会把当前指针的值&#xff0c;也就是该指针指向的地址赋予给另外一个指针&#xff0c;二者指向相同的地址&#xff1b; 深拷贝在遇到指针类型时&#xff0c;会先将当前指针指向地址包…

车载诊断架构 --- 整车重启先后顺序带来的思考

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 周末洗了一个澡,换了一身衣服,出了门却不知道去哪儿,不知道去找谁,漫无目的走着,大概这就是成年人最深的孤独吧! 旧人不知我近况,新人不知我过…

【C++11(下)】—— 我与C++的不解之缘(三十二)

前言 随着 C11 的引入&#xff0c;现代 C 语言在语法层面上变得更加灵活、简洁。其中最受欢迎的新特性之一就是 lambda 表达式&#xff08;Lambda Expression&#xff09;&#xff0c;它让我们可以在函数内部直接定义匿名函数。配合 std::function 包装器 使用&#xff0c;可以…

Windows 10/11系统优化工具

家庭或工作电脑使用时间久了&#xff0c;会出现各种各样问题&#xff0c;今天给大家推荐一款专为Windows 10/11系统设计的全能优化工具&#xff0c;该软件集成了超过40项专业级实用程序&#xff0c;可针对系统性能进行深度优化、精准调校、全面清理、加速响应及故障修复。通过系…

浅谈在HTTP中GET与POST的区别

从 HTTP 报文来看&#xff1a; GET请求方式将请求信息放在 URL 后面&#xff0c;请求信息和 URL 之间以 &#xff1f;隔开&#xff0c;请求信息的格式为键值对&#xff0c;这种请求方式将请求信息直接暴露在 URL 中&#xff0c;安全性比较低。另外从报文结构上来看&#xff0c…

LightRAG实战:轻松构建知识图谱,破解传统RAG多跳推理难题

作者&#xff1a;后端小肥肠 &#x1f34a; 有疑问可私信或评论区联系我。 &#x1f951; 创作不易未经允许严禁转载。 姊妹篇&#xff1a; 2025防失业预警&#xff1a;不会用DeepSeek-RAG建知识库的人正在被淘汰_deepseek-embedding-CSDN博客 从PDF到精准答案&#xff1a;Coze…

C++多线程编码二

1.lock和try_lock lock是一个函数模板&#xff0c;可以支持多个锁对象同时锁定同一个&#xff0c;如果其中一个锁对象没有锁住&#xff0c;lock函数会把已经锁定的对象解锁并进入阻塞&#xff0c;直到多个锁锁定一个对象。 try_lock也是一个函数模板&#xff0c;尝试对多个锁…

垃圾回收——三色标记法(golang使用)

三色标记法(tricolor mark-and-sweep algorithm)是传统 Mark-Sweep 的一个改进&#xff0c;它是一个并发的 GC 算法&#xff0c;在Golang中被用作垃圾回收的算法&#xff0c;但是也会有一个缺陷&#xff0c;可能程序中的垃圾产生的速度会大于垃圾收集的速度&#xff0c;这样会导…

Windows环境下开发pyspark程序

Windows环境下开发pyspark程序 一、环境准备 1.1. Anaconda/Miniconda&#xff08;Python环境&#xff09; 如果不怕包的版本管理混乱&#xff0c;可以直接使用已有的Python环境。 需要安装anaconda/miniconda&#xff08;python3.8版本以上&#xff09;&#xff1a;Anaconda…

SSM婚纱摄影网的设计

&#x1f345;点赞收藏关注 → 添加文档最下方联系方式咨询本源代码、数据库&#x1f345; 本人在Java毕业设计领域有多年的经验&#xff0c;陆续会更新更多优质的Java实战项目希望你能有所收获&#xff0c;少走一些弯路。&#x1f345;关注我不迷路&#x1f345; 项目视频 SS…

1110+款专业网站应用程序UI界面设计矢量图标figma格式素材 Icon System | 1,100+ Icons Easily Customize

1110款专业网站应用程序UI界面设计矢量图标figma格式素材 Icon System | 1,100 Icons Easily Customize 产品特点 — 24 x 24 px 网格大小 — 2px 线条描边 — 所有形状都是基于矢量的 — 平滑和圆角 — 易于更改颜色 类别 &#x1f6a8; 警报和反馈 ⬆️ 箭头 &…

Llama 4 家族:原生多模态 AI 创新的新时代开启

0 要点总结 Meta发布 Llama 4 系列的首批模型&#xff0c;帮用户打造更个性化多模态体验Llama 4 Scout 是有 170 亿激活参数、16 个专家模块的模型&#xff0c;同类中全球最强多模态模型&#xff0c;性能超越以往所有 Llama 系列模型&#xff0c;能在一张 NVIDIA H100 GPU 上运…

正则表达式(Regular Expression,简称 Regex)

一、5w2h&#xff08;七问法&#xff09;分析正则表达式 是的&#xff0c;5W2H 完全可以应用于研究 正则表达式&#xff08;Regular Expressions&#xff09;。通过回答 5W2H 的七个问题&#xff0c;我们可以全面理解正则表达式的定义、用途、使用方法、适用场景等&#xff0c…

JMeter脚本录制(火狐)

录制前准备&#xff1a; 电脑&#xff1a; 1、将JMeter证书导入&#xff0c;&#xff08;bin目录下有一个证书&#xff0c;需要安装这个证书到电脑中&#xff09; 2、按winr&#xff0c;输入certmgr.msc&#xff0c;打开证书&#xff0c;点击下一步&#xff0c;输入JMeter证书…

基于SpringBoot的“高校社团管理系统”的设计与实现(源码+数据库+文档+PPT)

基于SpringBoot的“高校社团管理系统”的设计与实现&#xff08;源码数据库文档PPT) 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBoot 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 总体功能结构图 局部E-R图 系统首页页面 用户…

C# Winform 入门(3)之尺寸同比例缩放

放大前 放大后 1.定义当前窗体的宽度和高度 private float x;//定义当前窗体的宽度private float y;//定义当前窗台的高度 2.接收当前窗体的尺寸大小 x this.Width;//存储原始宽度ythis.Height;//存储原始高度setTag(this);//为控件设置 Tag 属性 3.声明方法&#xff0c;获…

infinityfree最新免费建站详细教程_无需备案_5G空间_无限流量_免费域名_免费SSL

一、明确目标—是否要使用 1.为什么选择InfinityFree&#xff1f; 对于初学者、学生或只是想尝试网站搭建的个人用户来说&#xff0c;InfinityFree提供了一个绝佳的免费解决方案。这个国外免费的虚拟主机服务提供&#xff1a; 5GB存储空间 - 足以存放个人博客、作品集或小型…