数据库即业务架构

数据库是业务架构的核心,是不言自明的共识。但如果我们更进一步,将数据库作为架构本身,又会发生什么? 未来会是一个数据库吞噬后端,前端,操作系统,甚至一切的世界吗?


数据库是架构的核心

“If you show me your software architecture, I learn nothing about your business. But if you show me your data model, I can guess exactly what your business is.”。 —— Michael Stonebraker

数据库祖师爷迈克·石破天有句名言:“如果你给我看软件架构,我对你的业务一无所知;但如果你给我看数据模型,我就能精准知道你的业务是干嘛的”

无独有偶,微软 CEO 纳德拉 也在最近公开表示:我们今天所称的软件,你喜欢的那些应用程序,不过是包装精美的数据库操作界面而已。

即使在 GenAI / LLM 爆火的当下,绝大多数信息系统依然是以数据库为核心设计。所谓的分库分表,几地几中心,异地多活这些架构花活,说到底也就是数据库的不同使用方式罢了。

数据库是业务架构的核心,早已是不言自明的共识。但如果我们更进一步,将数据库作为业务架构本身,又会如何?


驱动未来的数据库

不久之前,我邀请 Omnigres 创始人 Yurii 到 第七届PG生态大会 上进行分享。 他在题为《数据库驱动未来》 的演讲中抛出了一个有趣的观点 —— 数据库就是业务架构。(DBaaA, Database as an Architecture)

具体来说,他的开源项目做了一件“疯狂”的事:把所有应用逻辑,甚至 Web Server 都塞进 PostgreSQL 数据库。 不只是后端包个REST接口中间件这种形式,而是把前后端都整个塞进 PG 里去了!

CREATE EXTENSION omni_httpd CASCADE;
CREATE EXTENSION omni_vfs   CASCADE;

CREATE FUNCTION mount_point()
  returns omni_vfs.local_fs language sql AS $$SELECT omni_vfs.local_fs('/www')$$;

UPDATE omni_httpd.handlers
SET query = (SELECT omni_httpd.cascading_query(name, query) FROM
  (SELECT * FROM omni_httpd.static_file_handlers('mount_point', 0,true)) routes);

httpd.png

几行 SQL 就能把 PostgreSQL 变成一个能跑在 8080 端口的 ‘Nginx’,并且还能用数据库函数编写业务逻辑,实现 HTTP API。 看到这种神奇玩法,我一度怀疑这玩意到底能不能行。但事实就是它居然跑了起来,还真挺像那么回事。

除了这里的 httpd 扩展外,Omnigres 还提供了另外 33 个扩展插件, 这套扩展全家桶,提供了在 PostgreSQL 中进行完整 Web 应用开发的能力!

类似 PostgREST 这样的工具,可以将设计良好的 PostgreSQL 模式直接转化为开箱即用的 RESTful API。 而 Omnigres 这样的工具则是百尺竿头更进一步,直接让 HTTP 服务器运行在了 PG 数据库内部!而这意味着,你不仅可以把后端放进数据库里,你甚至可以把前端也放进数据库中!

但这真的会是一个好主意吗?还是要看具体情况。 互联网企业出身的架构师或者数据库 DBA 看到这种玩法可能会大喊:“这也太离经叛道了!” 但是也不要着急下结论,我还真的看到过这种开发范式取得过成功。


DBaaA的利弊权衡

早先我在探探时(一个瑞典团队在中国运营的约会应用,Tinder in China),我们深度利用了 PostgreSQL:那时候我们所有的业务逻辑(包括一个 100ms 的推荐算法)都是 PG 存储过程。 后端应用只是一个 Go 写的非常轻薄一层转发代理,虽然没有把 Web Server 放到 PostgreSQL 中,但也基本差不多了。

靠着这种单一 PostgreSQL 选型的架构,我们在没有使用任何其他数据库(我们确实用了对象存储)的情况下,一路干到了在四百万日活,与 2.5M 数据库 QPS。 而建设这一切的只有三位工程师。其实有点儿像 Instagram,因为其实我们就是仿照着 Instagram 的架构搞的。 将业务逻辑,甚至业务架构整个放入数据库中(以下简称为 DBaaA)优点与缺点都非常明显。

这种玩法的优点在于出活快,架构简单、部署敏捷、延迟性能好,开发成本低:当你设计好 PostgreSQL 数据库模式后,用 PostgREST + Kong 几行配置就能自动生成后端,一套服务新鲜出炉。 很多管理操作可以用纯SQL完成,比如 CI/CD/发布/迁移/降级等;比如,要实现一个断路器,执行 SQL 刷新存储过程逻辑,提前返回即可。 架构设计与部署交付上非常简单,一个数据库 + 一个无状态的网关,复制一份数据目录,就是一套新的部署。 而且出乎意料的是,这种实践的性能并不差 —— 因为存储过程可以有效节省交互式查询多次网络往返的开销, 而内置的web服务器也省下了额外的交互,所以在响应时间/延迟(RT/Latency)表现上反而相当出色。

但这种架构的劣势也同样非常显著:数据库的吞吐确实会因为承担了更多计算逻辑而下降, 而在 2017 年那会的硬件性能还没有现在发达,数据库通常是整个架构中的性能瓶颈,单节点动辄大几万 TPS,确实没有多少性能余量给这些花活。

而比起吞吐量上的问题,人力的挑战更为棘手,而随着创始骨干的离开,编写存储过程开始成为一门逐渐失传的高深技术 —— 新员工不会写了!

所以我们最后还是逐渐将这些存储过程抽离出来在外部应用中实现,也开始使用 Redis 以及其他数据库给 PG 打辅助,但那已经是被收购之后的事了。 不过现在回头再看看,如果是在 2025 年的当下,我认为会有完全不一样的选择:因为无论是软件还是硬件都已经发生了翻天覆地的变化,而这些变化带来了全新的利弊权衡。


分久必合的架构钟摆

俗话说:“分久必合,合久必分”。在上古时期,许多应用使用的也是这种简单的 C/S,B/S 架构,几个客户端直接读写数据库。 但是后来,随着业务逻辑的复杂化,以及硬件性能(相对于业务需求)的捉襟见肘,许多东西从数据库中被剥离出来,形成了传统的三层架构,以及越来越多的组件。

但现在时过境迁,GPT 已经达到了能够熟练编写存储过程的中高级开发者的水准,而遵循摩尔定律发展的硬件直接把单机性能推到了一个匪夷所思的地步。 那么拆分剥离的趋势也很有可能会逆转,原本从数据库中分离出去的业务逻辑,又会重新回到数据库中。 将业务逻辑放到数据库中,甚至让数据库成为整个业务架构本身,可能重新成为一种流行的实践。

实际上,我们已经可以在《PostgreSQL吞噬数据库世界》,以及社区正在流行的 “一切皆用 PostgreSQL” 口号中,观察到观察到数据库领域正在出现的收敛趋势: 原先从数据库中分离出去的细分领域专用数据库,如全文搜索、向量,机器学习、图数据库、时序数据库等,现在都在重新以插件超融合的方式回归到 PostgreSQL 中。

相应地,前端,后端重新融合回归到数据库的实践也开始出现。我认为一个非常值得注意的例子是 Supabase,一个号称 “开源 Firebase” 的项目,据说 80% YC 创业公司都在使用它。 它将 PostgreSQL,对象存储,PostgREST,EdgeFunction 和各种工具封装成为一整个运行时,然后将后端与传统意义上的数据库整体打包成为一个 “新的数据库”。

Supabase 实际上就是 “吃掉” 了后端的数据库,如果这种架构走到极致,那大概会是像 Omnigres 这样的架构 —— 一个运行着 HTTP 服务器的 PostgreSQL,干脆把前端也吃下去了。

当然,可能还有更为激进的尝试 —— 例如 Stonebraker 老爷子的新创业项目 DBOS,甚至要把操作系统也给吞进数据库里去了!

这也许意味着软件架构领域的钟摆正在重新回归简单与常识 —— 前端绕开花里胡哨的中间件,直接访问数据库,螺旋上升回归到最初的 C/S,B/S 架构上去。 或者像纳德拉所说,Agent 可以直接绕过中间商,代替前后端与软件去读写数据库,出现一种新的 A(gent)/D(atabase) 架构也未尝不可。


拆分与合并的利弊权衡

在当下,

然而,吞吐和人力,这两个核心障碍在 2025 年的当下,已经被软硬件告诉

有机会规避一些复杂的并发争用,并通过节省了后端与数据库的网络 RT 带来更好的延迟性能表现; 而且在管理上也会有一些独特优势:所有业务逻辑、模式定义和数据都在同一个地方,用同样的方式处理,你的 CI/CD,发布/迁移/降级都可以用SQL实现。 你想部署一套新系统?把 PostgreSQL 数据目录复制一份,重新拉起一个 PostgreSQL 实例就可以了。一个数据库解决所有问题,架构简单无比。

而主要缺点在于人员要求高,运维复杂,最大吞吐下降。

类似 PostgREST 这样的工具,可以将设计良好的 PostgreSQL 模式直接转化为开箱即用的 RESTful API。 而 Supabase 这样的 BaaS 更是在其基础上将整个后端都变成了一项公用服务 —— 这意味着你只要设计好数据库模型,基本就没有什么后端开发的工作了。 Omnigres 这样的工具则是百尺竿头更进一步,直接让 HTTP 服务器运行在了 PG 数据库内部!而这意味着,你不仅可以把后端放进数据库里,你甚至可以把前端也放进数据库中!

这样做在管理上也有一些独特优势:所有业务逻辑、模式定义和数据都在同一个地方,用同样的方式处理,你的 CI/CD,发布/迁移/降级都可以用SQL实现。 你想部署一套新系统?把 PostgreSQL 数据目录复制一份,重新拉起一个 PostgreSQL 实例就可以了。一个数据库解决所有问题,架构简单无比。

使用 PostgreSQL 作为业务架构,你可以

由数据库处理业务逻辑,可以通过避免交互式查询的多次网络RT来提高查询(延迟)性能,但是消耗数据库服务器的 CPU 资源会导致最大吞吐量下降。 将业务逻辑作为 SQL / 存储过程会带来一些管理上的优势:用统一的方式管理代码与数据,CI/CD,发布/迁移/降级都可以用SQL实现,高度集成,非常灵活; 但也会带来新的挑战:在数据库里对模式变更,版本控制,备份恢复都是全新的玩法,一般的开发者和DBA恐怕并没有能力兜住这种“激进”的玩法。

有机会规避一些复杂的并发争用,并通过节省了后端与数据库的网络 RT 带来更好的延迟性能表现; 而且在管理上也会有一些独特优势:所有业务逻辑、模式定义和数据都在同一个地方,用同样的方式处理,你的 CI/CD,发布/迁移/降级都可以用SQL实现。 你想部署一套新系统?把 PostgreSQL 数据目录复制一份,重新拉起一个 PostgreSQL 实例就可以了。一个数据库解决所有问题,架构简单无比。

时将几乎所有的业务逻辑(甚至推荐算法)都在 PostgreSQL 里实现,后端只有很轻薄的一层转发。 只不过这种做法对开发者、DBA 的综合技能要求较高 —— 毕竟写存储过程、维护复杂的数据库逻辑不是一件轻松活儿。

老实说 DBA 和运维很难喜欢这些看上去 “离经叛道” 的玩意。但作为一个开发者,特我认为这个主意非常有趣,值得探索!


吞噬一切的数据库

俗话说:“分久必合,合久必分”。在上古时期,许多 C/S,B/S 架构的应用就是几个客户端直接读写数据库。 但是后来,随着业务逻辑的复杂化,以及硬件性能(相对于业务需求)的捉襟见肘,许多东西从数据库中被剥离出来,形成了传统的三层架构。

硬件的发展让数据库服务器的性能重新出现大量的富余,而数据库软件的发展让存储过程的编写变得更加容易, 那么拆分剥离的趋势也很有可能会逆转,原本从数据库中分离出去的业务逻辑,又会重新回到数据库中。


拥抱新趋势

如果你想试试在数据库里写应用,一套 PostgreSQL 打天下的刺激玩法,确实应该尝试一下 Supabase 或者 Omnigres! 我们最近实现了了在本地自建 Supabase 的能力(这涉及到二十多个扩展,其中有几个棘手的扩展使用Rust编写), 并在刚刚提供了对 Omnigres 扩展的支持 —— 这为 PostgreSQL 提供了 DBaaA 的能力。

如果你有几十万 TPS,几十 TB 的数据,或者运行着一些至关重要、人命关天、硕大无朋的核心系统,那么这种玩法可能不太合时宜。 但如果你运行的是一些个人项目,小网站,或者是初创公司与边缘创新系统,那么这种架构会让你的迭代更为敏捷,开发、运维更加简单。

当然不要忘记,除了二十多种可以用于编写存储过程的的语言支持外,PostgreSQL 生态中还有 1000+ 扩展插件可以提供各种强力功能。 除了大家都已经耳熟能详的 postgis, timescaledb, pgvector, citus 之外,最近还有许多亮眼的新兴扩展: 比如在 PG 上提供 ClickHouse T0 分析性能的 pg_duckdbpg_mooncake,提供比肩 ES 全文检索的 pg_search, 将 PG 转换为 S3 湖仓的 pg_analyticspg_parquet,…… 我们将在 OLAP 领域再次见证一个类似 pgvector 的玩家出现,让许多 “大数据” 组件变成 Punchline。

而这正是我们 Pigsty 想要解决的问题 —— Extensible Postgres,让所有人都可以轻松使用这些扩展插件,让 PostgreSQL 成为一个真正的超融合数据库全能王。

在我们开源的 Pigsty 扩展仓库中,总共已经提供了将近 400 个开箱即用的扩展,你可以在主流Linux系统(amd/arm, EL 8/9, Debian 12, Ubuntu 22/24),使用 Pigsty 一键安装这些扩展。 但这些插件是一个可以独立使用的仓库(Apache 2.0),您非一定要使用 Pigsty 才能拥有这些扩展 —— Omnigres 与 AutoBase 这样的 PostgreSQL 也在使用这个仓库进行扩展交付,这确实是一个开源生态互惠共赢的大好例子。 如果您是 PostgreSQL 供应商,我们非常欢迎您使用 Pigsty 的扩展仓库作为上游安装源,或在 Pigsty 中分发您的扩展插件。

如果您是 PostgreSQL 用户,并对扩展插件感兴趣,也非常欢迎看一看我们开源的 PG 包管理器 [pig] ,可以让您一键轻松解决 PostgreSQL 扩展插件的安装问题。


什么,还能这么玩

在 PG 生态大会上,尤里展示了一个想法:把所有业务逻辑,甚至是Web服务器和整个后端都塞进 PostgreSQL 数据库里。 比如可以通过写存储过程,把原本后端功能直接放到数据库里运行。为此,他还以 PG 扩展的形式实现了许多 “标准库”,从 http, vfs, os 到 python 模块。

让我们来看一个有趣的例子,在 PostgreSQL 中执行以下 SQL,将会启动一个 Web 服务器,将 /www 作为一个 Web 服务器的根目录对外提供服务。

CREATE EXTENSION omni_httpd CASCADE;
CREATE EXTENSION omni_vfs CASCADE;
CREATE EXTENSION omni_mimetypes CASCADE;

create function mount_point()
returns omni_vfs.local_fs language sql AS
$$select omni_vfs.local_fs('/www')$$;

UPDATE omni_httpd.handlers
SET query = (SELECT omni_httpd.cascading_query(name, query order by priority desc nulls last)
         from (select * from omni_httpd.static_file_handlers('mount_point', 0,true)) routes);

是的,天啊,PostgreSQL 数据库竟然拉起来了一个 HTTP 服务器,默认跑在 8080 端口!你可以把它当成 Nginx 用!

httpd.png

当然,你可以选择任意你喜欢的编程语言来创建 PostgreSQL 函数,并将这些函数挂载到 HTTP 端点上,实现你想要的任何逻辑。

如果是熟悉 Oracle 的用户可能会发现,这有点类似于 Oracle Apex。但在 PostgreSQL 中,你可以用二十多种编程语言来开发存储过程,而不仅仅局限于 PL/SQL!

除了这里的 httpd 扩展外,Omnigres 还提供了另外 33 个扩展插件,这套扩展全家桶,提供了在 PostgreSQL 中进行完整 Web 应用开发的能力!

BTW 他还说 SaaS is Dead:因为以后 Agent 可以直接绕过中间商,代替前后端去读写数据库

这意味着,你可以把一个经典前端-后端-数据库三层架构的应用,完整地塞入一个数据库中!

当然,你可以选择任意你喜欢的编程语言来创建 PostgreSQL 函数,并将这些函数挂载到 HTTP 端点上,实现你想要的任何逻辑。 他是怎么做到的?Omnigres 提供了一套扩展全家桶,包括 httpdvfsospython 等33个 PG “标准库”扩展模块。 从浏览器可以访问 HTML 页面,而 HTML 页面可以通过 Javascript 动态访问 HTTP 服务器与数据库存储过程。

将业务逻辑,Web Server,甚至是整个前后端都放入数据库中,又会擦出怎么样的火花?

这个想法的实质是:把所有业务逻辑,甚至是Web服务器和整个前后端都塞进 PostgreSQL 数据库里。 让我们来看一个有趣的例子,在 PostgreSQL 中执行以下 SQL,将会启动一个 Web 服务器,将 /www 作为一个 Web 服务器的根目录对外提供服务: 天啊,PostgreSQL 数据库竟然拉起来了一个 HTTP 服务器,默认跑在 8080 端口!你可以把它当成 Nginx 用! 除了实现 httpd 之外,他还以 PG 扩展的形式实现了许多 “标准库”,这包括一个由 33 个扩展插件组成的全家桶,提供在 PostgreSQL 中进行完整 Web 应用开发的能力!

熟悉 Oracle 的用户可能会发现,这有点类似于 Oracle Apex。但在 PostgreSQL 中,你可以用二十多种编程语言来开发存储过程,而不仅仅局限于 PL/SQL!

但如果你的性能主要指的是 “最大TPS吞吐量”,那么

但比起吞吐性能下降,这种实践不受待见的一个核心原因是,它对人的要求太高了 —— 这种实践通常只有精英小团队才能玩转。 你要会写存储过程,以及更重要的,你要知道在这种范式下如何实现各种各样的管理操作(PITR,备份恢复,高可用,CI/CD,模式变更,版本控制)。 而拥有这些经验的人要比拥有常规实践经验的人要稀少得多。

吞吐和人力,是这种范式的最大困难。

最后修改 2025-02-16: init commit (35df8f3)