Neon Pageserver Storage Shard 扩容分析
Neon pageserver 的扩容通过 Storage Shard 机制实现。这不是传统意义上对单个 pageserver 水平扩展而是两层扩容策略1. Tenant Sharding分片 —将租户数据打散到多个 pageserver 节点上2. Node Scale-out节点伸缩 —增减 pageserver 物理节点两者由 storage controller 统一管理。---一、架构总览架构总览Neon Storage Shard 架构概览用户/控制面neon_local CLI / storcon_cli / REST API↓ HTTP callsStorage Controller (Rust)Scheduler(AZ感知)Reconciler(执行差异)TenantShard(Intent/Observed)DB: PostgreSQL (tenant_shards, nodes 表)↓ gRPC/HTTPPageserver(shard 0)Pageserver(shard 1)Pageserver(shard N)关键角色组件位置职责Storage Controllerstorage_controller/src/service.rs (~10K行)核心编排器管理所有 shard placement、split、migrationPageserverpageserver/数据平面存储实际 data layersTenant Managerpageserver/src/tenant/mgr.rs管理本地 shard 集合DBstorage_controller/migrations/持久化 tenant_shards nodes---二、Shard 概念模型核心类型定义在 libs/utils/src/shard.rs 和 libs/pageserver_api/src/shard.rs┌────────────────────────────────────────────────────────┬────────────────────────────────────────────────────────────┐│ 类型 │ 说明 │├────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤│ TenantShardId {tenant_id, shard_number, shard_count} │ 全局唯一标识 │├────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤│ ShardCount (u8) │ 总分片数0unsharded │├────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤│ ShardNumber (u8) │ 0-based 索引最多 255 │├────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤│ ShardStripeSize │ 默认 4096 页16 MiB决定连续 block 同放一个 shard │├────────────────────────────────────────────────────────┼────────────────────────────────────────────────────────────┤│ ShardIdentity │ {number, count, stripe_size, layout} —包含 key→shard映射 │└────────────────────────────────────────────────────────┴────────────────────────────────────────────────────────────┘Key 到 Shard 的映射用 MurmurHash32与 Postgres smgr 兼容hash murmurhash32(rel_node) murmurhash32(block_num / stripe_size)shard_number hash % shard_count数据分三类- local —只存一个 shard- global —存所有 shard如 rel_size- disposable —split 后可丢弃不属于本 shard 的数据---三、三种扩容操作1. Tenant Shard Split租户分片拆分将租户从一个 shard 拆成多个 shards分布到更多 pageserver 上。API: PUT /control/v1/tenant/:tenant_id/shard_split触发方式:# CLIstorcon_cli tenant-shard-split --tenant-idid --new-shard-countN# APIcurl -X PUT http://controller:PORT/control/v1/tenant/tid/shard_split \-d {new_shard_count: N}执行流程 (service.rs →tenant_shard_split()):1. 标记父 shard 为 Splitting数据库锁2. 创建 child shard 行继承 generation3. 对每个 pageserver 上的 parent shard 调用 PUT /v1/tenant/id/shard_split4. Pageserver 侧执行 (mgr.rs →do_shard_split()):- Phase 1: Prepare —下载 index_part.json上传到各 child remote path- Phase 2: Hardlink —硬链接 resident layer files零拷贝冷分片- Phase 3: Spawn children —创建 child location- Phase 4: WAL catch-up —等 children 追平 WAL- Phase 5: Shutdown parent —关闭 parent shard- Phase 6: Release lock —清理 splitting flag5. 完成 —DB 中删除 parent 行child 行 splitting06. 后台 warmup —child shard 在 secondary mode 下预热限制:- 只能 2 的幂次扩展1→2,2→4,4→8...- stripe_size 只在第一次 split (1→N)时能设之后不可改2. Node Drain/Fill/Delete节点级别伸缩Drain —把所有 shard 从一个 pageserver 迁出curl -X PUT http://controller:PORT/control/v1/node/node_id/drain- 最多并发 64 个 reconcile- 优先用 warm secondary 做 cutover零停机迁移- 用于维护/退役节点Fill —把 shard 迁回到新节点curl -X PUT http://controller:PORT/control/v1/node/node_id/fill反向操作配合 drain 用于滚动升级Delete —物理删除节点curl -X DELETE http://controller:PORT/control/v1/node/node_id/delete先 drain 完再 delete3. Single Shard Migrate单 shard 迁移手动指定某个 shard 迁到特定 pageservercurl -X PUT http://controller:PORT/control/v1/tenant/shard_id/migrate \-d {node_id: target}---四、自动扩缩容HSCC (Hyper Scalable Compute Controller) 利用以下指标驱动 autoscalingsql_exporter_autoscaling 暴露的指标端口 9499从 neon_collector_autoscaling.jsonnet 引入全部跟 LFC 相关┌────────────────────────────────────────────────────────────┬────────────────────────────────────────────┐│ 指标名 │ 说明 │├────────────────────────────────────────────────────────────┼────────────────────────────────────────────┤│ lfc_approximate_working_set_size_seconds{duration_seconds} │ 过去 1~60 分钟每个窗口的工作集大小核心 │├────────────────────────────────────────────────────────────┼────────────────────────────────────────────┤│ lfc_cache_size_limit │ LFC 缓存上限 │├────────────────────────────────────────────────────────────┼────────────────────────────────────────────┤│ lfc_hits / lfc_misses │ 缓存命中/未命中计数 │├────────────────────────────────────────────────────────────┼────────────────────────────────────────────┤│ lfc_used / lfc_writes │ 缓存使用量和写入量 │└────────────────────────────────────────────────────────────┴────────────────────────────────────────────┘其中 lfc_approximate_working_set_size_windows 是最关键的 —看历史 working set 趋势来判断是否需要 split。Auto-Split 机制见 test_runner/performance/test_sharding_autosplit.py —storage controller 监控 tenant size / working set超过阈值时自动触发 split。---五、关键文件清单┌──────────────────────────────────────────────────────┬──────────────────────────────────────────────────┐│ 文件 │ 内容 │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ storage_controller/src/service.rs │ 核心编排split/migrate/drain/fill/reconcile_all │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ storage_controller/src/tenant_shard.rs │ TenantShard 状态机 (Intent/Observed/Policy) │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ storage_controller/src/scheduler.rs │ 节点打分/AZ感知调度 │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ storage_controller/src/reconciler.rs │ 将 intent diff 转化为 pageserver API 调用 │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ storage_controller/src/http.rs │ REST API 端点注册 │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ storage_controller/src/background_node_operations.rs │ Drain/Fill/Delete │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ storage_controller/src/persistence.rs │ DB CRUD (tenant_shards/nodes 表) │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ storage_controller/src/schema.rs │ Diesel table definitions │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ storage_controller/migrations/* │ DB schema evolution │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ libs/utils/src/shard.rs │ ShardCount/ShardNumber/TenantShardId │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ libs/pageserver_api/src/shard.rs │ ShardIdentity/key_to_shard_number │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ pageserver/src/tenant/mgr.rs │ do_shard_split() —pageserver 侧 split 逻辑 │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ pageserver/src/http/routes.rs │ pageserver API endpoint │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ control_plane/storcon_cli/src/main.rs │ CLI 入口 │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ compute/vm-image-spec-bookworm.yaml │ VM 中 sql_exporter 启动配置 │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ docs/rfcs/2025-02-14-storage-controller.md │ Storage Controller RFC │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ docs/rfcs/028-pageserver-migration.md │ Zero-downtime migration procedure │├──────────────────────────────────────────────────────┼──────────────────────────────────────────────────┤│ test_runner/regress/test_sharding.py │ 分片功能测试 │└──────────────────────────────────────────────────────┴──────────────────────────────────────────────────┘---六、验证方案1. 查看当前 shard 分布: curl http://controller:PORT/debug/v1/tenant/tenant_id2. 定位 shard 在哪台 pageserver: curl http://controller:PORT/debug/v1/tenant/tid/locate3. 手动 split: 用 storcon_cli tenant-shard-split 或 HTTP API4. 观察 reconciliation: 看 /debug/v1/tenant/tid/shards 的 intent vs observed5. 跑 test_sharding.py 确认 split 后数据正确性

相关新闻

Kimi K3 vs Fable 5 最新资讯

Kimi K3 vs Fable 5 最新资讯

最近AI圈两大顶级模型持续上演对标大戏,国产开源代表Kimi K3、海外闭源标杆Fable 5,短短几天接连爆出重磅消息,不管是做开发、AI内容创作、本地部署,还是选择API服务,这些动态直接影响选型。今天把两边最新事件一次性梳…

2026/7/23 15:17:14 阅读更多 →
AI如何学习知识?与人类学习的本质差异

AI如何学习知识?与人类学习的本质差异

如今,AI已深度融入生活,能识字作画、解题编程、对话答疑,看似拥有和人类相似的学习能力。但事实上,AI的“学习”与人类的学习只是表象相似,底层逻辑、认知方式、成长逻辑有着天壤之别。AI的学习是算法驱动的数据拟合&a…

2026/7/23 15:16:14 阅读更多 →
MySQL中文乱码全链路解决方案与最佳实践

MySQL中文乱码全链路解决方案与最佳实践

1. 乱码问题的本质与常见场景 当MySQL、phpMyAdmin和PHP三者之间出现中文乱码时,本质上都是字符编码不一致导致的。这种情况在Web开发中极为常见,特别是当系统涉及多语言环境或不同组件混用时。我处理过最典型的一个案例是:phpMyAdmin中显示正…

2026/7/23 15:16:14 阅读更多 →

最新新闻

2026 上海注册公司代账机构甄选指南|金税四期合规避坑 + 本土优质机构实测榜单

2026 上海注册公司代账机构甄选指南|金税四期合规避坑 + 本土优质机构实测榜单

2026 年,上海工商财税监管体系持续升级,金税四期智能风控、全电发票常态化监管、税务信用分级、工商地址动态核查、账务电子化归档等合规要求全面落地。对上海中小微企业、个体工商户、初创电商及科创企业而言,代理记账已经不再是简单的 “记…

2026/7/23 15:29:18 阅读更多 →
相机标定原理与OpenCV实战指南

相机标定原理与OpenCV实战指南

1. 相机标定基础概念解析相机标定是计算机视觉领域的基础性工作,它的核心目标是建立三维世界坐标与二维图像像素坐标之间的数学映射关系。这个过程就像给相机做"体检",通过测量和分析来确定相机的"视力参数"。在工业检测、机器人导航…

2026/7/23 15:29:18 阅读更多 →
Fabrice Bellard:从FFmpeg到QEMU,单人开发者的技术哲学与工程实践

Fabrice Bellard:从FFmpeg到QEMU,单人开发者的技术哲学与工程实践

如果你是一名程序员,却不知道Fabrice Bellard这个名字,那么你可能每天都在使用他的作品而不自知。从你看的在线视频、用的虚拟机到写的C代码,这位法国程序员的影子无处不在。 在技术圈,有些名字如雷贯耳却鲜为人知,Fa…

2026/7/23 15:29:18 阅读更多 →
弱电视频监控系统技术要求与工程实践

弱电视频监控系统技术要求与工程实践

1. 弱电视频监控系统技术要求的核心价值解析 在当今数字化安防领域,一套规范的弱电视频监控系统技术要求文档,往往决定着整个项目的成败。作为参与过数十个大型园区监控项目的老兵,我深刻体会到:招标文件中的技术要求不仅是采购方…

2026/7/23 15:29:18 阅读更多 →
Oracle RAC中crsctl start crs与start cluster命令详解

Oracle RAC中crsctl start crs与start cluster命令详解

1. 问题背景与核心概念澄清在Oracle 11g RAC环境中,CRS(Cluster Ready Services)是集群资源管理的核心组件。很多DBA在使用crsctl命令时会遇到两个看似相似的命令:crsctl start cluster和crsctl start crs。这两个命令虽然都用于启…

2026/7/23 15:29:18 阅读更多 →
Unity Mod Manager深度优化:从源码剖析Info.json加载失败与健壮性改造

Unity Mod Manager深度优化:从源码剖析Info.json加载失败与健壮性改造

1. 项目概述:当Mod加载器“罢工”时 如果你是一名Unity游戏的Mod开发者或资深玩家,那么对Unity Mod Manager(简称UMM)这个工具一定不会陌生。它就像一座桥梁,连接着玩家社区无穷的创意与游戏本体,让《觅长生…

2026/7/23 15:28:18 阅读更多 →

日新闻

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表)

更多请点击: https://intelliparadigm.com 第一章:从单点好评到指数级传播:AI副业主理人必须掌握的4层口碑渗透模型(含ROI测算表) 当AI副业主理人不再仅满足于单次服务交付,而是主动构建可复用、可裂变、可…

2026/7/23 0:00:25 阅读更多 →
AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析

更多请点击: https://codechina.net 第一章:AI写作开头钩子设计:为什么你的AI文案完读率不足18%?——基于2,346篇A/B测试报告的归因分析 在对2,346篇跨行业AI生成文案的A/B测试数据进行聚类分析后,我们发现&#xff1…

2026/7/23 0:01:26 阅读更多 →
Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具

Chitchatter完整指南:免费开源的终极点对点安全聊天工具 【免费下载链接】chitchatter Secure peer-to-peer chat that is serverless, decentralized, and ephemeral 项目地址: https://gitcode.com/gh_mirrors/ch/chitchatter Chitchatter是一款革命性的安…

2026/7/23 0:01:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/22 8:58:19 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/22 19:43:43 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/22 12:54:44 阅读更多 →

月新闻