Quack: 为 DuckDB 引入客户端-服务器架构

多年来,DuckDB 一直倡导进程内(in-process)架构。通过消除客户端-服务器之间的隔阂,它为数据科学家和开发人员提供了一个直接运行在应用程序或 notebook 中的低延迟、高性能工具。然而,这种设计也带来了一个根本性的限制:难以同时从多个进程修改单个数据库文件。

为了解决这个问题,DuckDB 团队推出了 Quack,一种专用的客户端-服务器协议。Quack 允许 DuckDB 实例之间相互通信,将 DuckDB 从一个严格的本地工具转变为一个能够支持集中式状态和并发远程访问的多功能系统。

需要远程协议的原因

进程内系统在交互式分析方面表现出色,但在遥测数据收集或仪表板展示方面却显得力不从心,因为在这些场景下,多个进程必须向同一个数据集写入数据。虽然用户之前依赖于各种变通方法——例如自定义 RPC 层、Arrow Flight SQL 协议,或将 DuckDB 封装在 PostgreSQL 中(即所谓的 "EleDucken" 方法)——但对原生解决方案的需求已变得不可忽视。

Quack 被设计为一个“通用数据处理工具”,在提供服务器管理的可变状态(mutable state)优势的同时,保持了用户对 DuckDB 所期望的简单性和速度。

Quack 的工作原理

Quack 允许任何 DuckDB 实例充当客户端或服务器。该设置通过一个 DuckDB 扩展来处理,使用户能够通过简单的 SQL 命令来提供数据库服务并远程连接到它。

核心技术设计

  • 基于 HTTP: Quack 构建在 HTTP 之上,确保了与现有负载均衡器、防火墙和身份验证系统的兼容性。这一选择也使得 DuckDB-Wasm 能够原生支持 Quack,从而允许基于浏览器的实例直接连接到远程服务器。
  • 请求-响应模式: 该协议遵循客户端驱动的请求-响应模型。它针对低延迟进行了优化,允许查询在单次往返中完成。
  • 自定义序列化: Quack 没有使用外部交换格式,而是使用了一种新的 MIME 类型 application/duckdb。这利用了 DuckDB 的内部序列化原语(与其 Write-Ahead Log 中使用的相同),从而允许团队在不受外部格式限制的情况下,对数据类型进行创新。
  • 安全性: 默认情况下,Quack 在启动时会生成一个随机身份验证令牌,并绑定到 localhost。对于生产环境,团队建议使用 Nginx 等反向代理来处理 SSL 终止。

可扩展的身份验证与授权

Quack 没有构建僵化的权限系统,而是使用了一种基于回调的模型。身份验证(验证用户身份)和授权(决定用户可以做什么)都可以通过用户提供的代码甚至简单的 SQL 宏来覆盖,从而使其能够与 LDAP 或基于自定义文本文件的身份验证集成。

性能基准测试

为了验证该协议,团队在 AWS m8g.2xlarge 实例上将 Quack 与 PostgreSQL 和 Arrow Flight SQL 进行了对比测试。

大量数据传输

在移动大量数据时,Quack 展示了显著的优势。在传输 TPC-H lineitem 表的测试中,Quack 仅用 4.94 秒 就移动了 6000 万行数据(CSV 格式下为 76 GB),表现远超 Arrow Flight (17.40s) 和 PostgreSQL (158.37s)。

小规模写入吞吐量

在针对多个线程进行小规模、随机 INSERT 事务的测试中,令人惊讶的是,Quack 在低并发场景下表现优于 PostgreSQL,在 8 个线程下达到了约 5,500 次事务/秒。虽然 PostgreSQL 在超过 8 个线程时扩展性更好,但 Quack 为集中化可观测性(observability)和遥测数据提供了极高效的路径。

为什么不使用 Arrow Flight SQL?

鉴于 Arrow Flight SQL 协议已经存在,选择构建自定义协议是一个深思熟虑的决策。团队提出了两个主要原因:

  1. 对创新的控制权: 使用外部交换格式会限制 DuckDB 快速添加新数据类型或协议消息的能力。
  2. 单次往返效率: Arrow Flight SQL 对于每个查询至少需要两次往返(CommandStatementQueryDoGet)。Quack 旨在实现单次往返执行,这对于延迟敏感型的小规模更新至关重要。

前景展望

Quack 目前可在 core_nightly 仓库中获取,并计划在 2026 年秋季随 DuckDB v2.0 一起发布生产版本。未来的开发方向包括:

  • DuckLake 集成: 使用远程 DuckDB 服务器作为 DuckLake 目录,以提高性能和数据内联(data inlining)。
  • ** scaling 扩展并发:** 改进核心引擎以支持显著多于 8 个的并行插入线程。
  • 复制 (Replication): 基于 Quack 开发复制协议,以实现只读副本集群。

通过弥合进程内效率与客户端-服务器灵活性之间的鸿沟,Quack 将 DuckDB 定位为现代数据架构的核心构建块,而不仅仅是一个用于本地分析的利基工具。

Sources