找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

5106

积分

0

好友

677

主题
发表于 3 小时前 | 查看: 6| 回复: 0

2025 年,随着 Neon 和 CrunchyData 两家 PostgreSQL 生态公司被收购,PostgreSQL 再次成为行业焦点。除了数据库本体的发展,其生态扩展主要沿两条路径推进:我称之为“自下而上”的扩展方式和“自上而下”的协议兼容方式。

以与 Rust 生态的结合为例,“自下而上”的方式主要基于 pgrx 框架,将各种 Rust 库引入 PostgreSQL 内部,代表项目如 ParadeDB;而“自上而下”的方式则通过模拟 PostgreSQL 的协议和接口,构建出各种“类 Postgres”的全新数据库。

GreptimeDB 从早期版本就开始适配 Postgres 协议,走的正是“自上而下”这条路。

什么是 Postgres 协议?

狭义的 Postgres 协议,特指用于与 PostgreSQL 服务端通信的 TCP 应用层协议。当我们使用 psql 命令行工具或 JDBC 驱动连接数据库时,底层发生的正是基于此协议的通信。

概括来说,这个协议主要包含 5 个部分:

  • 启动:包含连接建立阶段的握手信息交换和各类认证机制。
  • 简单查询:基于文本的查询和响应。
  • 扩展查询:俗称 PreparedStatement,支持后端缓存查询语句,仅传输参数,提升效率。
  • 拷贝:用于数据的批量导入和导出。
  • 取消:取消一个正在执行的查询。

这里我们并未包含数据库逻辑同步协议和流式同步协议,尽管它们也采用了类似的思路。

然而,要实现相对完整的 Postgres 兼容性,仅支持狭义的网络协议是远远不够的,我们还需要支持广义的 PostgreSQL 接口,包括:

  • 查询语言:兼容其 SQL 方言和关键内置函数。
  • 数据类型系统:建立与 Postgres 自身类型系统的映射关系。
  • pg_catalog 元信息:支持其元数据体系,这是许多客户端工具能正确工作的基础。

PostgreSQL 协议兼容性分层架构图

兼容 Postgres 协议的好处

相较于从头设计一套全新的四层协议,复用成熟的 Postgres 协议带来诸多优势:

  1. 经过充分验证,核心功能可靠。PostgreSQL 当前主流的 3.0 版本协议已稳定运行十多年,经过了海量生产环境的考验。它完整支持 TLS、多种认证方式以及与客户端的特性协商。这套协议本身甚至具备流式返回数据的能力,只是受限于 PostgreSQL 原生的进程模型而未被充分利用。

  2. 解锁海量的生态工具链。几乎每种主流编程语言都有成熟的 PostgreSQL 客户端驱动。只需实现协议支持,就能直接使用这些驱动来编写访问 GreptimeDB 的应用程序。此外,从最简单的 psql 命令行,到 DBeaver 等 GUI 管理工具,再到各类 BI 报表系统,都可以将兼容 Postgres 协议的数据库直接当作 PostgreSQL 来使用。这部分工具往往对 pg_catalog 的兼容性有更高要求,以便提取元数据。

  3. 可作为原生 PostgreSQL 的 FDW 数据源。这意味着你可以将 GreptimeDB 挂载为原生 PostgreSQL 的一个外部数据源,直接在 PostgreSQL 中发起 SQL 查询,甚至可以实现两个异构数据库之间的 JOIN 操作。这种架构非常适合混合数据管理的场景,例如用原生 PostgreSQL 管理设备元数据,而用时序数据库 GreptimeDB 管理其产生的指标数据。

通过 DBeaver 图形化界面访问 GreptimeDB

当然,Postgres 协议也存在一些局限性:

  1. 协议面向行式数据结构设计。如果数据库底层是列式存储,在返回原始数据时需要进行行列转换,可能带来额外开销。
  2. 查询取消机制与 PostgreSQL 的进程模型强绑定,在其他架构中较难实现,且存在一定的安全风险。
  3. 扩展查询对数据库的类型推断能力有要求。协议要求数据库能在不实际查询数据的情况下,对语句中的变量参数进行类型推断。例如 SQLite 和 DuckDB 就无法直接从语句推断参数类型,因此难以完整适配扩展查询协议。

GreptimeDB 如何实现兼容?

GreptimeDB 通过笔者开发的 pgwire 库及其在 DataFusion 查询引擎上的生态来实现 Postgres 协议兼容。

GreptimeDB 中 PostgreSQL 协议兼容性的组件架构

传输协议支持

如果将 Postgres 协议比作 HTTP 协议,那么 pgwire 就相当于 Rust 生态中的 hyper 乃至 axum 框架。它帮助用户构建兼容 Postgres 协议的服务端,用户可以选择性地实现认证、简单查询、扩展查询、拷贝等功能,以达到不同程度的兼容性。

以简单查询为例,pgwire 提供了两个层次的 API:

  1. 低层 APISimpleQueryHandler::on_query,关注网络消息层面的处理和协议语义。
  2. 高层 APISimpleQueryHandler::do_query,关注数据层面的处理和业务语义。

有趣的是,对于简单查询子协议,它甚至不要求客户端发送的必须是 SQL 语句。下面是一个简单的“回声”处理器示例,它会将任何输入字符串原样返回:

#[async_trait]
impl SimpleQueryHandler for EchoHandler {
    async fn do_query<C>(&self, _client: &mut C, query: &str) -> PgWireResult<Vec<Response>>
    where
        C: ClientInfo + Sink<PgWireBackendMessage> + Unpin + Send + Sync,
        C::Error: Debug,
        PgWireError: From<<C as Sink<PgWireBackendMessage>>::Error>,
    {
        let query = query.to_string();
        let f1 = FieldInfo::new("input".into(), None, None, Type::VARCHAR, FieldFormat::Text);
        let schema = Arc::new(vec![f1]);
        let data = vec![Some(query)];
        let mut encoder = DataRowEncoder::new(schema.clone());
        let data_row_stream = stream::iter(data).map(move |r| {
            encoder.encode_field(&r)?;
            Ok(encoder.take_row())
        });
        Ok(vec![Response::Query(QueryResponse::new(schema, data_row_stream,))])
    }
}

使用 psql 连接这个服务,你会看到如下效果:

❯ psql -h 127.0.0.1 -p 5432 -U postgres
psql (18.1, server 16.6-pgwire-0.38.2)
Type "help" for help.

postgres=# hello world;
  input
--------------
 hello world;
(1 row)

pg_catalog 元信息支持

pgwire 解决了网络协议问题,但要实现更深入的兼容性(特别是让 GUI 工具正常工作),就必须提供元信息 (pg_catalog) 支持。由于 pg_catalog 本质上是一系列系统表或视图,因此需要构建在某个查询引擎之上。

GreptimeDB 使用了 Apache DataFusion 作为其查询引擎。为此,我们维护了 datafusion-postgres 项目。它充当了 pgwire 与 DataFusion 查询引擎、Arrow 内存格式之间的适配器,其中包含了对 pg_catalog 的支持以及 Arrow 数据到 Postgres 数据格式的转换模块 (arrow-pg)。

pg_catalog 功能庞杂,许多表与 PostgreSQL 内部机制深度绑定。我们优先关注其中几个核心表:

  • pg_database: 数据库信息
  • pg_namespace: 模式(schema)信息
  • pg_tables: 表信息
  • pg_class: 列信息

一些高级管理工具(如 DataGrip)在连接初始化阶段会发送非常复杂的 pg_catalog 查询,可能涉及 DataFusion 不支持的语法或 UDF。这部分适配工作需要针对性处理,也欢迎对 数据库/中间件 协议兼容感兴趣的开发者参与到 datafusion-postgres开源实战中来。

作者在 DataFusion 社区 Meetup 上分享 datafusion-postgres

总结

我们将 PostgreSQL 兼容性的能力封装成了可复用的库(pgwiredatafusion-postgres)。这不仅让 GreptimeDB 能够快速实现协议兼容,也意味着任何现代数据基础设施都可以利用这些库来适配 Postgres 协议,从而构建一个全新的“类 Postgres”生态。这何尝不是一种新时代的“Postgres”?

除了 GreptimeDB,pgwire 还被应用于多个项目,例如被 ClickHouse 收购的 PeerDB、为实时在线游戏设计的 SpacetimeDB、fly.io 的开源项目 corrosion 以及近期发布的 db9.ai 等。在 DataFusion 生态中,我们甚至可以结合 geoarrowgeodatafusion 来探索构建与 PostGIS 兼容的地理空间数据处理生态。

如果你也对构建这样一个新颖的、基于现代技术栈的数据访问生态感兴趣,欢迎加入相关项目的开发,或者直接使用这些工具来实现你的想法。

往期精彩文章





上一篇:Rust生态动态:三款新兴工具Cellophane、Aralez与Toasty解析
下一篇:开源 Hermes Agent 解析:基于自学习闭环与记忆架构的智能体框架
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-4-12 04:16 , Processed in 0.606824 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表