Apache Pulsar PIP-157 深度解读:用主题桶(Topic Bucketing)打破单命名空间的主题数量上限
消息队列流处理后端微服务消息路由【免费下载链接】pulsarApache Pulsar - distributed pub-sub messaging system项目地址https://gitcode.com/gh_mirrors/pu/pulsar点击查看免费下载本文围绕 Apache Pulsar 的 PIP-157 提案展开讲清楚“单个命名空间内主题数量受元数据存储制约”这一问题的成因、分桶bucketing方案的总体设计、新增命名空间策略numberOfTopicBuckets的语义、桶分配的哈希规则与元数据目录示例并结合当前仓库中TopicResources、TopicName等源码位置说明该特性在元数据持久化链路上的具体挂载点帮助读者完整理解这一扩容方案的原理与落地边界。一、问题背景为什么单命名空间的主题数量存在上限Pulsar 可以管理数百万个主题但单个命名空间内的主题数量受到元数据存储的制约。提案文档pip/pip-157.md在 Motivation 一节给出了直接原因命名空间内的每个主题在 ZooKeeper 中对应一个节点。列出list主题意味着对某个节点做子节点列举list children而这一操作在主题数达到约 1 万10K时就会触碰到 ZooKeeper 的能力上限。从当前仓库源码可以印证这一元数据布局。pulsar-broker-common模块中集中管理/managed-ledgers路径访问的 TopicResources 类其列举持久主题的实现是public CompletableFutureListString listPersistentTopicsAsync(NamespaceName ns) { String path MANAGED_LEDGER_PATH / ns /persistent; return store.getChildren(path).thenApply(children - ...); }即给定命名空间tenant/namespace主题直接平铺在/managed-ledgers/tenant/namespace/persistent/之下。store.getChildren(path)一次返回该路径下所有子节点——这正是瓶颈所在主题越多该节点子节点越多ZooKeeper 的 getChildren 调用越慢、越容易失败最终限制单命名空间的主题规模。二、方案目标在 topic 节点前插入中间层bucketsPIP-157 的核心目标是在 topic 节点之前插入一层“桶”buckets中间层把原来的持久化路径/managed-ledgers/tenant/namespace/domain/topic改造为/managed-ledgers/tenant/namespace/domain/bucket/topic这样列举一个命名空间下的主题时不再需要对一个巨大的节点做 getChildren而是对若干个桶节点分别列举单节点的子节点规模被摊薄从而支撑单个命名空间内的主题数量大幅提升。提案中还明确了两个重要的设计约束默认关闭、按命名空间粒度启用。该特性默认处于关闭状态仅在创建命名空间时通过设置策略policy按命名空间启用。这样完全避免了对存量集群进行元数据迁移的需要——旧命名空间保持原有结构不变。桶与 bundle 没有对应关系。桶bucket只服务于元数据的列举性能与 Pulsar 中用于负载分担的 bundle 机制相互独立运维人员不需要也无法把两者对应起来理解。三、API 变化新增命名空间策略numberOfTopicBucketsPIP-157 在 API 层面的变化很小但很关键新增一个命名空间策略numberOfTopicBuckets。语义取值行为默认值 11不分桶完全保持命名空间当前的行为路径中无桶层分桶 1主题的元数据将存储在包含桶的层级路径下同时提案明确规定命名空间创建后用户不能修改桶的数量。这一约束来自“分桶意味着物理路径结构变更变更桶数等价于对全部主题元数据做一次原子搬迁”的事实考量后文的“被拒绝的替代方案”一节也呼应了这一点。值得说明的是基于对当前仓库的检索numberOfTopicBuckets这一策略尚未出现在代码库中pip/pip-157.md 是该特性的设计载体也就是说当前代码库快照处于该特性的设计/实施阶段。下文的实现分析均基于该 PIP 的设计描述并结合仓库中现有代码结构指出其接入点。四、实现方案对用户透明的持久化命名翻译PIP-157 在 Implementation 一节的总体原则是该特性对用户透明。客户端继续以domain://tenant/namespace/topic的形式引用主题Pulsar 在内部“按需”把它翻译成新的持久化命名含桶号。提案给出的实现机制是向TopicName.getPersistenceNamingEncoding提供桶号bucket number并据此计算出修改后的路径。当前仓库中该方法位于 TopicName.java现有实现按领域生成持久化相对路径public String getPersistenceNamingEncoding() { // The convention is: domain://tenant/namespace/topic // We want to persist in the order: tenant/namespace/domain/topic if (domain TopicDomain.segment segmentRange ! null) { return String.format(%s/%s/%s/%s/%04x-%04x-%d, tenant, namespacePortion, domain, getEncodedLocalName(), segmentRange.start(), segmentRange.end(), segmentId); } if (domain TopicDomain.topic) { return String.format(%s/%s/%s, tenant, namespacePortion, getEncodedLocalName()); } return String.format(%s/%s/%s/%s, tenant, namespacePortion, domain, getEncodedLocalName()); }对普通 persistent/non-persistent 主题编码结果形如tenant/namespace/persistent/topic即四段形式TopicNameTest 中的断言assertEquals(name.getPersistenceNamingEncoding(), prop/ns/persistent/ encodedName)正是对这一格式的固化。PIP-157 的改造点即在这里为该编码方法引入桶号参数使普通主题的编码结果变为tenant/namespace/domain/$N/topic形式的五段路径桶号大于 1 时。与编码对应的反向解析方法是 fromPersistenceNamingEncoding它目前按段数区分四种情况4 段标准格式、5 段且第三段为segment分段主题、5 段遗留 V1 格式tenant/cluster/namespace/domain/topic、其余抛异常。从源码结构看引入桶层后这里需要新增对“五段且第三段为 domain 的桶化路径”的识别这是实现时需要处理的兼容性细节之一。提案同时强调元数据存储metadata store的工作方式不受影响。pulsar-metadata层的抽象不感知“桶”的语义分桶只体现在 broker 侧计算出的路径上。4.1 桶的分配规则哈希取模主题分配到哪个桶采用确定性规则以主题名称的哈希码hash code绝对值对桶数取模即abs(topicName.hashCode()) % numberOfBuckets。这一规则保证了同一主题在任意 broker、任意时刻计算出的桶号一致因而对主题的创建、存在性检查、列举等操作都指向同一个物理路径无需额外的“桶路由表”或一致性协调。4.2 主要工作量让命名空间策略在“计算持久化命名处”可用提案指出该特性的大部分改动量在于让命名空间策略namespace policies在所有需要计算持久化命名的位置可用——因为要知道某主题进哪个桶就必须先知道其命名空间的numberOfTopicBuckets值。在需要列举命名空间内主题的场景包括检查单命名空间主题数量上限是否已触达新的中间层会带来额外开销每个桶一次元数据存储请求取代原来的一次请求。这是设计者明示的性能权衡——用“桶数次 getChildren”换取“单个 getChildren 不再触碰 ZooKeeper 大节点上限”在桶数通常较小的前提下开销可控。4.3 Schema 存储无需改动由于瓶颈在“列举主题”通过 managed ledgers 的路径完成提案明确不需要修改 schema 存储并且当前存储在/managed-ledgers/tenant/namespace/domain/topic下的数据结构与内容保持不变只是在新路径下可用。五、元数据目录示例PIP-157 给出了同一组主题在“无分桶”与“3 个桶”两种布局下的目录对照是该文档最直观的说明这里完整保留。原始层级无分桶managed-ledgers \- tenant \- namespace \- persistent - nptopic1 - nptopic2 - ptopic-partition-0 - ptopic-partition-1 - ptopic-partition-2 \- ptopic-partition-3在 3 个桶的情况下同样的主题元数据按如下方式分布managed-ledgers \- tenant \- namespace \- persistent - $0 | - ptopic-partition-0 | \- ptopic-partition-3 - $1 | - nptopic2 | \- ptopic-partition-1 \- $2 - nptopic1 \- ptopic-partition-2桶节点以$0、$1、$2命名各主题按“哈希绝对值对 3 取模”落入对应桶。注意示例中ptopic的 4 个分区被分散到了三个不同桶中——分桶按分区主题partitioned topic 的各个分区作为独立主题逐个计算而不是把整个逻辑主题固定在同一桶内。六、兼容性设计PIP-157 的兼容性承诺非常明确可以概括为两条存量命名空间不受影响既有命名空间以及创建时未显式启用该特性的命名空间行为与路径完全保持现状numberOfTopicBuckets缺省为 1 时即无桶层。启用了分桶的命名空间可以像其他命名空间一样使用管理、生产、消费、列举等所有既有 API 语义不变客户端无感知。这套“默认关闭 按命名空间启用 创建后不可变更桶数”的组合使得该特性天然向后兼容集群无需升级元数据格式旧路径与新路径可以长期共存于同一集群。七、被拒绝的替代方案PIP-157 的 Rejected alternatives 一节值得单独展开它解释了为什么最终选择了“按命名空间可选分桶”而不是其他看似更优雅的方案对所有命名空间全局引入分桶。这会让元数据结构更统一homogeneous但要求在所有 broker 升级完成后把全部主题的元数据从旧路径原子地搬迁到新路径需要复杂的更新逻辑与升级协调。允许修改桶数量。基于同样的原因变更桶数等价于一次全量元数据搬迁因此“可修改桶数”不在本提案的目标范围内。在 ZK 元数据存储实现内部解决。该问题虽然与 ZooKeeper 相关若把“分桶”逻辑塞进 ZK 版 metadata store 的实现就必须让该层理解“什么路径代表什么含义”即主题、命名空间从而破坏关注点分离——metadata store 应保持对路径语义无感知这正是提案坚持在 broker 侧命名空间策略 持久化命名计算解决的原因。八、结合当前仓库看特性接入点与现状把 PIP-157 的设计映射回当前仓库的代码结构可以清晰地看到几个既定的接入点持久化路径的统一出口TopicResources 是 broker 侧对/managed-ledgers的集中封装创建主题createPersistentTopicAsync使用topic.getPersistenceNamingEncoding()拼路径、存在性检查persistentTopicExists、列举listPersistentTopicsAsync、getExistingPartitions都经过这里。从源码结构看分桶后的列举逻辑逐桶 getChildren 再聚合以及桶化路径的创建/检查逻辑最自然的落点就是这个抽象层。命名翻译TopicName.getPersistenceNamingEncoding / fromPersistenceNamingEncoding 是domain://tenant/namespace/topic与持久化路径之间互译的唯一权威实现PIP 中“向该编码方法提供桶号”的描述正对应于此TopicNameTest 中的多组编码/解码断言也表明桶化改造需要以同样的测试风格固化新的四段/五段格式。策略载体numberOfTopicBuckets属于命名空间策略其不可变性约束需要在命名空间创建/策略修改的校验逻辑中落地。需要如实指出的是在当前仓库快照中代码检索未发现numberOfTopicBuckets策略或桶化路径的实现getPersistenceNamingEncoding也尚不接受桶号参数。因此本文关于分桶行为桶命名$N、哈希取模分配、逐桶列举开销等的描述均以 pip/pip-157.md 的提案文本为准属于“设计目标”层面的事实仓库源码部分则用于说明该设计在现有元数据链路上的挂载位置而非对已落地实现的描述。九、小结PIP-157 用一组非常克制的改动解决了 Pulsar 单命名空间主题数量的天花板问题机制在/managed-ledgers/tenant/namespace/domain/topic中插入桶层把大节点的 getChildren 拆分为若干个桶节点的小规模列举控制面新增命名空间策略numberOfTopicBuckets默认 1不分桶创建后不可修改桶与 bundle 无关联透明性客户端命名domain://tenant/namespace/topic不变分桶只发生在 broker 内部由getPersistenceNamingEncoding承载的持久化命名翻译中分配规则abs(topicName.hashCode()) % numberOfBuckets无状态、确定性兼容与代价存量命名空间零迁移列举主题的元数据请求数从 1 次变为“桶数”次schema 存储完全不动。对于运维大规模主题集群的读者而言该提案的核心价值在于它把“元数据扇出”从一个全局性的架构问题收敛为一个可按命名空间灰度开启、创建后冻结的局部策略是典型的以最小 API 面换取最大容量收益的设计。赞分享消息队列流处理后端微服务消息路由【免费下载链接】pulsarApache Pulsar - distributed pub-sub messaging system项目地址https://gitcode.com/gh_mirrors/pu/pulsar点击查看免费下载相关推荐Apache Pulsar 主题统计Topic Stats详解从命令行到源码级的指标解读Apache Pulsar 主题统计Topic Stats详解从命令行到源码级的指标解读 Apache Pulsar 提供了丰富的主题级topic le消息队列后端流处理trackerslist 选表指南5 个文件配好 qBittorrent 公共 Trackertrackerslist 选表指南5 个文件配好 qBittorrent 公共 Tracker 先说结论直接取 trackers_best.txt http消息队列流处理后端微服务消息路由Apache Pulsar 命名空间复制职责拆分PIP-321 与 allowed-clusters 机制深度解析Apache Pulsar 命名空间复制职责拆分PIP 321 与 allowed clusters 机制深度解析 PIP 321Split the res消息队列后端上一篇Zoom Classic OAuth Scopes 完整参考指南权限层级、资源类别与授权实践下一篇RisingWave 错误 UI 快照测试指南error_ui 目录的结构、原理与基线维护创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

使用 Remotion 编写场景布局定义(howto-layouts):Stagewise 风格指南体系中的布局规范实战

使用 Remotion 编写场景布局定义(howto-layouts):Stagewise 风格指南体系中的布局规范实战

人工智能AI Agent代码智能体开发工具 【免费下载链接】stagewise The Open Source Agentic IDE. Create and orchestrate coding agents, show app previews and run git workflows. Use your favorite models across all providers. 项目地址: https://gitcode.com…

2026/10/9 7:43:16 阅读更多 →
docker-selenium 4.34.0 版 Chrome 108 镜像标签全解:从 tag_and_push_browser_images.sh 看发布脚本与版本矩阵

docker-selenium 4.34.0 版 Chrome 108 镜像标签全解:从 tag_and_push_browser_images.sh 看发布脚本与版本矩阵

测试后端云原生容器编排可观测性 【免费下载链接】docker-selenium Provides a simple way to run Selenium Grid with Chrome, Firefox, and Edge using Container Platform, making it easier to perform browser automation at scale 项目地址: https://gitcode.…

2026/10/9 7:42:16 阅读更多 →
嵌入式蓝牙开发:AC2005B 芯片技术解析 —— 省晶振设计、13dBm 射频与 Auracast 广播音响开发指南

嵌入式蓝牙开发:AC2005B 芯片技术解析 —— 省晶振设计、13dBm 射频与 Auracast 广播音响开发指南

AC2005B是什么芯片?杰理蓝牙双模Auracast方案解析与开发支持指南本文以硬件工程师第一视角,系统介绍杰理科技2026年8月新发布的AC2005B蓝牙双模芯片。文章覆盖芯片定位、核心技术特点(省晶振设计、13dBm发射功率、Auracast广播音响&#xff0…

2026/10/9 7:42:16 阅读更多 →

最新新闻

物业管理系统源码实战:Access数据库设计与C#连接部署指南

物业管理系统源码实战:Access数据库设计与C#连接部署指南

简介:面向小区物业管理人员与.NET开发者的物业管理系统源码,基于VS2010与Access数据库的C/S架构,覆盖收费管理、住户管理、房间及单价设置、通知单打印,并支持收支与住户信息的Excel批量导入导出。通知单打印采用水晶报表实现&…

2026/10/9 11:19:11 阅读更多 →
Superpowers 完整培训指南:让 AI 编程代理遵循工程纪律的 TaoToken 配置实践

Superpowers 完整培训指南:让 AI 编程代理遵循工程纪律的 TaoToken 配置实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 11:19:11 阅读更多 →
7个可调试Hadoop MapReduce实战项目:从WordCount到PageRank

7个可调试Hadoop MapReduce实战项目:从WordCount到PageRank

简介:本资源是一套基于Hadoop生态的分布式开发实战项目集,面向计算机、人工智能、通信工程等专业的在校学生、教师及初学者,助力掌握MapReduce编程模型与HBase、HDFS核心组件的工程实践能力。包内含7个完整可运行项目:KMeans与KMe…

2026/10/9 11:19:11 阅读更多 →
C++与Java性能深度拆解:原理、实测与选型指南

C++与Java性能深度拆解:原理、实测与选型指南

C和Java的性能到底谁更厉害,这问题我几乎每隔一阵就会被人问一次。说实话,每次看到网上吵得不可开交的“C秒杀Java”“Java也不慢”之类的论战,我都觉得大家其实不在一个频道上。恰好最近热搜上又飘着“c为什么没有普遍”“java面试题”这类词…

2026/10/9 11:19:11 阅读更多 →
品味 + 工程思维:AI 时代最难被替代的两件事,TaoToken 视角下的 Agent 工程实践

品味 + 工程思维:AI 时代最难被替代的两件事,TaoToken 视角下的 Agent 工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 11:19:11 阅读更多 →
树结构核心术语解析:根、父子兄弟、深度高度与路径的工程意义

树结构核心术语解析:根、父子兄弟、深度高度与路径的工程意义

1. 为什么“树”这个词在计算机里被反复提起,却没人真去种一棵?你打开任何一本算法入门书,翻到第三章,大概率会看到一个分叉的图示:一个圆圈在最上面,下面连着两个圆圈,再往下又分出更多——旁边…

2026/10/9 11:18:10 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 10:11:06 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →