文章目录

兼容 是对前人努力的尊重 是确保业务平稳过渡的基石 然而 这仅仅是故事的起点
说真的,我一开始根本没打算写这篇东西。上个月帮一个老朋友搞MongoDB迁移,折腾了大半个月,过程中把KES的MongoDB兼容版翻来覆去用了好几遍,踩了不少坑也想明白了不少事。
MongoDB原生协议兼容这个事,我得展开说说
当时我也不太信这个"零代码修改"的说法,因为之前见过太多号称兼容实际上各种不兼容的案例。但翻完KES MongoDB兼容版的产品文档和一些社区帖子之后,发现它确实是走了一条比较硬核的路------不是在应用层做适配,而是在数据库协议层直接兼容。
啥意思呢?你的Java应用原来用MongoDB Java Driver连接MongoDB,现在只要把连接地址从MongoDB服务器改成KES服务器,端口设成27017(KES监听这个端口来接收MongoDB协议请求),其他啥都不用动。Driver发出的所有insertOne、find、update这些命令,KES都能识别和处理。
java
// 原来连MongoDB
MongoClient client = MongoClients.create(
"mongodb://user:pass@mongo-host:27017/mydb"
);
// 迁移到KES,只改地址
MongoClient client = MongoClients.create(
"mongodb://system:123456@kes-host:27017/mydb"
);
// 后续所有操作完全不变
MongoCollection<Document> collection =
client.getDatabase("mydb").getCollection("users");
// 插入文档
collection.insertOne(new Document("name", "张三")
.append("age", 28)
.append("tags", Arrays.asList("vip", "active")));
// 查询
FindIterable<Document> results = collection.find(
Filters.eq("age", 28)
);
看到没?就是改个连接字符串的事。Spring Data MongoDB、PyMongo这些主流框架也都能直接用,因为KES兼容的是MongoDB Wire Protocol,而不是简单做了个API翻译层。
我当时跟朋友说,你可以先用 mongosh 连上去试试,感觉就跟连了个真的MongoDB一样:
javascript
// 用mongosh连接KES的MongoDB兼容端口
mongosh "mongodb://system:123456@127.0.0.1:27017/mydb?directConnection=true&authMechanism=SCRAM-SHA-256"
// 创建集合
db.createCollection("orders")
// 插入文档
db.orders.insertOne({
order_id: "ORD20260801001",
customer: {
name: "李四",
phone: "138xxxx0001"
},
items: [
{sku: "SKU001", qty: 2, price: 99.9},
{sku: "SKU002", qty: 1, price: 199.0}
],
status: "pending",
created_at: new Date()
})
// 查询
db.orders.find({"customer.name": "李四"})
// 聚合查询,统计每个客户的订单数
db.orders.aggregate([
{$group: {_id: "$customer.name", orderCount: {$sum: 1}}},
{$sort: {orderCount: -1}}
])
朋友试了之后说"卧槽真的能用",说实话我也挺惊讶的。因为KES对MongoDB常用命令的支持率非常高,查询和写入类命令100%覆盖,更新操作符100%覆盖,聚合管道操作符98.82%。只有一些不太常用的管理类命令(比如角色管理那块)没完全兼容,但KES本身有自己的一套权限管理机制,可以通过KES的管理工具来做。
然后聊到迁移具体怎么搞
零代码修改是应用层的事,但数据库本身的迁移还是得做点工作的。我把KES文档里提到的步骤捋了一遍,大致是这么个流程。
首先是初始化KES实例,得指定兼容模式:
bash
# 初始化KES,指定兼容模式
# -m 参数指定兼容模式,具体模式值参考官方部署手册
# -U 指定超级用户
initdb -U system -D /data/kes_data
这里插一句,KES支持多种兼容模式,不同模式下语法习惯和默认行为有差异。MongoDB兼容功能是在内核层面实现的,通过加载插件来启用。
然后改配置文件 kingbase.conf,开启MongoDB协议兼容:
ini
# kingbase.conf 中添加或修改以下参数
# 开启协议兼容
enable_protocol_compat = on
# MongoDB兼容监听端口,默认就用27017
extension_protocol_port = 27017
# BSON格式使用EJSON
documentdb_core.bsonUseEJson = on
# 在shared_preload_libraries中追加以下三个模块
shared_preload_libraries = 'kdb_cron, kdb_documentdb_core, kdb_documentdb'
这几个参数逐个说下。enable_protocol_compat是总开关,打开后KES才能处理非SQL协议连接。extension_protocol_port指定MongoDB协议监听端口,设27017是为了跟原生MongoDB一致,迁移时连接串只改IP就行。bsonUseEJson控制BSON序列化方式,建议开启。shared_preload_libraries里那两个模块是KES实现MongoDB兼容的核心组件,必须在启动时加载。
配置改完之后重启数据库,然后登录进去创建插件:
bash
# 用ksql连接数据库
ksql -U system -p 54321 mydb
sql
-- 创建MongoDB兼容插件,cascade会自动安装依赖组件
CREATE EXTENSION documentdb CASCADE;
-- 给system用户设置密码,MongoDB客户端连接时需要
ALTER USER system WITH PASSWORD '123456';
执行完这一步,KES就处于MongoDB兼容模式了。此时你可以用任何MongoDB客户端工具来连接它,mongosh、MongoDB Compass、Navicat都行,选择MongoDB数据源直接连。
朋友问数据怎么搬。KES有配套的KDTS做存量数据迁移,图形化工具,配好源端MongoDB和目标端KES连接信息就行。数据量大或对停机时间有要求的话,还有KFS做实时增量同步,边搬边追增量,最后切换只需要很短停机窗口。
bash
# KDTS命令行示例(具体参数根据版本调整)
# 全量迁移
kdts --mode full \
--source "mongodb://source-host:27017" \
--target "kingbase://kes-host:27017" \
--database mydb
# 增量同步(不停机迁移用)
kfs --mode incremental \
--source "mongodb://source-host:27017" \
--target "kingbase://kes-host:27017" \
--database mydb
不过KDTS和KFS具体用法还是得看官方部署手册,我这里只给个概念。
性能这块,我得说实话
我知道很多人关心迁移完性能会怎样。老实说,KES在纯文档操作的性能上跟原生MongoDB比是有差距的。从产品文档里给的测试数据来看,1万条数据规模下,INSERT操作KES是144毫秒,MongoDB是100毫秒;10万条数据时,KES的UPDATE是543毫秒,MongoDB是328毫秒。到了百万级数据,差距更明显一些,UPDATE操作KES 6413毫秒,MongoDB 3083毫秒。
数据量:1万条
操作 MongoDB KES
INSERT 100ms 144ms
UPDATE 35ms 52ms
SELECT(全表) 24ms 38ms
SELECT(标量) 4ms 6ms
数据量:100万条
操作 MongoDB KES
INSERT 2275ms 3498ms
UPDATE 3083ms 6413ms
SELECT(全表) 2087ms 3320ms
SELECT(标量) 174ms 270ms
差距是客观存在的。但这里面有个核心问题------你是拿KES跟MongoDB单独比文档操作性能,可KES的真正价值在于融合。三套系统的总成本------硬件、授权费、运维人力、数据同步开销------跟一套KES比,哪个高?我朋友算过一笔账,光运维人力一年省两个人就够覆盖性能差距带来的硬件投入了。
再说安全这块,MongoDB默认认证弱、传输加密要手动配、没有透明数据加密、审计得靠第三方插件。信创和等保2.0背景下这些是硬伤。KES有细粒度RBAC、国密SM2/SM3双向认证、SSL/TLS、TDE透明数据加密、内建审计,这套纵深防御体系是MongoDB给不了的。
还有一点,KES的文档操作性能虽然慢一些但完全够用。标量查询百万级数据270毫秒,对绝大多数业务可接受。而且KES还有SQL接口操作文档数据,有些复杂分析用SQL写比MongoDB聚合管道方便太多。
SQL操作文档数据这个能力,被严重低估了
说到SQL操作文档数据,我觉得这个功能被很多人忽略了。KES除了支持MongoDB原生协议访问文档数据之外,还支持直接用SQL来查。这意味着什么?意味着你可以在一个SQL语句里同时操作关系型数据和文档数据。
举个例子,你有个用户表(关系型)和一个订单集合(文档型),原来分属MySQL和MongoDB两个库,想要关联查询得写ETL先同步数据再跑分析。现在都在KES一个库里了:
sql
-- users是关系表,orders是文档集合对应的表
-- 用SQL直接做关联查询
SELECT u.username, u.phone, o.order_info
FROM users u
JOIN orders o ON u.user_id = o.order_info->>'user_id'::int
WHERE o.order_info->>'status' = 'pending'
AND u.register_time >= '2026-01-01';
-- 也可以直接用SQL插入文档数据
INSERT INTO orders (order_info)
VALUES ('{"order_id": "ORD001", "customer": "张三", "amount": 299.0}');
-- JSONB字段上的查询操作
SELECT order_info->>'customer' AS customer_name,
(order_info->>'amount')::numeric AS amount
FROM orders
WHERE order_info @> '{"status": "completed"}'
ORDER BY amount DESC
LIMIT 10;
javascript
// 同样的查询用MongoDB语法也能做
db.orders.find(
{"status": "completed"}
).sort({"amount": -1}).limit(10)
你看,同一份数据,你可以用MongoDB驱动访问也可以用SQL访问,取决于你的场景需要。开发新功能的时候用SQL多方便啊,JDBC直接连上就能写,不用学MongoDB的查询语法。老代码不动,继续用MongoDB驱动跑。这种灵活性是真的香。
你团队里那些只会写SQL的后端,以前碰MongoDB的数据就抓瞎,现在一条SQL就能搞定跨数据模型的关联查询。
多集群架构这个事也值得聊聊
KES的融合架构里还有一个概念叫"集中分布一体化",说白了就是它支持多种部署模式------单机、主备、分布式集群,可以根据你的可用性需求和成本预算来选。
朋友原来MongoDB用Replica Set三节点,MySQL主从一备,Redis三主三从cluster。三套高可用方案、三套故障切换逻辑,出故障时排障顺序都能搞晕人。
KES的多集群架构思路是:同一套数据库,先单机做开发测试,再切主备上生产,业务量上来扩到分布式集群。底层的数据模型和SQL语法都不变,只是部署形态变了。
单机模式:开发测试用
↓
主备模式:小规模生产,满足基本高可用
↓
分布式集群:大规模生产,水平扩展+高可用
而且KES分布式集群用MPP架构,数据分片存在不同节点上,查询时各节点并行处理。后面要做跨业务数据分析,不需要额外搭数据仓库,直接在KES上跑就行。
朋友听完这些之后说了一句话让我印象很深,他说"早知道有这种融合方案,我当初就不该搞那么多套数据库了"。说实话我也是这种感觉,很多时候技术选型上的"分别部署"不是有意为之,而是业务发展过程中一步步加出来的,等问题积累了才发现收不了场。
关于融合数据库架构的一些碎碎念和文献思考
聊到这块我想多说几句。数据库融合架构这个概念,其实不是KES首创的,但不同厂商走的技术路线差异很大,理解这些差异对你做技术选型挺重要的。
你去看早期做多模数据库的尝试,大概2015年前后吧,当时业界讨论的热点是"NewSQL能不能取代NoSQL"。一批人认为关系型数据库通过扩展JSON类型就能覆盖文档数据库的场景,另一批人觉得NoSQL的灵活schema和水平扩展能力是关系型数据库无法替代的。这个争论持续了好几年,最后的结果是两边都没完全取代对方,反而催生了一种新的思路------在关系型内核上原生支持多种数据模型。
不过我也得说句公道话,KES的多模融合方案目前也不是完全没有短板。比如在超大规模向量检索场景下(十亿级以上向量),专业向量数据库的检索性能还是更有优势的。再比如文档模型那边,一些MongoDB的高级特性像查询计划缓存、角色管理命令这些还没完全兼容。这些gap是否影响你的业务,得自己评估。
我个人觉得,融合数据库架构这条路方向是对的。与其追求单一场景的极致性能然后忍受多系统的运维痛苦,不如在"够用"的性能水平上把技术栈收敛了。尤其对于信创背景下的国产化替代来说,你本来就要换数据库了,与其一个MongoDB换成另一个MongoDB、一个MySQL换成另一个MySQL,不如一步到位选个能融合的,把长期的技术债一起清了。
回到那次迁移本身
最后说说我朋友那边的结果吧。经过大半个月的折腾,最终方案是核心交易数据保持在KES的关系型存储里,MongoDB里的用户画像和商品动态数据迁移到了KES的文档存储,Redis缓存暂时保留但后续也计划迁移到KES(KES本身也有缓存能力)。GIS相关的业务直接用了KES内置的KGIS组件。
迁移之后最直观的感受是数据一致性问题彻底解决了。因为所有数据都在一个库里,跨表事务由ACID保证,再也不用依赖ETL和补偿逻辑了。运维那边反馈说监控面板从一个铺满四个屏幕的大屏变成了一块屏,看监控的时候终于不用来回转头了(这是原话,我笑了半天)。
应用代码那边,MongoDB相关的代码几乎没改,就是连接字符串换了一下。倒是有些原来用ETL做跨库分析的任务,现在直接改成了SQL关联查询,代码量少了一大截。朋友说光把ETL相关的代码删掉就删了两千多行,删的时候特别爽。
当然了过程中也有踩坑的地方。比如MongoDB的一些聚合管道操作符KES虽然支持但行为细节有差异,$lookup在处理大数据量的时候内存占用比原生MongoDB高一些,需要调整work_mem参数。还有mongosh连接的时候认证机制要指定SCRAM-SHA-256,不指定的话有些版本会默认用SCRAM-SHA-1导致认证失败。