Pulsar 元数据服务设计

在分布式系统中,元数据如同导航地图,指引着各个组件准确无误地工作。Pulsar 作为一款采用存算分离架构的分布式消息队列,其核心组件包括负责存储服务的 BookKeeper 和承担计算任务的 Broker。为了确保这些组件的高效协同运作,一个稳定可靠的元数据存储服务显得尤为重要。本文将深入探讨 Pulsar 元数据服务的设计理念与实现细节。

BookKeeper 元数据设计

BookKeeper 的定位是一个可用于实时场景下的高扩展性、强容错、低延迟的存储服务。适合作为日志、流式数据、Topic 这类服务的持久化服务。

BookKeeper 中的基本概念

Ledger:它是 BK 的一个基本存储单元,BK Client 的读写操作也都是以 Ledger 为粒度的;类似文件系统中的一个文件,ledgerID 就是个唯一的文件名。 Fragment:是 Ledger 的组成单位,一个 Ledger 可能由1个或多个 Fragment 组成;当前 Fragment 使用的 Bookies 发生写入错误或超时,系统会在剩下的 Bookie 中新建 Fragment。 Entry:每条日志都是一个 Entry,它代表一个 record,每条 record 都会有一个对应的 entry id; 关于 Fragment,它是 Ledger 的物理组成单元,也是最小的物理存储单元,在以下两种情况下会创建新的 Fragment:

BookKeeper 元数据

Bookie集群的元数据在 ZK里有以下4个目录: 1、00,保存所有ledger元数据,根据ledgerID可以找到数据在哪个Bookie节点上存着。为了防止某个目录下node过多,通过多级目录打散。

shell 复制代码
└── 00
    ├── 0000
    │   ├── L0001
    │   ├── L0002
    │   ├── L0003
    ├── 0001
    │   ├── L0011
    │   ├── L0012
    │   └── L0013
    └── 0002
        └── L0397

bookKeeper 使用了一种固定算法,将 long 类型的 ledger ID 转化成 00/0000/L0001 这样的字符串,作为zookeeper 中的path。 一个ledger的元数据如下,解码后的内容为:

json 复制代码
{
  "23632": {
    "ledgerId": 23632, //ledgerId
    "metadataFormatVersion": 3,
    "ensembleSize": 3,//将数据分布到几个bookie节点
    "writeQuorumSize": 3,//数据存储的副本数
    "ackQuorumSize": 3,//返回给客户端前,要求写成功的副本数
    "state": "OPEN",//ledger 当前状态,有:CLOSED、IN_RECOVERY、OPEN
    "length": 0,
    "lastEntryId": -1,
    "ctime": 1739245083147,
    "digestType": "CRC32C",
    "password": "",
    "customMetadata": {
      "pulsar/managed-ledger": "YmVuY2htYXJrL3RuL3BlcnNpc3RlbnQvdHAtcGFydGl0aW9uLTA=", //the name of the ledger
      "component": "bWFuYWdlZC1sZWRnZXI=",
      "application": "cHVsc2Fy"
    },
    "closed": false,
    "allEnsembles": {//Fragment集合,这里有2个Fragment
      "0": [//Fragment1,Entry0~167的数据所在的bookie节点
        {
          "id": "10.224.129.239:3181"
        },
        {
          "id": "10.224.130.217:3181"
        },
        {
          "id": "10.224.130.218:3181"
        }
      ],
      "168": [//Fragment2,Entry168以后的数据所在的bookie节点
        {
          "id": "10.224.129.253:3181"
        },
        {
          "id": "10.224.130.217:3181"
        },
        {
          "id": "10.224.130.218:3181"
        }
      ]
    },
    "ctoken": 0
  }
}

2、available,保存集群中的bookie节点,包括可用和只读的 3、cookies,保存bookie节点数据目录配置和集群ID

shell 复制代码
bookieHost: "10.224.130.218:3181" journalDir: "/data/bookkeeper/journal" ledgerDirs: "1\t/data/bookkeeper/ledgers" instanceId: "2a7890d3-1c66-40f0-b271-1a051b0682e6"

4、underreplication,用于autorecovery恢复数据的所有元信息 auditorelection:AutoRecovery 的 leader 节点,leader节点扫描缺副本的ledger,将结果写到下面的 ledgers 目录下。 ledgers:缺副本的ledger locks:AutoRecovery 的 Worker 节点各自分配一些缺副本的 ledger,进行修复。

Broker 元数据设计

Broker作为计算层,实现了MQ的topic模型,比如 topic 信息、数据持久化(保存和过期)、消费进度记录。 在 Pulsar 内部,一个topic使用多个 BookKeeper 的 Ledgers 来存储数据,当 Ledger 中的 Entry 条数超过客户端配置的数量时,将滚动创建新Ledger,当 Ledger 中的所有游标都消费完了 Ledger 中的消息时,Ledger 可以被删除。

topic 与ledger 的映射关系就记录在元数据服务里。当新打开一个ledger 时,才会更新zk里的元信息,每次插入数据不会更新元数据,因此元数据服务压力较小。

元数据路径: /managed-ledgers/[tenant]/[namespace]/persistent/[test-topic-partition-0]

json 复制代码
ledgerInfo {
  ledgerId: 20420
  entries: 522
  size: 32758
  timestamp: 1737290581468
}
ledgerInfo {
  ledgerId: 20426
  timestamp: 0
}

消费进度也保存在Bookie中,元数据路径: /managed-ledgers/[tenant]/[namespace]/persistent/[test-topic-partition-0]/[subscription-name]

bash 复制代码
cursorsLedgerId: 20432
markDeleteLedgerId: 20419
markDeleteEntryId: 11
lastActive: 1737276571526

Message对应的schema,由客户端注册到broker上,数据存储到bookie中,这里保存了schema存在哪个ledger上 元数据路径: /schemas/[tenant]/[namespace]/[test-topic]

bash 复制代码
info {
  version: 0
  position {
    ledgerId: 20421
    entryId: 0
  }
  hash: "\343\260\304B\230\374\034\024\232\373\364\310\231o\271$\'\256A\344d\233\223L\244\225\231\033xR\270U"
}
index {
  version: 0
  position {
    ledgerId: 20421
    entryId: 0
  }
  hash: "\343\260\304B\230\374\034\024\232\373\364\310\231o\271$\'\256A\344d\233\223L\244\225\231\033xR\270U"
}

参考

1\]. BookKeeper 原理浅谈 [matt33.com/2019/01/28/...](https://link.juejin.cn?target=https%3A%2F%2Fmatt33.com%2F2019%2F01%2F28%2Fbk-store-realize "https://matt33.com/2019/01/28/bk-store-realize") \[2\]. Bookkeeper AutoRecovery [bookkeeper.apache.org/docs/admin/...](https://link.juejin.cn?target=https%3A%2F%2Fbookkeeper.apache.org%2Fdocs%2Fadmin%2Fautorecovery%2F "https://bookkeeper.apache.org/docs/admin/autorecovery/")

相关推荐
炒空心菜菜9 小时前
SparkSQL 连接 MySQL 并添加新数据:实战指南
大数据·开发语言·数据库·后端·mysql·spark
蜗牛沐雨11 小时前
Rust 中的 `PartialEq` 和 `Eq`:深入解析与应用
开发语言·后端·rust
Python私教11 小时前
Rust快速入门:从零到实战指南
开发语言·后端·rust
秋野酱12 小时前
基于javaweb的SpringBoot爱游旅行平台设计和实现(源码+文档+部署讲解)
java·spring boot·后端
小明.杨12 小时前
Django 中时区的理解
后端·python·django
有梦想的攻城狮12 小时前
spring中的@Async注解详解
java·后端·spring·异步·async注解
qq_124987075312 小时前
原生小程序+springboot+vue医院医患纠纷管理系统的设计与开发(程序+论文+讲解+安装+售后)
java·数据库·spring boot·后端·小程序·毕业设计
lybugproducer13 小时前
浅谈 Redis 数据类型
java·数据库·redis·后端·链表·缓存
焚 城13 小时前
.NET8关于ORM的一次思考
后端·.net
撸猫79115 小时前
HttpSession 的运行原理
前端·后端·cookie·httpsession