Neon Serverless Postgres 的扩展体系:深入解析 pgxn/neon 中的 neon extension
2026/9/13 5:13:27 网站建设 项目流程

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 library(neon.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 可知,该扩展由两大块组成:

  1. shared preload libraryneon.so:在shared_preload_libraries中随 postmaster 一起加载,通过钩子(hook)与自定义存储管理器(smgr)接管 PostgreSQL 的存储、复制与权限变更等关键路径;
  2. SQL 函数(neon--*.sql:以CREATE EXTENSION neon暴露给用户的监控与运维工具函数,默认在集群中的所有数据库中创建

neon.control(pgxn/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.ofile_cache.o依赖 cargo 生成的communicator_bindings.h),这体现了 Neon 扩展“C 内核 + Rust 网络栈”的混合架构。

二、shared preload libraryneon.so的六大核心子系统

README 明确了neon.so承担六项核心职责,下面结合源码逐一展开。

2.1 存储管理器与 Page Server 通信(pagestore)

implements storage manager API and network communications with remote page server

PostgreSQL 通过自定义存储管理器(Storage Manager)抽象访问堆、索引等关系文件。Neon 用 pgxn/neon/pagestore_smgr.c 实现了一套“远端存储”的 smgr:当计算节点需要某个数据页时,它不再从本地磁盘读取,而是向远程 Page Server 发起请求拉取该页。底层网络通信由 pgxn/neon/libpagestore.c 与 Rust 实现的communicator(pgxn/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 广播协议 walproposer

walproposer: implements broadcast protocol between postgres and WAL safekeepers

在 Neon 中,事务提交前 WAL 必须先被多数派 Safekeeper 确认。walproposer(pgxn/neon/walproposer.c、pgxn/neon/walproposer_pg.c)在 PostgreSQL 的 WAL 写入路径上实现了“Proposer-Acceptor”广播协议:postgres 作为 proposer 将每一条 WAL 记录同时推送给多个 Safekeeper(acceptor),收到多数派确认后才向客户端返回提交成功。该协议与 safekeeper 侧的 TLA+ 规范模型(safekeeper/spec)一一对应,保证任意故障场景下 WAL 不丢失、不重复、不乱序。相关重连/连接超时由wal_acceptor_reconnect_timeoutwal_acceptor_connection_timeout等 GUC 控制(见 pgxn/neon/neon.h)。

2.3 控制面连接器(control plane connector)

Captures updates to roles/databases using ProcessUtility_hook and sends them to the control plane

Serverless 场景下,用户执行的CREATE ROLECREATE 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 server)

Request compute_ctl to download extension files

Serverless 场景下,计算节点镜像中不会预装全部扩展(如 pgvector、PostGIS 等),而是在用户首次使用时按需下载。extension_server(pgxn/neon/extension_server.c)作为计算节点内部的一个服务器进程,向 compute_tools 中的compute_ctl发出请求,让其从对象存储或扩展目录下载对应的.so与 SQL 文件,再安装进运行中的实例。这保证了“开箱即用”的扩展体验,同时避免镜像体积膨胀。

2.5 本地文件缓存 file_cache(LFC)

Local file cache is used to temporarily store relation pages in local file system for better performance

尽管数据页来自远端 Page Server,Neon 仍会在计算节点本地保留一份按页组织的缓存,即Local File Cache(LFC)。其实现位于 pgxn/neon/file_cache.c,以文件形式将最近访问的关系页暂存于本地磁盘(目录由neon.pg_file_cache_path等配置指定)。LFC 与 PostgreSQL 的共享缓冲池协同工作:热页命中本地磁盘即可返回,只有缺失页(file_cache_misses)才需要走网络向 Page Server 拉取,从而显著降低延迟与远端 IO。关于 LFC 命中/缺失的量化观测,见下文 SQL 函数与视图部分。

2.6 关系大小缓存 relsize_cache

Relation size cache for better neon performance

计算节点经常需要查询表/索引的大小(如规划器估算、pg_relation_size调用)。在存储分离架构下,每次都向 Page Server 请求会引入额外往返。relsize_cache(pgxn/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_subscribers
WAL 发送端钩子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 如何处理这一过程:

  1. Stage 1(早期初始化):注册扩展 GUC、初始化各子系统(pg_init_libpagestorelfc_initpg_init_walproposerinit_lwlsncachepg_init_communicator_processpg_init_communicatorInitDDLHandlerpg_init_extension_server等),并注册shmem_request_hookshmem_startup_hook
  2. Stage 2(共享内存请求)neon_shmem_request_hook()(pgxn/neon/neon.c#L822-L836)依次为 LFC、性能计数器、pagestore、relsize_cache、walproposer、LSN 缓存申请共享内存与 LWLock tranche;在 PG14 上,该阶段被合并进 Stage 1 提前执行;
  3. Stage 3(共享内存初始化)neon_shmem_startup_hook()(pgxn/neon/neon.c#L844-L876)在AddinShmemInitLock保护下完成各共享结构初始化,并在 PG17 上为 LFC 读写、Page Server 读写、WAL 下载等操作注册扩展等待事件(如Neon/FileCache_ReadNeon/PS_ReadIO),这些事件会出现在pg_stat_activitywait_event列中,便于定位 IO 瓶颈。

此外,_PG_init()还会自动加载$libdir/neon_rmgr(PG16+,见 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 恢复运行中事务快照溢出时的策略:ignoreskipwait
neon.pgstat_file_size_limitint (KB) / 0SIGHUPpgstat.stat持久化上限,0 表示禁用
neon.debug_compare_localenum / nonePOSTMASTER调试模式,对比 prefetch ring/LFC/Page Server 与本地磁盘页面内容,取值noneprefetchlfcall
neon.privileged_role_namestring /neon_superuserPOSTMASTER“弱超级用户”角色名,Neon 授予用户的最低权限角色
neon.lakebase_modebool / offPOSTMASTER是否以 Lakebase 模式运行(Databricks 数据湖场景)

其中neon.privileged_role_nameProcessUtility_hook联动:控制面连接器在捕获到角色/数据库变更时,会以该角色名执行或校验,从而保证普通用户也能安全地完成 Serverless 场景下的自助 DDL。

五、SQL 函数与监控视图:neon--*.sql的版本演进

README 指出,neon--*.sql提供“向用户与指标采集暴露 Neon 特有信息”的工具函数,且扩展默认装进所有数据库。仓库中的 SQL 升级链完整保留了这些函数的演进过程(pgxn/neon 下的neon--1.0.sqlneon--1.5--1.6.sql)。

5.1 基础函数(neon--1.0.sql)

pgxn/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_lsn(Safekeeper 已接收)、disk_consistent_lsn(已落盘一致点)、remote_consistent_lsn(Page Server 侧一致点),用于判断写路径是否被背压;
  • backpressure_throttling_time():返回当前因背压而节流的微秒数;
  • local_cache_pages()/local_cache视图:枚举 LFC 中缓存的每个页(文件偏移、relfilenode、tablespace、database、fork、block、访问计数),是排查缓存命中率与驱逐行为的直接工具。

5.2 LFC 统计(1.0 → 1.2)

  • neon--1.0--1.1.sql(pgxn/neon/neon--1.0--1.1.sql)新增neon_get_lfc_stats()neon_lfc_stats视图,输出(lfc_key, lfc_value)键值对;
  • neon--1.1--1.2.sql(pgxn/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 / (hits+misses)),并对pg_monitor角色授权查询。这是衡量 Neon 计算节点本地缓存效果的核心指标。

5.3 近似工作集大小(1.2 → 1.4)

  • neon--1.2--1.3.sql(pgxn/neon/neon--1.2--1.3.sql)新增approximate_working_set_size(reset bool),估算当前工作集大小(页面数),可选地重置统计窗口;
  • neon--1.3--1.4.sql(pgxn/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.5)

pgxn/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 的启用方式为:

  1. 预加载共享库:在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'
  2. 创建扩展:在所有目标数据库中执行
    CREATE EXTENSION neon;

    该扩展trusted且默认装进所有数据库;已安装的实例可通过

    ALTER EXTENSION neon UPDATE TO '1.6';

    沿 pgxn/neon 下的升级脚本完成版本迁移。

  3. 观测与验证
    -- 查看本地文件缓存命中率 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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询