Neon核心技术解析:Pageserver如何重构PostgreSQL存储引擎
存储引擎的革命性突破
传统PostgreSQL采用共享存储架构,计算节点与存储紧密耦合,导致资源利用率低、扩展困难。Neon通过Pageserver实现计算与存储分离,彻底重构了PostgreSQL的存储引擎。这一创新架构使Neon能够提供自动扩缩容、分支功能和无限存储等Serverless特性,解决了传统数据库在云环境下的诸多痛点。
Pageserver作为Neon存储引擎的核心组件,负责处理来自计算节点的GetPage@LSN请求、接收WAL(Write-Ahead Logging,预写日志)并存储数据,同时与云存储交互实现数据持久化。通过将PostgreSQL的存储层抽象为可独立扩展的服务,Pageserver为数据库带来了前所未有的灵活性和可扩展性。
分层存储架构:L0与L1层的协同
Pageserver采用基于LSM树(Log-Structured Merge Tree)的分层存储架构,将数据组织为L0(Level 0)和L1(Level 1)两层,有效平衡了写入性能和读取效率。
L0层包含一系列按LSN范围递减排列的层文件,每个L0层覆盖整个键空间。当内存中的数据达到checkpoint_distance阈值(默认256MB)时,Pageserver会将其排序后写入L0层文件。随着WAL写入的持续,L0层文件数量不断累积,可能导致读取放大问题。
L1层则由图像层(Image Layer)和增量层(Delta Layer)组成。图像层包含特定LSN下的页面快照,增量层则记录页面在LSN范围内的变更。通过L0→L1压缩和L1图像压缩两个阶段,Pageserver能够有效减少读取放大,提升系统性能。
Cloud Storage Page Server Safekeeper
L1 L0 Memory WAL
+----+ +----+----+
|AAAA| |AAAA|AAAA| +---+-----+ |
+----+ +----+----+ | | | |AA
|BBBB| |BBBB|BBBB| |BB | AA | |BB
+----+----+ +----+----+ |C | BB | |CC
|CCCC|CCCC| <---- |CCCC|CCCC| <--- |D | CC | <--- |DDD <---- ADEBAABED
+----+----+ +----+----+ | | DDD | |E
|DDDD|DDDD| |DDDD|DDDD| |E | | |
+----+----+ +----+----+ +---+-----+
|EEEE| |EEEE|EEEE|
+----+ +----+----+
页面缓存:高效内存管理机制
Pageserver实现了高效的全局页面缓存机制,使用8KB固定大小的缓冲区(与PostgreSQL页面大小匹配),并通过LRU(Least Recently Used)算法进行页面替换。页面缓存由所有租户共享,能够动态分配内存资源,提高内存利用率。
缓存键(CacheKey)唯一标识缓存的页面,对于不可变文件页面,缓存键由文件ID和块号组成。当需要读取页面时,Pageserver首先检查缓存,如果命中则直接返回;如果未命中,则从磁盘读取并填充缓存。通过这种机制,Pageserver能够显著减少磁盘I/O,提升读取性能。
页面缓存的实现细节可参考pageserver/src/page_cache.rs。该模块定义了页面缓存的核心数据结构和操作,包括缓存键的管理、页面的读写锁定机制以及缓存替换策略等。
WAL处理:从解析到持久化
WAL处理是Pageserver的核心功能之一,负责接收、解析和存储PostgreSQL的WAL记录。WAL处理流程如下:
- WAL接收:从WAL safekeeper接收WAL流。
- WAL解码:使用
wal_decoder模块解码WAL记录,生成InterpretedWalRecord。 - WAL存储:将解码后的WAL记录存储到Repository中,可选择页面图像或WAL记录格式。
Pageserver通过WalIngest结构体实现WAL的 ingestion 逻辑。ingest_record方法处理单个WAL记录,根据记录类型执行相应的操作,如创建关系、截断关系、清除VM位等。对于修改数据页的WAL记录,Pageserver会将其应用到相应的页面,并根据需要生成新的页面图像。
WAL处理的详细实现可参考pageserver/src/walingest.rs。该模块包含了解析WAL记录、更新检查点信息以及将WAL变更应用到数据页的核心逻辑。
压缩策略:平衡读写性能
为了平衡写入性能和读取效率,Pageserver采用了分层压缩策略,包括L0→L1压缩和L1图像压缩:
-
L0→L1压缩:当L0层文件数量超过
compaction_threshold(默认10)时触发。该过程将多个L0层文件合并排序,生成L1增量层文件,每个文件大小约为compaction_target_size(默认128MB)。 -
L1图像压缩:当L1层中某个键空间区域的增量层数量超过
image_creation_threshold(默认3)时触发。该过程在特定LSN点生成新的图像层,包含该LSN下的页面快照,从而减少读取时需要处理的增量层数量。
压缩过程由compaction_loop后台任务定期执行,默认每20秒检查一次是否需要压缩。通过这种主动压缩策略,Pageserver能够有效控制读取放大,保持系统性能稳定。
压缩策略的详细说明可参考docs/pageserver-compaction.md。该文档详细介绍了压缩的触发条件、执行流程以及与其他系统组件的交互。
多租户与隔离:资源管理与安全
Pageserver采用多租户架构,通过租户ID和时间线ID实现资源隔离。每个租户的元数据和数据存储在独立的目录结构中,确保租户间的数据隔离和安全性。
租户的元数据包括租户ID、时间线ID、PostgreSQL版本等信息,用于标识和管理租户的资源。数据存储采用键值对形式,键包含租户ID、时间线ID、关系标识和页面号等信息,确保不同租户的数据不会相互干扰。
Pageserver还实现了基于JWT的认证机制,确保只有授权用户能够访问租户数据。认证逻辑可参考pageserver/src/auth.rs,该模块定义了认证相关的结构体和方法,包括JWT令牌的验证和权限检查。
未来展望:持续优化与创新
Pageserver作为Neon的核心组件,仍在不断优化和演进中。未来的发展方向包括:
- 智能压缩策略:基于工作负载特征动态调整压缩参数,进一步优化读写性能。
- 多级缓存:引入多级缓存架构,结合本地缓存和分布式缓存,提升大规模部署下的性能。
- 增强的故障恢复能力:优化检查点机制和日志管理,减少故障恢复时间。
- 硬件加速:利用NVMe、RDMA等新技术提升存储和网络性能。
通过持续的技术创新和优化,Pageserver有望进一步提升Neon的性能和可靠性,为用户提供更优质的Serverless PostgreSQL体验。
总结
Pageserver通过分层存储、高效缓存、智能压缩等技术,彻底重构了PostgreSQL的存储引擎,实现了计算与存储的分离。这一创新架构使Neon能够提供自动扩缩容、分支功能和无限存储等Serverless特性,解决了传统数据库在云环境下的诸多挑战。
通过深入理解Pageserver的核心技术,我们可以更好地利用Neon的优势,构建高性能、可扩展的云原生应用。无论是开发人员还是运维人员,都能从Neon的创新设计中受益,提升数据库管理效率,降低运维成本。
要深入了解Pageserver的实现细节,建议参考以下资源:
- Pageserver源代码:包含页面缓存、WAL处理、压缩策略等核心模块的实现。
- Neon文档:包含架构设计、存储模型、操作指南等详细文档。
- Neon GitHub仓库:获取最新代码和参与社区贡献。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



