1. 项目背景与挑战
去年我们团队面临一个棘手问题:需要将公司积累了5年的Confluence 9知识库(约20GB数据)完整迁移到Wiki.js平台,而且整个操作必须在纯内网环境下完成。这个看似简单的数据迁移任务,在实际操作中遇到了诸多意想不到的困难。
我们使用的Confluence 9服务器部署在内网DMZ区,出于安全考虑无法连接外网,这意味着所有工具和依赖都必须通过离线方式安装。目标平台Wiki.js 2.5需要MySQL 8.0作为后端数据库,而原有Confluence使用的是PostgreSQL,这种跨数据库迁移本身就充满挑战。
2. 迁移方案设计与选型
2.1 技术路线评估
我们对比了三种主流迁移方案:
- 官方导出/导入功能:Confluence的XML导出在大型知识库上极不稳定
- 第三方迁移工具:内网环境无法使用云服务
- 自定义脚本方案:灵活可控但开发成本高
最终选择了混合方案:使用Confluence REST API提取数据 + 自定义Python转换脚本 + Wiki.js批量导入API。这个方案虽然实施复杂,但能确保数据完整性和迁移过程可控。
2.2 关键工具准备
在内网环境部署需要提前准备以下组件:
- Python 3.8 + requests/BeautifulSoup库
- MySQL 8.0 RPM安装包及所有依赖
- Node.js 14.x二进制包(Wiki.js依赖)
- Git 2.3+(用于版本控制迁移脚本)
重要提示:所有软件包必须提前下载好完整离线安装包,包括所有依赖项。我们当时就因漏掉libaio依赖导致MySQL安装失败。
3. 详细迁移步骤
3.1 数据提取阶段
使用Confluence API提取数据的核心命令:
python复制import requests
session = requests.Session()
session.auth = ('admin', 'password')
def get_space_pages(space_key):
url = f"http://confluence/rest/api/space/{space_key}/content"
params = {'limit': 100, 'expand': 'body.storage,version'}
return session.get(url, params=params).json()
关键参数说明:
expand=body.storage获取原始存储格式内容limit=100分页获取避免超时- 必须使用会话保持连接
3.2 数据转换处理
Confluence的存储格式与Wiki.js的Markdown需要复杂转换:
- 表格转换:Confluence使用HTML表格 → Wiki.js的Markdown表格
- 附件处理:提取附件链接并重写路径
- 用户映射:建立Confluence用户到Wiki.js的对应关系
我们开发了专门的转换脚本处理这些差异,核心转换逻辑示例:
python复制def convert_table(html):
soup = BeautifulSoup(html, 'html.parser')
markdown = []
for row in soup.find_all('tr'):
cols = [c.get_text() for c in row.find_all(['th','td'])]
markdown.append('| ' + ' | '.join(cols) + ' |')
return '\n'.join(markdown)
3.3 数据导入实施
Wiki.js提供了完善的GraphQL API用于批量导入:
javascript复制mutation {
pages {
create(
title: "迁移文档示例",
content: "# 这是迁移的文档\n\n内容已转换",
path: "/demo",
isPublished: true,
isPrivate: false
) {
responseResult {
succeeded
errorCode
slug
}
}
}
}
批量导入时需要注意:
- 控制并发请求数(建议5-10个并行)
- 实现失败重试机制
- 记录成功/失败状态
4. 关键问题与解决方案
4.1 大附件处理难题
当遇到超过50MB的附件时,直接API上传会超时。我们的解决方案:
- 先将附件通过SCP传到Wiki.js服务器
- 使用本地路径引用方式导入
- 通过cronjob定期同步新增附件
4.2 权限映射复杂
Confluence的精细权限体系与Wiki.js的简化模型不匹配。最终采取:
- 保留主要读写权限
- 复杂权限需求通过Wiki.js的组别功能实现
- 特殊权限需求单独处理
4.3 内网环境限制
纯内网带来的主要挑战:
- 无法实时查询文档
- 依赖包安装困难
- 无法使用云验证服务
应对策略:
- 搭建内网PyPI镜像
- 预下载所有依赖包
- 开发离线文档查询工具
5. 迁移后验证
为确保数据完整性,我们设计了多维度验证方案:
| 检查项 | 方法 | 合格标准 |
|---|---|---|
| 页面数量 | 数据库统计 | 源/目标差异<0.1% |
| 附件完整性 | MD5校验 | 全部匹配 |
| 链接有效性 | 爬虫检测 | 无死链 |
| 渲染效果 | 人工抽检 | 关键页面100%检查 |
6. 性能优化建议
针对20GB级知识库的特别优化:
- MySQL配置优化:
ini复制[mysqld] innodb_buffer_pool_size = 4G innodb_log_file_size = 512M max_connections = 200 - Wiki.js缓存配置:
json复制{ "cache": { "enabled": true, "adapter": "redis", "ttl": 3600 } } - 定期维护脚本:
bash复制# 每周执行一次索引优化 curl -X POST http://wiki/api/reindex
7. 经验总结
- 一定要先做小规模试迁移,我们前两次尝试都因未充分测试而失败
- 内网环境务必准备完整的离线安装包和依赖
- 复杂内容转换建议分阶段验证
- 建立详细的迁移日志和回滚方案
- 预留至少30%的时间缓冲应对意外问题
整个迁移过程耗时3周,最终实现了:
- 19.8GB知识库完整迁移
- 99.97%的内容保真度
- 零停机时间过渡
- 所有历史版本保留
这次经历让我深刻认识到:大规模知识库迁移不仅是技术活,更是需要周密规划的系统工程。每个环节都可能成为瓶颈,提前识别关键路径和风险点至关重要。
