OpenTeleDB 测评,XStore 是惊喜!
前言
昨晚看到盖老板发了一条朋友圈
在 2025 年 11 月 1 日举办的 2025 GOTC 全球开源技术峰会上,中国电信宣布将其核心数据库产品 TeleDB 开源。
据悉,OpenTeleDB 针对 PostgreSQL 的核心痛点进行了深度创新,使其在性能波动和空间控制上远优于原生 PG,旨在为企业提供一个更稳定、高效且免于复杂运维的下一代开源数据库解决方案,并呼吁社区共同参与建设。OpenTeleDB 新增三大特性,XProxy、XStore 和 XRaft,具体内容可以参照官方网站:https://gitee.com/teledb/openteledb/blob/docs/docs/OpenTeleDB-Overview.md
XProxy
一直以来,PostgreSQL 的进程模型就被人诟病,XProxy 类似 pgbouncer,集成事务级连接池技术,实现前端连接与后端数据库连接的高效复用,并且看介绍还支持读写分离,这一点无疑相较于 pb 有不小优势,不过可惜的是,此次开源版并没有将 XProxy 开源出来,因此笔者也无法进行第一时间体验。我比较好奇的是:pgboucner 本身也是单进程模型,单机上限吞吐量大概在 5W 左右,XProxy 是进程模型还是线程?XProxy 相较于 pgcat,pgagroal 和奥德赛等连接池,有啥其独有的优势?并且既然类似 pb 是个代理,不知道其是不是也有单点故障的问题?
XStore
另一个让笔者感兴趣的便是 XStore 了,对于 PG 来说,一直被喷的点无益于其 MVCC 模型了,进而导致的诸如年龄问题、膨胀等更是经常被拿出来喷个体无完肤,为解决上述问题,OpenTeleDB 引入了 XStore 原位更新存储引擎。它有效解决了存储空间膨胀的问题,同时彻底解决垃圾回收带来的性能波动。XStore 通过创新的原位更新技术来解决空间膨胀的问题,XStore 此次开源了出来,又有点不同于夭折的 zheap,zheap 的索引没有 undo,Xstore 的索引也有 undo,于是笔者第一时间进行了尝鲜 (编译的时候记得加上 --with-xstore)
[postgres@mypg ~]$ psqlpsql (17.6)Type "help" for help.postgres=# create extension xstore ;CREATE EXTENSIONpostgres=# create table test_undo(id int,info text) using xstore;CREATE TABLEpostgres=# select version();version---------------------------------------------------------------------------------------------------------PostgreSQL 17.6 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit(1 row)
可以看到,使用前需要创建插件,并且 OpenTeleDB 基于 17.6 的 kernal,这便是插件化的优势,与上游解耦、升级成本低,做成扩展而不是永久 fork,能跟上 PG 的大版本节奏,把维护面积极小化(扩展重编译/小改即可)。典型例子是 Citus 走的就是扩展而非 fork 的路线,把分布式能力作为插件交付,这让它可以较快支持 PG17 等新版本,并且按需启用、降低风险与合规复杂度,类似地还有 openHalo,"让 PostgreSQL 说 MySQL 话",提供 MySQL 5.7/8.0 线级协议兼容,以便零改动迁到 PG 生态。
在数据目录下可以看到多了一个 undo 目录,自然是存放 undo 日志。
[postgres@mypg ~]$ ll openteletotal 144drwx------ 5 postgres postgres 4096 Nov 3 20:14 base-rw------- 1 postgres postgres 29 Nov 3 20:15 current_logfilesdrwx------ 2 postgres postgres 4096 Nov 3 20:14 globaldrwx------ 2 postgres postgres 4096 Nov 3 20:15 logdrwx------ 2 postgres postgres 4096 Nov 3 20:14 pg_commit_tsdrwx------ 2 postgres postgres 4096 Nov 3 20:14 pg_dynshmem-rw------- 1 postgres postgres 5711 Nov 3 20:14 pg_hba.conf-rw------- 1 postgres postgres 2640 Nov 3 20:14 pg_ident.confdrwx------ 4 postgres postgres 4096 Nov 3 20:14 pg_logicaldrwx------ 4 postgres postgres 4096 Nov 3 20:14 pg_multixactdrwx------ 2 postgres postgres 4096 Nov 3 20:14 pg_notifydrwx------ 2 postgres postgres 4096 Nov 3 20:14 pg_replslotdrwx------ 2 postgres postgres 4096 Nov 3 20:14 pg_serialdrwx------ 2 postgres postgres 4096 Nov 3 20:14 pg_snapshotsdrwx------ 2 postgres postgres 4096 Nov 3 20:15 pg_statdrwx------ 2 postgres postgres 4096 Nov 3 20:14 pg_stat_tmpdrwx------ 2 postgres postgres 4096 Nov 3 20:14 pg_subtransdrwx------ 2 postgres postgres 4096 Nov 3 20:14 pg_tblspcdrwx------ 2 postgres postgres 4096 Nov 3 20:14 pg_twophase-rw------- 1 postgres postgres 3 Nov 3 20:14 PG_VERSIONdrwx------ 4 postgres postgres 4096 Nov 3 20:14 pg_waldrwx------ 2 postgres postgres 4096 Nov 3 20:14 pg_xactdrwx------ 4 postgres postgres 4096 Nov 3 20:15 pg_xmultixact-rw------- 1 postgres postgres 88 Nov 3 20:14 postgresql.auto.conf-rw------- 1 postgres postgres 30736 Nov 3 20:15 postgresql.conf-rw------- 1 postgres postgres 29 Nov 3 20:15 postmaster.opts-rw------- 1 postgres postgres 91 Nov 3 20:15 postmaster.piddrwx------ 2 postgres postgres 4096 Nov 3 20:15 undo
让我们简单比比性能 (为了确保比对的公平性,参数均为一致,且在同一台环境上,同时修改了 checkpoint 参数减少 chk 带来的影响)
postgres=# insert into test_undo select n,md5(random()::text) from generate_series(1,10000000) as n;INSERT 0 10000000Time: 63565.188 ms (01:03.565)postgres=# truncate table test_undo ;TRUNCATE TABLETime: 39.913 mspostgres=# insert into test_undo select n,md5(random()::text) from generate_series(1,10000000) as n;INSERT 0 10000000Time: 61421.193 ms (01:01.421)
再看看原生 PG,性能相差一倍,看样子为了维护 undo 日志,牺牲了部分写入效率,毕竟要写入两个文件。
postgres=# insert into test_undo select n,md5(random()::text) from generate_series(1,10000000) as n;INSERT 0 10000000Time: 33592.512 ms (00:33.593)
让我们再看看 update 的效率对比,就是个很简单的更新 pgbench -f update.sql -D max_id=10000000 -c 2 -j 5 -T 60 -d postgres -v -P 1 -p 54333
\set id random(1, :max_id)UPDATE test_undoSET info = md5((random())::text)WHERE id = :id;
在我这个环境上,就更新操作,OpenTeleDB 大约有 10% 的性能提升,并且观察 TPS 的结果,XStore 要更稳定一些,PG的“凹”多得多。据官方测试资料
XStore 在 BenchmarkSQL 场景下,也要"平稳"一些,不过彼之蜜糖,吾之砒霜,引入 undo 的优势是平稳,但是代价自然也牺牲了 RTO,以及写入效率,各位要辩证地看待,根据不同场景选择不同的引擎,才能充分发挥其优势。更多测试,就请各位读者自行验证了。
XRaft
另外一个功能便是 XRaft 了,各位可以参照官方介绍,此次也还未开源出来。
OpenTeleDB 引入了基于 Raft 共识算法深度优化的 XRaft 技术。在日志复制方面,XRaft 实现了真正的一致性日志复制。其核心在于,它将 Raft 算法强一致的日志复制机制深度集成到数据库内核中,使得集群中每个节点都维护着一份与多数派达成共识的、唯一的日志序列。因此,在进行任意节点的主备切换时,绝不会发生日志分叉;在选主方面,XRaft 将 Raft 算法的选举过程应用于数据库的选主。
小结
“插件化”是 Postgres 的天然路径:能插件化的尽量插件化,插件化不了的,用“少量内核增强 + 组件”的方式把功能装配起来;此次 OpenTeleDB 的开源,我认为这是一个值得关注的积极信号,同时也应保持理性分析其机会与挑战,开源利于扩展、创新、生态共建,也可能推动与 upstream 更好融合。但是“开源”不等于“社区活跃”,开源只是第一步,关键是是否有活跃的社区治理、贡献者、Issue/PR 流程、文档支持,是否接受第三方扩展、是否有社区版 vs 商用版的明确分层、是否有用户/开发者论坛、Issue 跟踪透明、文档完善等等。若只是“源码开放但闭源式维护”,社区价值会大打折扣,不过今天笔者就第一时间加入了官方用户交流群,群里也有作者积极回应与解决,相信 OpenTeleDB 社区会越做越好。
参考
https://openteledb.ctyun.cn/open/openteledb
https://github.com/OpenTeleDB/OpenTeleDB
https://www.modb.pro/db/1984916549807988736