资讯动态

Neon Serverless Postgres 的扩展体系:深入解析 pgxn/neon 中的 neon extension

发布时间:2026/9/13 5:13:33 来源:尧图企业网站定制
Neon Serverless Postgres 的扩展体系深入解析 pgxn/neon 中的 neon extension【免费下载链接】neonNeon: Serverless Postgres. We separated storage and compute to offer autoscaling, code-like database branching, and scale to zero.项目地址: https://gitcode.com/GitHub_Trending/ne/neon导读neon extension 是 Neon 将 PostgreSQL 改造成 Serverless 数据库的“内核适配层”它以 shared preload libraryneon.so加 SQL 函数的形式把存储与计算分离、WAL 广播、本地缓存、控制面联动等核心能力注入到每个 PostgreSQL 实例中。阅读本文你将理解neon.so六大子系统的职责分工、_PG_init()的三阶段初始化与关键 GUC 参数并掌握neon--*.sql中全部监控与运维 SQL 函数的用法能够在自己的 Neon 计算节点上对本地文件缓存、backpressure、预热等机制进行观测与调优。一、neon extension 是什么Neon 的核心设计是“存储与计算分离”计算节点Compute Node只负责执行 SQL而数据页与 WAL 分别托管给远程的 Page Server 与 WAL Safekeeper。要让一个未经修改的 PostgreSQL 内核无缝融入这种架构Neon 选择以PostgreSQL 扩展extension的形式提供一个内核补丁层这就是 pgxn/neon 目录下的neonextension。从 pgxn/neon/README.md 可知该扩展由两大块组成shared preload libraryneon.so在shared_preload_libraries中随 postmaster 一起加载通过钩子hook与自定义存储管理器smgr接管 PostgreSQL 的存储、复制与权限变更等关键路径SQL 函数neon--*.sql以CREATE EXTENSION neon暴露给用户的监控与运维工具函数默认在集群中的所有数据库中创建。neon.controlpgxn/neon/neon.control给出了它的基本元信息# neon extension comment cloud storage for PostgreSQL default_version 1.6 module_pathname $libdir/neon relocatable true trusted true其中default_version 1.6表示当前仓库中的最新扩展版本trusted true意味着具有CREATE权限的用户即可安装无需超级用户relocatable true表示该扩展可以移动到任意 schema。而 pgxn/neon/Makefile 则揭示了neon.so的全部组成单元它把下列对象链接进同一个模块MODULE_big neon OBJS communicator.o communicator_process.o extension_server.o file_cache.o hll.o libpagestore.o logical_replication_monitor.o neon.o neon_lwlsncache.o neon_pgversioncompat.o neon_perf_counters.o neon_utils.o neon_walreader.o pagestore_smgr.o relsize_cache.o unstable_extensions.o walproposer.o walproposer_pg.o neon_ddl_handler.o walsender_hooks.o .../libcommunicator.a注意其中的libcommunicator.a是由 pgxn/neon/communicator 子目录下的Rust 源码通过cargo build构建后链接进来的Makefile 中communicator_process.o与file_cache.o依赖 cargo 生成的communicator_bindings.h这体现了 Neon 扩展“C 内核 Rust 网络栈”的混合架构。二、shared preload libraryneon.so的六大核心子系统README 明确了neon.so承担六项核心职责下面结合源码逐一展开。2.1 存储管理器与 Page Server 通信pagestoreimplements storage manager API and network communications with remote page serverPostgreSQL 通过自定义存储管理器Storage Manager抽象访问堆、索引等关系文件。Neon 用 pgxn/neon/pagestore_smgr.c 实现了一套“远端存储”的 smgr当计算节点需要某个数据页时它不再从本地磁盘读取而是向远程 Page Server 发起请求拉取该页。底层网络通信由 pgxn/neon/libpagestore.c 与 Rust 实现的communicatorpgxn/neon/communicator共同完成并通过Custom_XLogReaderRoutines NeonOnDemandXLogReaderRoutines见 pgxn/neon/neon.c让 WAL 重放也能按需从远端读取日志记录。一个典型的场景当计算节点冷启动时PostgreSQL 需要读取控制文件与数据页而这些内容可能从未落在本地磁盘上。正是这套 smgr 与按需 WAL 读取机制让 Neon 的“从任意 LSN 快速启动只读副本”成为可能——RestoreRunningXactsFromClog()pgxn/neon/neon.c会在启动时直接扫描 CLOG 重建运行中事务快照而不必等待主库下发 running-xacts 记录从而避免副本永远无法开始接受查询的“limbo”状态。2.2 WAL 广播协议 walproposerwalproposer: implements broadcast protocol between postgres and WAL safekeepers在 Neon 中事务提交前 WAL 必须先被多数派 Safekeeper 确认。walproposerpgxn/neon/walproposer.c、pgxn/neon/walproposer_pg.c在 PostgreSQL 的 WAL 写入路径上实现了“Proposer-Acceptor”广播协议postgres 作为 proposer 将每一条 WAL 记录同时推送给多个 Safekeeperacceptor收到多数派确认后才向客户端返回提交成功。该协议与 safekeeper 侧的 TLA 规范模型safekeeper/spec一一对应保证任意故障场景下 WAL 不丢失、不重复、不乱序。相关重连/连接超时由wal_acceptor_reconnect_timeout、wal_acceptor_connection_timeout等 GUC 控制见 pgxn/neon/neon.h。2.3 控制面连接器control plane connectorCaptures updates to roles/databases using ProcessUtility_hook and sends them to the control planeServerless 场景下用户执行的CREATE ROLE、CREATE DATABASE等 DDL 需要同步到控制面Control Plane用于路由、鉴权与计费。neon.so通过注册ProcessUtility_hook在 pgxn/neon/neon_ddl_handler.c 与 pgxn/neon/unstable_extensions.c 中实现捕获所有 DDL 语句提取其中的角色、数据库变更事件并上报。此外pgxn/neon/neon.c 中的ReportSearchPath()还为search_path参数设置了GUC_REPORT标志使 pgbouncer 能通过track_extra_parameters跟踪它——这一技巧借鉴自 Citus 扩展的同类实现。2.4 远程扩展服务器remote extension serverRequest compute_ctl to download extension filesServerless 场景下计算节点镜像中不会预装全部扩展如 pgvector、PostGIS 等而是在用户首次使用时按需下载。extension_serverpgxn/neon/extension_server.c作为计算节点内部的一个服务器进程向 compute_tools 中的compute_ctl发出请求让其从对象存储或扩展目录下载对应的.so与 SQL 文件再安装进运行中的实例。这保证了“开箱即用”的扩展体验同时避免镜像体积膨胀。2.5 本地文件缓存 file_cacheLFCLocal file cache is used to temporarily store relation pages in local file system for better performance尽管数据页来自远端 Page ServerNeon 仍会在计算节点本地保留一份按页组织的缓存即Local File CacheLFC。其实现位于 pgxn/neon/file_cache.c以文件形式将最近访问的关系页暂存于本地磁盘目录由neon.pg_file_cache_path等配置指定。LFC 与 PostgreSQL 的共享缓冲池协同工作热页命中本地磁盘即可返回只有缺失页file_cache_misses才需要走网络向 Page Server 拉取从而显著降低延迟与远端 IO。关于 LFC 命中/缺失的量化观测见下文 SQL 函数与视图部分。2.6 关系大小缓存 relsize_cacheRelation size cache for better neon performance计算节点经常需要查询表/索引的大小如规划器估算、pg_relation_size调用。在存储分离架构下每次都向 Page Server 请求会引入额外往返。relsize_cachepgxn/neon/relsize_cache.c在共享内存中缓存每个关系的页数与大小配合写路径上的失效机制保持一致性显著减少了此类元数据查询的开销。同时pgxn/neon/neon.c 暴露的pg_cluster_size()函数返回整个集群当前的大小快照其值正是由SetNeonCurrentClusterSize()/GetNeonCurrentClusterSize()维护见 pgxn/neon/neon.h。2.7 其他内建子系统源码佐证从 pgxn/neon/Makefile 的 OBJS 列表和 pgxn/neon/neon.c 的初始化调用可以确认neon.so还包含以下模块模块源文件职责LSN 缓存neon_lwlsncache.c共享内存中缓存已提交 LSN加速可见性判断性能计数器neon_perf_counters.c采集后端级指标含直方图供get_perf_counters()系列函数读取逻辑复制监控logical_replication_monitor.c监控逻辑复制槽/订阅者状态支持neon.disable_logical_replication_subscribersWAL 发送端钩子walsender_hooks.c在 walsender 路径上注入 Neon 需要的逻辑如计算节点间 WAL 消费按需 WAL 读取neon_walreader.c提供NeonOnDemandXLogReaderRoutines的按需读取实现HLLhll.c近似工作集估算所用的 HyperLogLog 计数版本兼容层neon_pgversioncompat.c屏蔽 PG14–PG17 之间的 API 差异三、_PG_init()的三阶段初始化与共享内存布局PostgreSQL 的 preload 扩展在 postmaster 启动时依次经历三个阶段pgxn/neon/neon.c 中的_PG_init()完整展示了 neon 如何处理这一过程Stage 1早期初始化注册扩展 GUC、初始化各子系统pg_init_libpagestore、lfc_init、pg_init_walproposer、init_lwlsncache、pg_init_communicator_process、pg_init_communicator、InitDDLHandler、pg_init_extension_server等并注册shmem_request_hook与shmem_startup_hookStage 2共享内存请求neon_shmem_request_hook()pgxn/neon/neon.c#L822-L836依次为 LFC、性能计数器、pagestore、relsize_cache、walproposer、LSN 缓存申请共享内存与 LWLock tranche在 PG14 上该阶段被合并进 Stage 1 提前执行Stage 3共享内存初始化neon_shmem_startup_hook()pgxn/neon/neon.c#L844-L876在AddinShmemInitLock保护下完成各共享结构初始化并在 PG17 上为 LFC 读写、Page Server 读写、WAL 下载等操作注册扩展等待事件如Neon/FileCache_Read、Neon/PS_ReadIO这些事件会出现在pg_stat_activity的wait_event列中便于定位 IO 瓶颈。此外_PG_init()还会自动加载$libdir/neon_rmgrPG16见 pgxn/neon/neon.c#L472-L474因此shared_preload_libraries中只需列出neon一个名字无需同时列出neon_rmgr该 RMGR 扩展单独位于 pgxn/neon_rmgr。四、neon 扩展的 GUC 参数从源码确认以下 GUC 均在 pgxn/neon/neon.c 中通过DefineCustomBoolVariable/DefineCustomEnumVariable/DefineCustomIntVariable/DefineCustomStringVariable注册可在postgresql.conf中配置参数类型/默认值作用域说明neon.disable_logical_replication_subscribersbool / offSIGHUP关闭入站逻辑复制订阅端neon.disable_wal_prevlink_checksbool / offSIGHUP关闭 WAL 记录中 prev-link 的校验neon.monitor_query_exec_timebool / offUSERSET启用后通过 ExecutorStart/ExecutorEnd 钩子统计查询执行耗时neon.allow_replica_misconfigbool / onPOSTMASTER允许副本在关键 GUC 小于主库时启动neon.running_xacts_overflow_policyenum / ignorePOSTMASTERCLOG 恢复运行中事务快照溢出时的策略ignore、skip、waitneon.pgstat_file_size_limitint (KB) / 0SIGHUPpgstat.stat持久化上限0 表示禁用neon.debug_compare_localenum / nonePOSTMASTER调试模式对比 prefetch ring/LFC/Page Server 与本地磁盘页面内容取值none、prefetch、lfc、allneon.privileged_role_namestring /neon_superuserPOSTMASTER“弱超级用户”角色名Neon 授予用户的最低权限角色neon.lakebase_modebool / offPOSTMASTER是否以 Lakebase 模式运行Databricks 数据湖场景其中neon.privileged_role_name与ProcessUtility_hook联动控制面连接器在捕获到角色/数据库变更时会以该角色名执行或校验从而保证普通用户也能安全地完成 Serverless 场景下的自助 DDL。五、SQL 函数与监控视图neon--*.sql的版本演进README 指出neon--*.sql提供“向用户与指标采集暴露 Neon 特有信息”的工具函数且扩展默认装进所有数据库。仓库中的 SQL 升级链完整保留了这些函数的演进过程pgxn/neon 下的neon--1.0.sql至neon--1.5--1.6.sql。5.1 基础函数neon--1.0.sqlpgxn/neon/neon--1.0.sql 定义了四个基础函数与一个视图CREATE FUNCTION pg_cluster_size() RETURNS bigint ... CREATE FUNCTION backpressure_lsns( OUT received_lsn pg_lsn, OUT disk_consistent_lsn pg_lsn, OUT remote_consistent_lsn pg_lsn) RETURNS record ... CREATE FUNCTION backpressure_throttling_time() RETURNS bigint ... CREATE FUNCTION local_cache_pages() RETURNS SETOF RECORD ... CREATE VIEW local_cache AS SELECT P.* FROM local_cache_pages() AS P (pageoffs int8, relfilenode oid, reltablespace oid, reldatabase oid, relforknumber int2, relblocknumber int8, accesscount int4);pg_cluster_size()返回整个集群的估算大小字节对应 pgxn/neon/neon.c 中GetNeonCurrentClusterSize()的实现backpressure_lsns()返回三个 LSN——received_lsnSafekeeper 已接收、disk_consistent_lsn已落盘一致点、remote_consistent_lsnPage Server 侧一致点用于判断写路径是否被背压backpressure_throttling_time()返回当前因背压而节流的微秒数local_cache_pages()/local_cache视图枚举 LFC 中缓存的每个页文件偏移、relfilenode、tablespace、database、fork、block、访问计数是排查缓存命中率与驱逐行为的直接工具。5.2 LFC 统计1.0 → 1.2neon--1.0--1.1.sqlpgxn/neon/neon--1.0--1.1.sql新增neon_get_lfc_stats()与neon_lfc_stats视图输出(lfc_key, lfc_value)键值对neon--1.1--1.2.sqlpgxn/neon/neon--1.1--1.2.sql进一步把键值对透视成单行视图NEON_STAT_FILE_CACHE直接给出file_cache_misses, file_cache_hits, file_cache_used, file_cache_writes, file_cache_hit_ratio其中file_cache_hit_ratio在视图内用 SQL 实时计算hits / (hitsmisses)并对pg_monitor角色授权查询。这是衡量 Neon 计算节点本地缓存效果的核心指标。5.3 近似工作集大小1.2 → 1.4neon--1.2--1.3.sqlpgxn/neon/neon--1.2--1.3.sql新增approximate_working_set_size(reset bool)估算当前工作集大小页面数可选地重置统计窗口neon--1.3--1.4.sqlpgxn/neon/neon--1.3--1.4.sql新增approximate_working_set_size_seconds(duration int default null)估算最近duration秒内的工作集。两者的底层实现均为 pgxn/neon/neon.c 中的lfc_approximate_working_set_size_seconds()基于 LFC 页访问记录与 hll.c 的 HyperLogLog 去重计数。这两个函数被用于 Neon 的自动扩缩容autoscaling决策工作集大小直接决定实例所需的内存/磁盘规格。5.4 性能计数器1.4 → 1.5pgxn/neon/neon--1.4--1.5.sql 引入按后端与全局两个粒度的指标CREATE VIEW neon_backend_perf_counters AS SELECT P.procno, P.pid, P.metric, P.bucket_le, P.value FROM get_backend_perf_counters() AS P (...); CREATE VIEW neon_perf_counters AS SELECT P.metric, P.bucket_le, P.value FROM get_perf_counters() AS P (...);注意 SQL 注释中的说明计数器不随后端退出而重置新后端复用 backend ID 时会继续累加因此若只关心本会话增量应在会话开始处保存快照再相减bucket_le为直方图上界方便绘制分位分布。这两张视图是观测 Neon 计算节点内部 IO 与协议耗时的主要入口。5.5 预取预热1.5 → 1.6当前最新版本1.6见 pgxn/neon/neon--1.5--1.6.sql增加了计算节点预取prewarm三件套CREATE FUNCTION get_prewarm_info( OUT total_pages integer, OUT prewarmed_pages integer, OUT skipped_pages integer, OUT active_workers integer) ... CREATE FUNCTION get_local_cache_state(max_chunks integer default null) RETURNS bytea ... CREATE FUNCTION prewarm_local_cache(state bytea, n_workers integer default 1) RETURNS void ...这组函数对应 docs/rfcs/2025-03-17-compute-prewarm.md 描述的“计算节点预热”机制把本地缓存状态序列化为bytea在新实例如扩缩容、分支切换后启动时并行预取热点页从而把冷启动延迟降到最低。配合 compute_tools/src/compute_prewarm.rs 的调度逻辑可实现跨实例的缓存“迁移”。六、安装与使用方式结合仓库中的部署配置如 compute/etc/pgbouncer.ini、compute/jsonnet/neon.libsonnet 中shared_preload_libraries的组装逻辑neon extension 的启用方式为预加载共享库在postgresql.conf中设置shared_preload_libraries neon由于_PG_init()会自动加载neon_rmgr无需重复列出。GUC 配置示例neon.pg_file_cache_path /var/db/neon/file_cache # 示例路径按实际部署调整 neon.monitor_query_exec_time on neon.privileged_role_name neon_superuser创建扩展在所有目标数据库中执行CREATE EXTENSION neon;该扩展trusted且默认装进所有数据库已安装的实例可通过ALTER EXTENSION neon UPDATE TO 1.6;沿 pgxn/neon 下的升级脚本完成版本迁移。观测与验证-- 查看本地文件缓存命中率 SELECT * FROM NEON_STAT_FILE_CACHE; -- 查看工作集大小页面数 SELECT approximate_working_set_size(false); -- 查看 backpressure LSN 水位 SELECT * FROM backpressure_lsns(); -- 查看各后端性能计数器 SELECT * FROM neon_perf_counters;需要说明的是以上均针对 Neon 的计算节点Compute Node而言Neon 控制面侧的 Page Server、Safekeeper、Storage Broker 等组件不加载本扩展它们与计算节点通过 libs/pq_proto 与 pgxn/neon/communicator 中定义的协议通信。七、总结neon extension是 Neon Serverless Postgres 中连接“标准 PostgreSQL 内核”与“分离式存储架构”的桥梁neon.so通过自定义 smgr、WAL 广播、DDL 钩子、按需扩展下载、本地文件缓存与大小缓存六个子系统把远端 Page Server 与 Safekeeper 无缝“伪装”成本地存储与复制_PG_init()的三阶段初始化与十余个 GUC 参数为部署与调优提供了细粒度控制neon--*.sql中从 1.0 到 1.6 逐步积累的 SQL 函数与视图为缓存命中率、工作集估算、backpressure、后端性能计数器与预热等关键运维场景提供了开箱即用的观测手段。无论是想理解 Neon 的内部原理还是在自建 Neon 计算节点上排查性能问题本文所述的文件路径与 SQL 函数都是直接可用的入口。延伸阅读仓库内扩展核心实现pgxn/neon/neon.c、pgxn/neon/neon.h构建与版本链pgxn/neon/Makefile、pgxn/neon/neon.control计算节点预热设计docs/rfcs/2025-03-17-compute-prewarm.md、compute_tools/src/compute_prewarm.rs相关组件源码pgxn/neon_rmgr、pgxn/neon/communicator部署配置示例compute/etc/pgbouncer.ini、compute/jsonnet/neon.libsonnet【免费下载链接】neonNeon: Serverless Postgres. We separated storage and compute to offer autoscaling, code-like database branching, and scale to zero.项目地址: https://gitcode.com/GitHub_Trending/ne/neon创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价