聊聊KingbaseES V9的MongoDB兼容版到底怎么个平替法最近一段时间我一直在帮几个项目做数据库层面的国产化替换工作。大家原来用MongoDB用得其实挺顺手的。存JSON文档结构灵活开发起来快。但是现在的情况是很多单位都有替换的要求。那换个什么呢这是个问题。如果直接换成某个独立的文档数据库往往又会面临安全认证过不去的情况。也就是在这个时候我看到了KES出的这个KingbaseES V9 MongoDB兼容版。今天这篇文章我就结合平时的实际经验还有他们发出来的产品资料跟大家仔细扒一扒这个东西到底是怎么实现的能不能直接用在我们的项目里。一、先搞清楚现在的多模数据处理到底遇到了什么麻烦其实很多时候我们并不是非要换数据库。老的架构用久了问题确实会慢慢冒出来。特别是当业务越来越复杂的时候。1.1 老架构的那些坑大家回想一下自己公司的系统架构。往往是这个业务线用一套MySQL那个业务线搞一个MongoDB旁边可能还放着一个Redis。这就形成了一个个独立的系统。大家管这个叫“烟囱式”架构。这种架构最大的问题是什么呢数据分散。你想要把关系数据和文档数据关联起来查一下非常麻烦。往往仅仅只是拉通两个库的数据就要写一堆同步脚本。数据对不上的情况经常发生。信息滞后不一致。接着就是开发周期变长。每接一个新需求可能就要引入新的技术栈。学习成本高不说后面运维的人也头疼。1.2 技术栈太多导致的问题技术栈一旦多起来最直接的感受就是人力成本变高了。招人的时候得会这个又会那个。系统间的交互协作成本也是直线上升。有时候重复建设重复投资的情况特别严重。每个库独立部署资源利用率其实很低。那么怎么解决这些问题呢思路其实很简单就是把能合并的东西合并到一起。二、KES V9整体架构是个啥情况为了解决上面说的这些麻烦KES V9这个版本里其实做了一个很大的调整。他们搞了一个一体化架构。我画了个简单的图大家看一眼。应用层基于MongoDB驱动的应用基于KES驱动的应用网络层协议层 端口27017/54321MongoDB-parserOracle-parserPGSQL-parser协议调度存储层文档数据关系数据向量数据 GIS数据等2.1 一体化架构的思路你看这个图里的结构。最上面是应用层。你可以用原来的MongoDB驱动连过来。也可以用KES自己的驱动连过来。到了网络层之后往下走就是协议层。这里它开了两个端口一个是27017这是MongoDB默认的端口。另一个是54321这是KES自己的端口。再往下看语法层这里放了各种解析器。有MongoDB-parser也有Oracle-parser、PGSQL-parser。这些解析器把不同的语法解析完之后统一交给协议调度去处理。最后落到存储层的时候不管是文档数据、关系数据还是向量数据全都放在一个库里面存着。2.2 MongoDB兼容版在这个架构里的位置那么这个MongoDB兼容版处在什么位置呢其实就是图里MongoDB-parser加上27017端口这一条路。它并不是单独起了一个新的数据库进程。而是直接在KES的实例里面加了一层协议的转换。这样做的好处是很明显的。你不需要再去维护一套独立的文档数据库了。技术栈直接收敛到了KES这一个产品上。对于企业层级里的应用来说管理起来轻松了很多。三、KES MongoDB兼容版的几个关键点我看资料的时候发现他们重点提了三个词。自主研发无风险、产品统一原生兼容、纵深防御更高安全。我给大家翻译成大白话。3.1 为什么不单独搞个文档库而是做兼容版现在有些厂商是单独拿一个开源的文档数据库去包装。但是这里面有个合规的风险。目前的安全名录里面其实没有单独的“缓存库”或者“文档库”这个品类去进行测试和认证。你用了这类产品后面验收的时候可能会扯皮。KES本身是拿到了最高安全认证的。它把文档处理做成内置能力那你就没有二次改造的风险了。再一个就是安全方面。原来用MongoDB安全防护措施往往仅仅只是做个权限控制。但是KES这边是从访问控制、身份鉴别到传输安全、存储安全再到事后的安全审计是一套完整的机制。这点在政企客户那里是非常看重的。3.2 原生协议到底是怎么兼容的这是我最关心的一点。它说支持MongoDB原生协议兼容支持零代码平替。底层到底是怎么搞的呢其实KES底层还是基于PostgreSQL内核做的。PostgreSQL本身就有很强的自定义类型能力。KES就是利用了这一点。它在底层建了一种类型来存BSON数据。我们来看一段MongoDB的插入操作代码。db.products.insertMany([...{item:card, qty:15},...{item:envelope, qty:20},...{item:stamps, qty:30}...]);你在客户端敲下这段代码通过27017端口发出去。KES接收到之后它会把MongoDB的数据转为关系表的数据。也就是说你在MongoDB里看到的collection在KES底层其实就是一张表。文档就是表里的一行。那个_id字段比如{ $oid : 6840285d64289defb9c1c18c }会自动创建一个B-TREE索引。如果你执行db.products.createIndex({item:1})它底层其实是给item字段建了一个RUM索引。这样处理的话应用层只需要改一下连接串的IP和端口。代码“零”修改。这就是它说的全栈兼容的文档数据库平替。四、具体能用到哪些命令和操作符光说原理不行平时干活靠的是具体的命令。我对照着资料里的清单给大家捋一捋。4.1 常用的CRUD和统计操作大家平时用的最多的就是增删改查。从资料里的对比表来看这些接口KES全支持。比如插入数据db.collection.insertOne和db.collection.insertMany都是支持的。查询文档的话db.collection.find和db.collection.findOne也没问题。更新和删除的那些updateOne、deleteMany之类的全都有。统计操作也是一样。db.collection.count、db.collection.distinct、db.collection.dataSize这些平时用来查状态、算数量的命令也都支持。4.2 查询、更新操作符的支持情况操作符不是单独的命令。它是写在查询条件里的。这个支持度怎么样呢我拉了几个常用的看看。对比查询操作符有32个KES支持了31个支持率96.88%。像$eq、$gt、$in、$lt这些对比的全支持。逻辑操作符$and、$or、$not、$nor全支持。元素判断的$exists、$type也支持。求值的$mod、$regex、$expr、$jsonSchema同样支持。再看看更新操作符。这个是22个全支持100%。什么$set改字段值$inc加数字$min、$max取极值$unset删字段。数组操作的那些$push、$pull、$addToSet、$pop也全都有。投影操作符3个100%支持。比如$slice限制返回数组元素的数量这个很常用。4.3 聚合管道的支持度聚合管道这块稍微复杂一点。命令支持率是100%。聚合管道阶段有38个支持了32个支持率84.21%。聚合管道操作符有169个支持了167个支持率98.82%。也就是说你平时写的大部分聚合查询直接拿过来跑是没问题的。比如$group、$match、$project这些阶段以及里面的$sum、$avg这些操作符。那么有哪些是不支持的呢比如“查询计划缓存”相关的4个命令支持率是0%。“角色管理”相关的10个命令在MongoDB兼容接口这里也是0%。但是注意了资料里也说了KES本身是带角色管理功能的。只是它没有去兼容MongoDB那套角色管理的命令语法。你可以通过KES自己的管理工具去建角色。这个其实无伤大雅。五、性能到底差多少大家肯定要问套了一层壳性能会不会拉胯资料里给了一组实测数据我直接贴出来大家自己看。5.1 1万条数据量的情况数据库数据量INSERT(ms)全表数据UPDATE(ms)全表数据SELECT(ms)全表数据SELECT(ms)全表单个字段SELECT(ms)标量查询SELECT(ms)范围查询MongoDB1万条数据10035241044kingbaseES with nativeAPI1万条数据1445238206115.2 10万条数据量的情况数据库数据量INSERT(ms)全表数据UPDATE(ms)全表数据SELECT(ms)全表数据SELECT(ms)全表单个字段SELECT(ms)标量查询SELECT(ms)范围查询MongoDB10万条数据39532878632728kingbaseES with nativeAPI10万条数据47354318615940495.3 100万条数据量的情况数据库数据量INSERT(ms)全表数据UPDATE(ms)全表数据SELECT(ms)全表数据SELECT(ms)全表单个字段SELECT(ms)标量查询SELECT(ms)范围查询MongoDB100万条数据227530832087365174228kingbaseES with nativeAPI100万条数据34986413332013322705585.4 怎么看待这个性能差距看完这三张表结论很明显。KES的MongoDB兼容版在性能上跟原生的MongoDB比确实是有差距的。数据量越大差距越明显。比如在100万条数据的时候全表UPDATE的操作MongoDB是3083毫秒KES是6413毫秒差了一倍左右。标量查询也差了大概三四倍。那这个情况能接受吗我觉得要分场景看。如果你的业务是那种极高并发的、纯缓存性质的读写可能确实会有压力。但是对于一般的企业层级里的应用来说大部分表的数据量可能也就停留在十万级以内。在这个量级下比如10万条数据标量查询差了十几毫秒范围查询差了二十毫秒。这个延迟在业务层面往往是感知不到的。而且你要想到你换来的是什么呢换来的是不用维护两套数据库。换来的是通过了安全认证。换来的是可以在同一个库里用SQL直接关联你的文档数据和关系数据。这个账不同项目得自己算。六、真要从MongoDB迁过来要怎么做如果评估下来觉得可以搞那下一步就是怎么迁了。这里不涉及数据迁移工具的讨论单纯看怎么把KES实例配成一个能接MongoDB请求的状态。步骤其实不多但是每一步都很关键。6.1 初始化实例的时候要注意什么第一步是初始化数据库。这里有一个坑要注意。执行initdb的时候必须加上-m参数指定为兼容pg模式。同时还要指定默认用户一般是-U system。如果不加这个参数后面再想改就麻烦了。6.2 改配置项的那些事初始化完之后就要去改配置文件了。配置文件是kingbase.conf。你需要改下面这几个参数。enable_protocol_compatonextension_protocol_port27017documentdb_core.bsonUseEJsonon我解释一下这几个参数是干嘛的。enable_protocol_compaton这个一看就知道是把协议兼容的功能打开。extension_protocol_port27017这是指定兼容协议监听的端口。MongoDB默认就是27017你写这个的话应用那边基本就不用改连接端口了。documentdb_core.bsonUseEJsonon这个是让BSON类型使用扩展JSON的格式。因为底层的PG对JSON处理有自己的方式开这个能保证数据解析不出错。除了这三个还有一个很重要的。就是在shared_preload_libraries这一项的后面要追加三个东西。kdb_cron,kdb_documentdb_core,kdb_documentdb这是预加载的动态库。你必须把这三个写进去数据库在启动的时候才会把MongoDB兼容的核心组件加载到内存里。改完这些重启数据库服务。6.3 建插件和连上去的步骤重启完之后就可以进数据库里建插件了。你用ksql工具连上去连的是54321那个原生端口。ksql –Usystem-p54321dbname进去之后执行建插件的命令。create extension documentdb cascade;这里有个cascade参数。意思是把它依赖的那些插件也一起建了。省得你一个一个去建。接着你要给system用户设个密码。因为MongoDB连接的时候需要认证。alter user system with password123456;做完这些KingbaseES数据库就处于兼容mongodb模式了。这个时候你拿出mongosh客户端直接连就行。连接串是这样的。mongoshmongodb://system:123456127.0.0.1:27017/dbname?maxPoolSize1directConnectiontrueauthMechanismSCRAM-SHA-256你看这个连接串IP是127.0.0.1端口是27017认证机制是SCRAM-SHA-256。这跟连一个真正的MongoDB没有任何区别。你连上之后敲db.collection.find()就能把刚才建的表里的数据查出来。总结其实写到这里大家应该对KES V9的MongoDB兼容版有个清晰的认识了。它不是一个重新造轮子的文档数据库。它是站在KES成熟的关系型数据库底座上通过协议解析转换硬生生抠出来的一套MongoDB兼容层。这种做法的好处是稳。因为底层的存储、事务、备份恢复全都是KES原来那套经过多年验证的东西。你不用去担心一个新的文档库在数据可靠性上出什么幺蛾子。缺点也有。就是性能上面毕竟多了一层转换跟原生的比肯定有损耗。聚合管道和一些偏门的管理命令也没有做到100%覆盖。但是回到我们最开始说的那个问题。很多项目现在要的是合规要的是减少技术栈要的是能过验收。在这个前提下KES的MongoDB兼容版提供了一条非常直接的路径。你改个连接串把应用跑起来测试通过这就完事了。对于一线干活的兄弟们来说这其实就是一个很实在的平替方案。大家如果在项目里也遇到类似的需求不妨拿个测试环境搭一下跑跑看毕竟实践出真知嘛。