Neon PostgreSQL修改:核心数据库引擎的定制化扩展
引言:Serverless PostgreSQL的革命性架构
你是否曾面临这样的困境?传统PostgreSQL数据库在云原生环境中难以实现真正的弹性伸缩,存储与计算耦合导致资源浪费严重,分支创建和快照管理复杂且耗时。Neon通过分离存储与计算架构,为PostgreSQL带来了革命性的Serverless体验,但这背后需要对PostgreSQL核心进行深度定制和扩展。
本文将深入解析Neon对PostgreSQL核心引擎的关键修改,揭示如何通过精巧的架构设计实现无服务器化PostgreSQL,同时保持与原生PostgreSQL的完全兼容性。
架构概览:存储与计算的彻底分离
Neon的架构核心在于将PostgreSQL的传统单体架构解耦为三个关键组件:
这种架构要求对PostgreSQL核心进行以下关键修改:
1. 存储管理器(SMGR)接口扩展
Neon通过扩展PostgreSQL的存储管理器接口,实现了远程页面存储的能力:
// PostgreSQL原生smgr接口
typedef struct f_smgr
{
void (*smgr_read) (SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, char *buffer);
void (*smgr_write) (SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, char *buffer, bool skipFsync);
// ... 其他方法
} f_smgr;
// Neon扩展的smgr接口
typedef struct f_smgr
{
void (*smgr_read) (SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, char *buffer);
void (*smgr_write) (SMgrRelation reln, ForkNumber forknum,
BlockNumber blocknum, char *buffer, bool skipFsync);
// Neon新增方法
void (*smgr_start_unlogged_build) (SMgrRelation reln);
void (*smgr_finish_unlogged_build_phase_1) (SMgrRelation reln);
void (*smgr_end_unlogged_build) (SMgrRelation reln);
} f_smgr;
2. WAL记录格式增强
为了在分布式环境中保持数据一致性,Neon扩展了PostgreSQL的WAL记录格式:
| WAL记录类型 | PostgreSQL原生 | Neon扩展 | 扩展目的 |
|---|---|---|---|
| XLOG_HEAP_INSERT | 不包含t_cid | 包含t_cid | 支持页面逐出后的正确重放 |
| XLOG_HEAP_DELETE | 不包含t_cid | 包含t_cid | 确保删除操作的命令ID一致性 |
| XLOG_HEAP_UPDATE | 不包含t_cid | 包含t_cid | 维护更新操作的完整上下文 |
核心修改详解
1. 预取优化:应对高延迟存储
在传统PostgreSQL中,操作系统级的readahead(预读)能够有效提升顺序扫描性能。但在Neon架构中,页面服务器(Pageserver)的网络延迟远高于本地磁盘,因此需要在数据库引擎层面实现智能预取:
// Neon在多个关键路径添加预取逻辑
void neon_prefetch_range(SMgrRelation reln, ForkNumber forknum,
BlockNumber startblk, BlockNumber nblocks)
{
// 批量预取页面,减少网络往返次数
for (BlockNumber blk = startblk; blk < startblk + nblocks; blk += PREFETCH_STRIDE) {
RequestPageFromPageserver(reln, forknum, blk, PREFETCH_FLAG);
}
}
2. 无日志索引构建的特殊处理
PostgreSQL在构建GIN等索引时采用"无日志构建"模式,先构建索引再整体WAL日志化。这在Neon中会导致页面丢失问题:
3. 最后写入页面LSN跟踪
Neon引入了页面级别的LSN(Log Sequence Number)跟踪机制,确保页面逐出后能够正确地从页面服务器恢复:
-- Neon扩展的系统视图显示页面LSN信息
SELECT * FROM neon_page_lsn_info WHERE relid = 'mytable'::regclass;
relid | forknum | blocknum | last_written_lsn
-------+---------+----------+------------------
16384 | 0 | 0 | 0/16B5A50
16384 | 0 | 1 | 0/16B5A58
16384 | 0 | 2 | 0/16B5A60
4. 启动流程优化
传统PostgreSQL启动时需要读取检查点记录和WAL日志,而Neon计算节点是无状态的:
扩展机制:PGXN扩展体系
Neon的大部分功能通过PostgreSQL扩展实现,最大限度地减少对核心代码的修改:
1. Neon主扩展(neon)
-- 加载Neon扩展
CREATE EXTENSION IF NOT EXISTS neon;
-- 查看Neon特定信息
SELECT * FROM neon_get_metadata();
SELECT * FROM neon_get_perf_counters();
2. WAL重做处理器(neon_walredo)
专门用于在Pageserver中安全地执行WAL重做操作,通过Linux Secure Computing模式进行沙箱化:
// WAL重做进程的安全沙箱配置
void setup_walredo_seccomp(void)
{
scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW);
// 限制系统调用,防止恶意WAL记录造成危害
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(execve), 0);
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(fork), 0);
// ... 其他限制
seccomp_load(ctx);
}
3. 资源管理器扩展(neon_rmgr)
处理Neon特定的WAL记录类型和资源管理操作。
性能优化策略
1. 序列缓存禁用
PostgreSQL默认缓存32个序列值以减少WAL日志量,但在Neon中这会导致序列值间隙:
-- Neon中序列操作完全WAL日志化
#define SEQ_LOG_VALS 0 -- 替代原生的32
2. 缓冲区管理策略调整
禁用环形缓冲区策略,避免大容量操作时的不必要页面逐出:
| 策略 | PostgreSQL原生 | Neon调整 | 调整原因 |
|---|---|---|---|
| 环形缓冲区 | 启用 | 禁用 | 避免网络密集型环境中的性能下降 |
| 提示位脏页标记 | 启用 | 优化 | 减少FPI(完整页面镜像)的WAL日志量 |
3. 按需下载机制
实现SLRU文件和扩展的按需下载,减少启动时的数据传输量:
// SLRU文件按需下载回调
static bool slru_read_on_demand(SLRUFileType filetype, int segment)
{
if (!slru_file_exists_locally(filetype, segment)) {
return download_slru_file_from_pageserver(filetype, segment);
}
return true;
}
兼容性与演进策略
Neon团队采用双轨策略来管理PostgreSQL修改:
1. 上游贡献策略
积极将通用性改进提交到PostgreSQL社区,包括:
- 存储管理器API扩展
- 预取优化接口
- 进程中断回调钩子
2. 扩展优先原则
尽可能通过扩展而非核心修改实现功能:
- Neon特定功能在neon扩展中实现
- 保持核心修改的最小化和可维护性
- 为最终回归未修改PostgreSQL做准备
实际应用场景
1. 数据库分支创建
# 创建基于当前状态的新分支
cargo neon timeline branch --branch-name migration_check
# 在新分支上启动计算节点
cargo neon endpoint create migration_check --branch-name migration_check
cargo neon endpoint start migration_check
2. 弹性伸缩实践
Neon的架构天然支持计算节点的快速启动和停止:
-- 计算节点可随时启动停止,数据持久化在Pageserver中
-- 启动时间从分钟级降低到秒级
SELECT neon_get_startup_time(); -- 返回: 2.3秒
总结与展望
Neon对PostgreSQL的核心修改体现了现代数据库系统设计的几个关键趋势:
- 存储计算分离:通过精巧的架构设计实现真正的弹性伸缩
- 扩展优先:最大限度减少核心修改,提高可维护性
- 云原生优化:针对网络环境优化传统数据库行为
- 安全隔离:关键操作在沙箱环境中执行
随着PostgreSQL社区的不断发展,Neon的许多核心修改正逐步向上游贡献,最终目标是实现使用未修改PostgreSQL与Neon存储引擎的无缝协作。这种演进策略不仅保证了Neon的技术先进性,也确保了与PostgreSQL生态系统的长期兼容性。
通过深度定制和扩展PostgreSQL核心,Neon为云原生时代的数据库管理提供了全新的范式,证明了传统关系型数据库在现代架构中的持续价值和创新潜力。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



