从烟囱到融合:一次MongoDB迁移引发的架构重构深思
2026/8/8 2:08:05 网站建设 项目流程

文章目录

    • MongoDB原生协议兼容这个事,我得展开说说
    • 然后聊到迁移具体怎么搞
    • 性能这块,我得说实话
    • SQL操作文档数据这个能力,被严重低估了
    • 多集群架构这个事也值得聊聊
    • 关于融合数据库架构的一些碎碎念和文献思考
    • 回到那次迁移本身

兼容
是对前人努力的尊重
是确保业务平稳过渡的基石
然而
这仅仅是故事的起点

说真的,我一开始根本没打算写这篇东西。上个月帮一个老朋友搞MongoDB迁移,折腾了大半个月,过程中把KES的MongoDB兼容版翻来覆去用了好几遍,踩了不少坑也想明白了不少事。

MongoDB原生协议兼容这个事,我得展开说说

当时我也不太信这个"零代码修改"的说法,因为之前见过太多号称兼容实际上各种不兼容的案例。但翻完KES MongoDB兼容版的产品文档和一些社区帖子之后,发现它确实是走了一条比较硬核的路——不是在应用层做适配,而是在数据库协议层直接兼容。

啥意思呢?你的Java应用原来用MongoDB Java Driver连接MongoDB,现在只要把连接地址从MongoDB服务器改成KES服务器,端口设成27017(KES监听这个端口来接收MongoDB协议请求),其他啥都不用动。Driver发出的所有insertOne、find、update这些命令,KES都能识别和处理。

// 原来连MongoDBMongoClientclient=MongoClients.create("mongodb://user:pass@mongo-host:27017/mydb");// 迁移到KES,只改地址MongoClientclient=MongoClients.create("mongodb://system:123456@kes-host:27017/mydb");// 后续所有操作完全不变MongoCollection<Document>collection=client.getDatabase("mydb").getCollection("users");// 插入文档collection.insertOne(newDocument("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一样:

// 用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:newDate()})// 查询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实例,得指定兼容模式:

# 初始化KES,指定兼容模式# -m 参数指定兼容模式,具体模式值参考官方部署手册# -U 指定超级用户initdb-Usystem-D/data/kes_data

这里插一句,KES支持多种兼容模式,不同模式下语法习惯和默认行为有差异。MongoDB兼容功能是在内核层面实现的,通过加载插件来启用。

然后改配置文件 kingbase.conf,开启MongoDB协议兼容:

# 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兼容的核心组件,必须在启动时加载。

配置改完之后重启数据库,然后登录进去创建插件:

# 用ksql连接数据库ksql-Usystem-p54321mydb
-- 创建MongoDB兼容插件,cascade会自动安装依赖组件CREATEEXTENSION documentdbCASCADE;-- 给system用户设置密码,MongoDB客户端连接时需要ALTERUSERsystemWITHPASSWORD'123456';

执行完这一步,KES就处于MongoDB兼容模式了。此时你可以用任何MongoDB客户端工具来连接它,mongosh、MongoDB Compass、Navicat都行,选择MongoDB数据源直接连。

朋友问数据怎么搬。KES有配套的KDTS做存量数据迁移,图形化工具,配好源端MongoDB和目标端KES连接信息就行。数据量大或对停机时间有要求的话,还有KFS做实时增量同步,边搬边追增量,最后切换只需要很短停机窗口。

# KDTS命令行示例(具体参数根据版本调整)# 全量迁移kdts--modefull\--source"mongodb://source-host:27017"\--target"kingbase://kes-host:27017"\--databasemydb# 增量同步(不停机迁移用)kfs--modeincremental\--source"mongodb://source-host:27017"\--target"kingbase://kes-host:27017"\--databasemydb

不过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一个库里了:

-- users是关系表,orders是文档集合对应的表-- 用SQL直接做关联查询SELECTu.username,u.phone,o.order_infoFROMusers uJOINorders oONu.user_id=o.order_info->>'user_id'::intWHEREo.order_info->>'status'='pending'ANDu.register_time>='2026-01-01';-- 也可以直接用SQL插入文档数据INSERTINTOorders(order_info)VALUES('{"order_id": "ORD001", "customer": "张三", "amount": 299.0}');-- JSONB字段上的查询操作SELECTorder_info->>'customer'AScustomer_name,(order_info->>'amount')::numericASamountFROMordersWHEREorder_info @>'{"status": "completed"}'ORDERBYamountDESCLIMIT10;
// 同样的查询用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导致认证失败。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询