- 后端
- 数据库
- 文档数据库
【免费下载链接】FerretDB
A truly Open Source MongoDB alternative
本文是一份以 FerretDB 仓库官方迁移指南为主体的实战手册,系统讲解从 MongoDB(或其他兼容系统)迁移到 FerretDB 的完整流程:从迁移动机评估、预迁移测试(四种操作模式)、生产环境搭建,到使用 MongoDB 原生工具mongodump/mongorestore与mongoexport/mongoimport完成数据备份与恢复。读完本文,你将掌握一套可复制、可验证的迁移方案,并了解底层操作模式与认证机制的实现原理。
为什么迁移到 FerretDB
越来越多的团队倾向使用开源软件,因为它可以避免供应商锁定并降低成本。但迁移本身的复杂度和成本同样值得评估——好消息是,借助 FerretDB,从 MongoDB 兼容数据库迁移过来相对容易。
迁移动机通常有以下几类:
- 参与开源、影响项目方向:FerretDB 是开源项目,你可以贡献代码、提交 bug 报告或请求新功能;
- 摆脱供应商锁定:开源文档数据库不受单一商业厂商约束;
- 降低成本:基于 PostgreSQL 生态的架构可以复用已有的数据库运维经验与基础设施。
无论出于何种原因,重要的是先明确迁移动机,并确认 FerretDB 确实适合你的使用场景。FerretDB 是 MongoDB 的良好替代品,但并非所有场景都适用——这正是迁移前需要充分评估的原因。
迁移最佳实践
明确迁移原因
在动手迁移前,先回答"为什么迁移"。明确的原因有助于设定迁移成功标准,也便于后续与 FerretDB 团队沟通需求。
规划迁移流程
迁移不宜仓促,需要仔细规划与执行。官方建议:
- 先在测试环境中让 FerretDB 与你的应用共同运行一段时间,再迁移生产数据;
- 利用这段时间暴露潜在的迁移问题;
- 用真实业务流量测试应用与 FerretDB 的兼容性,确认应用按预期工作。
关于如何开展测试环境验证,可以参考仓库中的 预迁移测试文档。
评估现有 MongoDB 环境与 FerretDB 的契合度
FerretDB 并不支持 MongoDB 的全部功能,因此迁移前必须核对你的应用所依赖的特性是否被支持。仓库中的 兼容性清单 逐条列出了各命令的现状(✅ 已支持 / ⚠️ 有限支持 / ❌ 未实现),例如:
- 查询类命令
find、insert、update、delete、findAndModify、getMore、aggregate、count、distinct均已支持; - 用户管理命令
createUser、dropUser、updateUser、usersInfo均已支持; - 而
bulkWrite、cloneCollectionAsCapped、convertToCapped、setParameter等尚未实现。
如果发现你依赖的功能缺失,这正是与 FerretDB 团队沟通的起点,便于提前寻找解决方案。此外,FerretDB 在部分使用细节上与 MongoDB 存在已知差异(如错误消息文本可能不同、集合名必须是合法 UTF-8),这些差异同样记录在 兼容性清单 中。
备份数据
无论迁移到哪个数据库,备份永远是第一步。完整、可验证的备份确保迁移过程中一旦出错,你可以随时回退到原有环境。
与 FerretDB 团队沟通
虽然不是必须,但在有疑虑时提前与 FerretDB 团队沟通需求,可以获得针对性的支持。FerretDB 有活跃的社区,也可以借助其他用户的迁移经验。
理解四种操作模式:预迁移测试的基石
预迁移测试之所以可行,核心在于 FerretDB 提供的操作模式(operation modes)。根据 操作模式文档,这些模式指定了 FerretDB 如何处理传入请求,可用于测试、调试和 bug 报告。
模式通过--mode标志或FERRETDB_MODE环境变量指定,可取值如下四种:
| 模式 | 行为 |
|---|---|
normal | 默认模式。所有客户端请求仅由 FerretDB 处理并返回给客户端 |
proxy | 所有请求转发给代理(另一个 MongoDB 兼容数据库)并返回其响应 |
diff-normal | 同时向 FerretDB 与代理转发请求并记录差异,只把 FerretDB 的响应返回给客户端 |
diff-proxy | 同时向 FerretDB 与代理转发请求并记录差异,只把代理的响应返回给客户端 |
从源码可以印证这四种模式的定义,见 internal/handler/middleware/mode.go:NormalMode只处理请求,ProxyMode只把请求代理给另一个兼容服务,DiffNormalMode既处理又代理并记录差异(只返回 FerretDB 响应),DiffProxyMode与之类似但只返回代理响应。
其中diff系列模式的价值在于:让 FerretDB 与一个 MongoDB 实例并行处理相同请求,然后逐字节对比两者的响应头与响应体,从而精确定位行为差异。
用diff-normal模式做手动/自动化测试
假设你的应用执行某个复杂查询或操作,希望验证 FerretDB 是否能正确处理:
以
diff-normal模式启动 FerretDB(默认即为normal模式,见 配置标志文档):ferretdb --mode=diff-normal \ --proxy-addr=<mongodb-URI> \ --listen-addr=<ferretdb-listen-address> \ --postgresql-url=<postgres-connection>--proxy-addr(或FERRETDB_PROXY_ADDR)指向你的 MongoDB 实例地址;--listen-addr(或FERRETDB_LISTEN_ADDR)默认是127.0.0.1:27017;--postgresql-url(或FERRETDB_POSTGRESQL_URL)默认是postgres://127.0.0.1:5432/postgres。
用
mongosh连接--listen-addr指定的地址并插入测试文档:db.locations.insertMany([ { postId: '1', position: { type: 'Point', coordinates: [-73.97, 40.77] } }, { postId: '2', position: { type: 'Point', coordinates: [-74.0, 40.75] } }, { postId: '3', position: { type: 'Point', coordinates: [-73.95, 40.78] } }, { postId: '4', position: { type: 'Point', coordinates: [-73.93, 40.76] } } ])执行命令检查集合占用的存储空间:
db.runCommand({ dataSize: '<DB-NAME>.locations' })在
diff-normal模式下,FerretDB 返回的任何错误都会直接传给客户端,便于即时发现问题。例如在功能未实现时会得到如下错误:MongoServerError[NotImplemented]: "dataSize" is not implemented for FerretDB yet需要注意:这是早期版本的示例。根据当前仓库的 兼容性清单,
dataSize命令现已标记为 ✅ 已支持,但其作为"diff 模式如何暴露未实现功能"的工作流示范依然有效——凡是列表中标 ❌ 的命令,都可以用同样的方式在测试环境中验证。
用diff-proxy模式深入检查差异输出
继续上面的例子,改用diff-proxy模式后,同样的请求会由 MongoDB(代理)处理并返回正常结果:
{ size: Long('424'), numObjects: Long('4'), millis: Long('1'), estimate: false, ok: 1 }而 diff 输出则清晰展示了 FerretDB 响应与代理响应之间的差异:
--- res header +++ proxy header @@ -1 +1 @@ -length: 133, id: 3, response_to: 28, opcode: OP_MSG +length: 99, id: 37, response_to: 28, opcode: OP_MSG Body diff: --- res body +++ proxy body @@ -7,6 +7,7 @@ "Document": { - "ok": 0.0, - "errmsg": "\"dataSize\" is not implemented for FerretDB yet", - "code": 238, - "codeName": "NotImplemented", + "size": int64(424), + "numObjects": int64(4), + "millis": int64(0), + "estimate": false, + "ok": 1.0, },通过这份 diff,可以精确判断哪些命令在 FerretDB 中尚未实现,为后续决策(规避、降级或向团队反馈)提供依据。
利用响应指标快速盘点
在开发构建版本(development build)中,FerretDB 退出时会把指标写入标准输出(stdout),用于快速统计应用发出的各类命令及其处理结果。例如下面这组指标表明dataSize命令被调用过一次,结果为NotImplemented:
# HELP ferretdb_client_requests_total Total number of requests. # TYPE ferretdb_client_requests_total counter ferretdb_client_requests_total{command="aggregate",opcode="OP_MSG"} 1 ferretdb_client_requests_total{command="dataSize",opcode="OP_MSG"} 1 ferretdb_client_requests_total{command="insert",opcode="OP_MSG"} 1 ... # HELP ferretdb_client_responses_total Total number of responses. # TYPE ferretdb_client_responses_total counter ferretdb_client_responses_total{argument="unknown",command="dataSize",opcode="OP_MSG",result="NotImplemented"} 1 ferretdb_client_responses_total{argument="unknown",command="insert",opcode="OP_MSG",result="ok"} 1这种"以指标代替人工核对"的方式非常适合在预迁移测试阶段快速找出不兼容的命令。
其他辅助工具
FerretDB 还提供了 Amazon DocumentDB 兼容性工具的 fork,用于扫描代码文件、识别其中使用了 FerretDB 不支持操作符的查询。需要说明的是,该工具精度有限:它不解析带上下文信息的查询语法,无法区分操作符出现在find还是aggregate命令中;并且只要某操作符并非在所有命令中都受支持就会被标记,可能产生误报。用法如下:
git clone <FerretDB 的 amazon-documentdb-tools 仓库> && cd amazon-documentdb-tools/compat-tool python3 compat.py --directory=/path/to/myapp --version=FerretDB迁移数据实战:前提条件与工具链
预迁移测试通过后,就可以开始正式迁移。根据 官方迁移指南,迁移前你需要准备:
- 现有 MongoDB(或兼容系统)的连接 URI;
- FerretDB 的连接 URI;
- MongoDB 原生工具:
mongodump/mongorestore、mongoexport/mongoimport。
由于 FerretDB 定位为 MongoDB 的开源替代品,兼容 MongoDB 5.0+ 的驱动与应用,因此这些原生工具可以直接对接。
第一步:搭建 FerretDB 环境
FerretDB 以 PostgreSQL 作为数据库后端,因此可以运行在任何支持 PostgreSQL 的环境:本机、Docker 容器或云上皆可。仓库中的 Docker 安装文档 给出了一份可直接使用的docker-compose.yml:
services: postgres: image: ghcr.io/ferretdb/postgres-documentdb:17-0.108.0-ferretdb-2.8.0 restart: on-failure environment: - POSTGRES_USER=username - POSTGRES_PASSWORD=password - POSTGRES_DB=postgres volumes: - ./data:/var/lib/postgresql/data ferretdb: image: ghcr.io/ferretdb/ferretdb:2.8.0 restart: on-failure ports: - 27017:27017 environment: - FERRETDB_POSTGRESQL_URL=postgres://username:password@postgres:5432/postgres networks: default: name: ferretdbpostgres容器运行预打包的、带 DocumentDB 扩展的 PostgreSQL,数据存放在宿主机的./data目录;ferretdb容器运行 FerretDB,通过FERRETDB_POSTGRESQL_URL连接 PostgreSQL。
启动后执行docker compose up -d,然后用mongosh连接(URI 形如mongodb://username:password@127.0.0.1/)即可。仓库中 Docker 安装文档 还建议始终指定完整镜像标签(如2.8.0)以保证部署一致性,并在升级 FerretDB 前先升级到配套的 DocumentDB 镜像版本。
第二步:使用mongodump/mongorestore迁移
备份全部数据,假设 MongoDB 实例连接 URI 为mongodb://127.0.0.1:27017:
mongodump --uri="mongodb://127.0.0.1:27017"成功后会生成包含所有集合 BSON 文件的数据转储(dump)。迁移数据时务必指定必要的认证凭据,保证传输安全。若只想迁移某个数据库或集合,把库名/集合名追加到 URI 上即可。例如只转储maindb数据库中的testcoll集合:
mongodump --uri="mongodb://127.0.0.1:27017/" --nsInclude=maindb.testcoll提示:如果连接串中已包含数据库名,则无需再为备份或恢复过程单独指定数据库名(参见 官方迁移指南)。
将转储数据恢复到 FerretDB 实例,指定 FerretDB 连接串(包含认证参数):
mongorestore --uri="mongodb://127.0.0.1:27017/ferretdb?authMechanism=PLAIN"恢复特定数据库与集合:
mongorestore --uri="mongodb://username:password@127.0.0.1:27018/?authMechanism=PLAIN" --nsInclude=maindb.testcoll关于认证机制的重要说明:上述示例中的authMechanism=PLAIN出自 2023 年发布的迁移指南,适用于当时的 FerretDB 版本。当前仓库已演进到 v2 架构,根据 认证文档,客户端目前仅支持SCRAM-SHA-256认证机制,连接串通常直接采用mongodb://username:password@127.0.0.1:27017/形式(仓库的集成测试也验证了SCRAM-SHA-256机制,见 integration/auth/create_user_test.go)。因此请以你所部署的 FerretDB 版本对应的认证方式为准:使用当前版本时,直接使用用户名密码形式的 URI 即可,无需追加authMechanism=PLAIN。
第三步:使用mongoexport/mongoimport迁移
与mongodump/mongorestore类似,也可以用mongoexport/mongoimport迁移数据。区别在于:mongoexport没有一次性导出全部集合的直接方式,需要为每个集合分别指定连接串、数据库、集合名与导出目录。
导出maindb数据库的testcoll集合到 JSON 文件:
mongoexport --uri="mongodb://127.0.0.1:27017/" --db=maindb --collection=testcoll --out=testcoll.json将导出的 JSON 文件导入 FerretDB:
mongoimport --uri="mongodb://username:password@127.0.0.1:27018/?authMechanism=PLAIN" --db=maindb --collection=testcoll --file=testcoll.json(同样,当前版本请使用mongodb://username:password@host:port/形式的 SCRAM-SHA-256 认证连接串。)
认证与连接串:迁移中的常见坑
迁移过程中最容易踩坑的是认证配置。根据 认证文档,FerretDB 自身不存储任何认证信息(用户名与密码),而是完全依赖 PostgreSQL 的认证机制,所有用户凭据都由 PostgreSQL 管理与校验:
- 客户端把凭据发给 FerretDB,FerretDB 转发给 PostgreSQL 验证,再把结果返回客户端;
- 匿名用户可以连接 FerretDB,但无法访问或操作数据库;
- 当前仅支持
SCRAM-SHA-256认证机制(authenticate命令尚未实现,但saslStart/saslContinue/logout已支持)。
创建用户有两种方式:
直接在 PostgreSQL 中创建:
CREATE USER newuser WITH PASSWORD 'newpassword';通过 FerretDB 的
createUser命令创建(会同步创建为 PostgreSQL 用户):db.createUser({ user: 'newuser', pwd: 'newpassword', roles: [] // 授权尚未支持,角色需留空数组 })
之后即可用mongodb://newuser:newpassword@127.0.0.1:27017/连接。如果出于测试目的需要关闭认证,可设置FERRETDB_AUTH=false或传--no-auth标志,但不建议在生产环境禁用认证。
另外需注意:FerretDB 要求 PostgreSQL 初始化一个postgres数据库用于建立连接;且本地连接(包括 Docker Compose 配置)中 PostgreSQL 可能使用trust认证,即使设置了POSTGRES_PASSWORD,任何能访问 PostgreSQL 服务器的用户都可能免密连接——需要自行评估并加固。
总结
从 MongoDB 迁移到 FerretDB 是一条成熟、可执行的路径,关键步骤如下:
- 明确动机:确认 FerretDB 是否适合你的使用场景;
- 预迁移评估:对照 兼容性清单 核对依赖特性;
- 预迁移测试:利用
diff-normal/diff-proxy操作模式与应用并行运行,借助 diff 输出与响应指标定位不兼容命令; - 搭建环境:通过 Docker Compose 部署 FerretDB + PostgreSQL(DocumentDB 扩展),准备连接串与认证凭据;
- 备份与恢复:用
mongodump/mongorestore(BSON 全量/指定库集合)或mongoexport/mongoimport(JSON 单集合)完成数据搬运; - 验证与回退:确保备份完整,迁移出错时随时回退。
所有软件迁移都会伴随挑战,但充分的准备能让整个过程平滑可控。迁移中发现的任何问题,都可以通过社区渠道反馈给 FerretDB 团队;同时,由于 FerretDB 是开源项目,你也可以直接为它贡献代码或提交功能请求——这正是开源的意义所在。更多细节可继续查阅仓库中的 迁移文档、操作模式文档 与 配置标志文档。
- 后端
- 数据库
- 文档数据库
【免费下载链接】FerretDB
A truly Open Source MongoDB alternative
相关推荐
Pydantic AI 接入 OpenRouter 完整指南:模型配置、提示缓存与 Web 搜索实战
Pydantic AI 接入 OpenRouter 完整指南:模型配置、提示缓存与 Web 搜索实战 OpenRouter 是一个统一的大模型路由网关,通过一个
后端数据库文档数据库OpenSimpleLidar编码器系统详解:15孔光栅与位置检测机制
OpenSimpleLidar编码器系统详解:15孔光栅与位置检测机制 OpenSimpleLidar作为一款开源扫描激光测距仪,其编码器系统是实现精确角度测量
人工智能机器学习数据科学从 FerretDB v1.x 迁移到 v2.x 完整指南:后端、认证与数据迁移实战
从 FerretDB v1.x 迁移到 v2.x 完整指南:后端、认证与数据迁移实战 FerretDB v2.x 相对 v1.x 是一次架构级的重大升级:后端从
后端数据库文档数据库
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考