前言
上周帮一个朋友单位把关信创选型,OceanBase 跟金仓二选一。两边都来了人,PPT 厚厚一沓,会开了一下午,没吵出结果。
推 OB 的说,人家银行核心都跑过了,分布式多牛。推金仓的说,我们在政企市场干了二十多年,图的就是稳。
回来的路上我一直在琢磨,两边吵的其实全是名词。什么 Paxos,什么共享存储,听着热闹,落不了地。真到落地,纠结的就两件事:延迟差多少?复杂 SQL 谁接得住?
这两块我刚好都踩过坑,写出来给后面的人参考。丑话说在前面,多少带点个人倾向,但不忽悠人。
一、先看骨架
OceanBase(下面简称 OB)是原生分布式。表进去先切分区,分区往一堆服务器上撒,每个分区默认存三份,副本之间靠 Paxos 投票选主、同步日志。没有中心节点这一说,坏一台,多数派里挑个副本顶上,服务接着跑。
金仓(KES)走集中式。一个实例把数据全管了,缓冲区、锁、事务、优化器,全在一个进程里转。要高可用就上主备,备库拉日志追主库。要求再高点,上共享存储集群,好几个实例读写同一份数据,一台倒了另一台秒级接管。数据从头到尾就一份。
| 对比项 | OceanBase | 金仓数据库 KES |
|---|---|---|
| 架构形态 | 原生分布式,分区打散多机 | 集中式单实例,集群另配 |
| 数据副本 | 每分区默认三副本,数据存三份 | 主备各一份;共享存储集群全局一份 |
| 写事务提交 | Paxos 多数派确认,跨分区加两阶段提交 | 本地日志刷盘即返回 |
| 高可用 | 副本自动选主,RPO=0 | 主备切换或共享存储多活接管 |
| 扩展方式 | 加服务器即水平扩容 | 纵向升配为主,集群分担读压力 |
路线本身分不出高低,合不合适的事。但骨架差这么多,后面延迟和 SQL 的账,算法就完全是两码事了。
二、延迟:一条 COMMIT 要走多少路
拿条最普通的转账来看:
BEGIN;
UPDATE account SET balance = balance - 100 WHERE acct_no = '622200001';
UPDATE account SET balance = balance + 100 WHERE acct_no = '622200002';
COMMIT;
先看金仓。COMMIT 一到,两条变更日志(WAL)写本地盘,刷盘,回客户端一句"好了"。没有网络什么事。SSD 上这一步一般 1ms 都不到。
就这么点事。
主备要是配了同步复制呢?多等备库一跳,也就一跳。而且异步、同步、极致安全几个档随便挑,想拿多少延迟换多少安全,自己定。
换到 OB 上,同样的 COMMIT 就绕了。两条 UPDATE 各落在分区的 leader 上,日志要发给同分区另外两份副本,多数派(三份里的两份)确认落盘,事务才算提交。这一跳跨服务器,多数时候还跨机房。要是事务碰巧跨了分区(上面那例子俩账号的分区八成不在一起,太常见了),还得走两阶段提交,协调、准备、提交,网络又跑两趟。
肯定有人不服:同城机房往返也就零点几毫秒,单笔还是毫秒级,无感。
行,这话没错,OB 在银行核心跑得动是真的。但一笔业务逻辑往往是几十条短事务串出来的。每条差零点几毫秒,乘上事务数,乘上并发,高峰期一拉开就不是小数了。对账、清结算这种延迟敏感的活儿,这笔账建议真拿计算器按一按。
那到底差多少?看机房,看分区设计,看业务模型,没有通用数字。谁跟你拍胸脯报一个固定数,你反倒要留个心眼。
三、复杂 SQL
延迟是事务型的账。报表的账,得看 SQL 执行器。
我摆一条典型报表 SQL,三表关联、嵌套子查询、窗口函数全有:
-- 各区域近30天的客户消费榜:谁贡献了头部销售额
SELECT *
FROM (
SELECT r.region_name,
c.cust_name,
SUM(o.amount) AS total_amt,
ROW_NUMBER() OVER (PARTITION BY r.region_name
ORDER BY SUM(o.amount) DESC) AS rn
FROM orders o
JOIN customer c ON o.cust_id = c.cust_id
JOIN region r ON c.region_id = r.region_id
WHERE o.pay_time >= CURRENT_DATE - INTERVAL '30 day'
AND o.amount > (
SELECT AVG(amount) * 0.1 -- 滤掉零头小额订单
FROM orders
)
GROUP BY r.region_name, c.cust_name
) t
WHERE rn <= 20;
金仓跑这条,数据全在本地。优化器先改写,嵌套子查询提出来,一次算完,回头再比对。然后排计划:扫表走哪个索引?两步关联用 Hash Join 还是 Nest Loop?窗口函数按区域排?全在单机的内存和磁盘里转。整个计划从头翻到尾,找不出一步"把数据传给别的机器":
EXPLAIN ANALYZE <上面那条SQL>;
-- 计划形态(节选示意):
-- Subquery Scan / WindowAgg ← 窗口函数计算
-- Hash Join ← orders × customer
-- Hash Join ← 再 × region
-- Index Scan / Seq Scan
-- InitPlan ← 嵌套子查询,一次算完
OB 跑,先看分区键。orders、customer 分区策略对得上,join 本地做。对不上呢?现实里多数对不上。计划里就会冒出 EXCHANGE 算子,数据先在节点间重分布,再碰头。
窗口函数更头疼。PARTITION BY 的键跟数据分布对不上,同一个区域的行得先从各节点凑齐,才能排序。SQL 越复杂、表越多,数据在网上搬的次数越多。这个"网络税",交得肉疼。
| 对比维度 | OceanBase | 金仓数据库 KES |
|---|---|---|
| 数据位置 | 分区打散在多台服务器 | 全部在本机 |
| 多表关联 | 分区对齐可本地join,否则网络重分布 | 本地 Hash/Merge Join,无网络开销 |
| 窗口函数 | 分布键不齐需跨节点汇聚排序 | 单机排序计算,数据不动 |
| 嵌套子查询 | 优化器改写,叠加分布式代价模型 | 子查询提升改写,纯单机代价 |
| 并行执行 | 跨节点分布式并行 | 单机多核并行查询 |
当然,数据量真大到一台机器装不下,那没得挑。OB 几十台机器一起扫,单机追不上。但我接触的政企核心库,数据量大多停在几百 GB 到几个 TB 这档,单机 SSD 轻轻松松。这个量级还去交网络税,就有点冤了。
金仓单机内部也在挖潜。并行查询让大报表吃满多核,配置不复杂:
-- 并行查询总开关
SET enable_parallel_query = on;
-- 单个查询计划允许拉起的并行工作进程数
SET max_parallel_workers_per_gather = 4;
-- 全局并行工作进程池(kingbase.conf 里改,重启生效)
-- max_parallel_workers = 16
参数一开,大表扫描、关联、聚合的计划里就有 Gather 节点了,几个工作进程分头干,干完汇合。
官方给 V9R4C019 出过实测:带标量子查询加多表关联的复杂查询,100 并发下 TPS 提了大约 60%,平均响应时间压到原来的十分之一。官方测试嘛,条件你可以怀疑。但方向我觉得靠谱:集中式在复杂 SQL 上的余地,比很多人想的大。
四、资源和运维,两笔容易漏的账
对了,还有两笔账没算,选型表上看不见,账单上跑不掉。
一笔是资源。OB 三副本起步,一份数据实打实存三遍,生产至少三台服务器。官方给的单机规格建议也不低,内存还是预分配的。机器一到位,业务跑多跑少,大头先被吃掉。金仓主备两台起步,数据就一份,共享存储集群更是几个实例共用一份数据。同样承载数据量,机柜里的密度差不少。
另一笔是人力。OB 的 LSM-Tree 每天要做一次大合并,内存增量刷成新基线,合并窗口的资源波动得躲开业务高峰。你要是 DBA 团队就俩人,想想这个窗口怎么排班吧。排障也费劲,分区、副本、租户、合并,一整套概念都得懂,分布式 DBA 现在多紧俏,去招聘网站搜一圈就有数了。金仓就好办了,集中式那套运维心智 DBA 都熟,日常无非备份、清理、维护索引,培训便宜,招人也容易。工具链省事:迁移前 KDMS 做评估,迁移中 KFS 做增量同步。官方公开的运营商案例里,KFS 扛过日均 4.5TB 增量、秒级延迟,这个有实锤。
五、到底怎么选
直接给结论。
数据量单机装不下、并发要无限横着扩、多地多活是硬指标,OB 对症。多副本的开销买扩展性和容灾,值。
反过来说,数据量几个 TB 以内、事务短平快、报表 SQL 复杂、延迟敏感,预算人手又都紧,金仓更合身。没有共识的固有延迟,不用交数据搬运的网络税,两台机器就能高可用,DBA 拿过来就用。
一句话:规模没到就上分布式,等于提前交税;规模到了还死守单机,那是硬撑。先想明白自己站在哪个区间。
六、动手前几句实在话
先说第一条,别全信评测,我这篇也一样。拿自己真实的业务 SQL,两边各搭一套环境跑一遍,EXPLAIN 摊开看:金仓的索引走没走对、并行拉没拉起来;OB 的 EXCHANGE 多不多、重分布狠不狠。计划不会说谎,人才会。
还有,压测一定用真实流量分布。玩具数据压出来的结论,上线会被教做人。别问我怎么知道的。
最后,算总账。机器、存储、许可证、人力、培训,按三年一起算。延迟低零点几毫秒值多少钱?省两台服务器又值多少钱?业务方自己会算。
有时候我想,那天会上要是有人直接把两边的 EXPLAIN 摊出来,估计根本吵不了一下午。
OceanBaseVS金仓这道题没有标准答案,合不合你的业务,自己的 SQL 跑一遍就知道了。