如何从关系型数据库迁移到mongodb · 2020. 4. 4. · rdbms jdbc sql / resultset orm pojos...
TRANSCRIPT
如何从关系型数据库迁移到MongoDB
MongoDB官方中文讲座系列之一
微信讨论群
如果你现在还没听到一个美妙的男中音:
• 请打开你的音箱或插上耳机 • 如果没有音箱或耳机,可以用电话拨入:
• 从固定电话拨入: 800-8190097 • 从手机拨入: 400-6200506 • 听到语音提示后按:3760527#
• (建议用电脑音频 – 别让移动挣太多钱了)
关于ReadyTalk
如何进行提问或请求帮助
• 用左下角的“Chat”窗口 • 关于在线讲座的问题或MongoDB技术问题都可以 • 简单的问题将由专人实时回答 • 有代表性的问题将在讲座结束后统一回答
关于我 • 唐建法、TJ
• MongoDB 大中华区技术顾问
• 原联邦快递首席架构师
• 15年数据库相关应用软件开发及架构经验
• 关系型数据库到NoSQL
今天的目标
讨论从已有的关系型数据库应用迁移到MongoDB的问题
• 评估迁移的必要性及价值 • 迁移设计的角色及责任 • 批量迁移技术 • 迁移演示
为什么要迁移??
列出你的痛点
如果你有2个或更多的需求你的关系型数据库无法轻易地满足,那么就可以考虑迁移了
• 高并发需求 (数千 – 数百万ops / sec)
• 动态模式和灵活查询
• 敏捷开发,快速迭代
• 缩短应用上线时间
• 地理查询
• 多数据中心数据同步,容灾
• 快速部署和按需扩展
• 99.999% uptime (<10分钟/年)
• 降低硬件成本,使用x86服务器
• 任意时间点恢复
不是理由的理由
• 希望使用免费软件来避免软件开支 • 因为玩大数据比较酷!
迁移难度
关系型到关系型 – 相对简单 Oracle -> MySQL, SQLServer – PostgreSQL)
关系型到文档型 – 相对复杂 需要考虑: • 模式设计 • 总体设计架构 • 全栈考量
迁移的主战场
RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
• 模式 • 存储过程 • 运维工具、脚本 • 备份及恢复 • 测试环境
Apps
Storage Layer
存储方案
典型的关系型数据库部署在 SAN 上。 MongoDB支持 SAN, 但是使用本地存储可以最大化的提高性能
RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
Apps
Storage Layer
隐性价值
额外的价值: • 高可用HA 和灾备DR • 读写分离
RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
Apps
Storage Layer
O/JDBC 基于行与列
MongoDB没有原生态JDBC, 而是采用自带的驱动程序: • MQL • 自带连接池管理 • 写安全级别 • 无多文档多语句事务控制 RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
Apps
Storage Layer
NoSQL : No SQL
MongoDB 不支持SQL,结果集也不是ResultSet MongoDB 不支持关联
RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
Apps
Storage Layer
再见ORM
ORM: Object Relational Mapping 转换关系型到POJO对象模型 不再需要啦!
RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
Apps
Storage Layer
POJO?
• 理论上,POJO应该是纯对象模型,表达业务概念
• 实际上,很多POJO和关系型表有一一对应以方便和ORM对接
• 有些还有SQL代码
RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
Apps
Storage Layer
迁移,还是重写?
Migration Approach
RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
Apps
Rewrite Approach
新设计,固定成本
越往上层代价越大 $
$
$
$ Storage Layer
迁移成本“计算器”
当前应用特点 难度 需求 多阶段 XA 远程事务支持(如队列) -5
100+ 表,大部分都是核心很重要 -3 ✔
大量使用ORM -3
数百个SQL驱动的BI报表 -2
动态SQL生成器 +2 ✔
业务代码整洁无SQL +2 ✔
业务代码有很多BLOB数据存取 +2
需要保存和查询第三方(不可控)数据 +4
有独立抽象的数据访问层 +4
非常希望简化数据访问层 +4
得分 +1
得分小于0:相对迁移的价值来说,成本会偏高
迁移还是重写?另一个角度
• 表的数量较少(~20) • 复杂数据存在BLOB字段里 • 千万或者十数亿级 • 频繁数据结构变化(每月) • 优良的设计架构:清晰的数据访问层
• 业务代码内嵌很多SQL • 数百个表 • 数据增长不多 • 大量SQL驱动的BI报表
迁移
重写
迁移的影响
迁移的影响
• 业务部门 • 开发工程师 • 数据架构师 • 数据库管理员 • 系统管理员 • 安全工程师
⋯特别是这些童鞋
• 业务部门 • 开发工程师 • 数据架构师 • 数据库管理员 • 系统管理员 • 安全工程师
数据架构师:建模
RDBMS MongoDB
{ name: { last: "Dunham”, first: “Justin” }, department : "Marketing", pets: [ “dog”, “cat” ], title : “Manager", locationCode: “NYC23”, benefits : [ { type : "Health", plan : “Plus" }, { type : "Dental", plan : "Standard”, optin: true } ] }
建模举例
数据结构:不仅仅是单值
BUYER_FIRST_NAME BUYER_LAST_NAME BUYER_MIDDLE_NAME INSERT INTO COLL BUYER_FIRST_NAME BUYER_LAST_NAME BUYER_MIDDLE_NAME
Map bn = makeName(FIRST, LAST, MIDDLE); Collection.insert( {“buyer_name”, bn});
Select BUYER_FIRST_NAME BUYER_LAST_NAME BUYER_MIDDLE_NAME ..
Collection.find(pred, {“buyer_name”:1});
{ first: “Buzz”, last: “Moschetti” }
增加一个新字段
BUYER_FIRST_NAME BUYER_LAST_NAME BUYER_MIDDLE_NAME BUYER_NICKNAME INSERT INTO COLL [prev + NICKNAME]
Map bn = makeName(FIRST, LAST, MIDDLE,NICKNAME);
Select BUYER_FIRST_NAME BUYER_LAST_NAME BUYER_MIDDLE_NAME BUYER_NICKNAME ….
Collection.insert( {“buyer_name”, bn}); Collection.find(pred, {“buyer_name”:1}); NO change
增加新类型 – 轻而易举
BUYER_FIRST_NAME BUYER_LAST_NAME BUYER_MIDDLE_NAME BUYER_NICKNAME SELLER_FIRST_NAME SELLER_LAST_NAME SELLER_MIDDLE_NAME SELLER_NICKNAME
INSERT INTO COLL [prev + SELLER_FIRST_NAME, SELLER_LAST_NAME, SELLER….]
Map bn = makeName(FIRST, LAST, MIDDLE,NICKNAME); Map sn = makeName(FIRST, LAST, MIDDLE,NICKNAME); Collection.insert( {“buyer_name”, bn, “seller_name”: sn});
Select BUYER_FIRST_NAME BUYER_LAST_NAME BUYER_MIDDLE_NAME BUYER_NICKNAME SELLER_FIRST_NAME SELLER_LAST_NAME SELLER_MIDDLE_NAME SELLER_NICKNAME
Collection.find(pred, {“buyer_name”:1, “seller_name”:1}); Easy change
⋯ 新的需求来了
BUYER_FIRST_NAME BUYER_LAST_NAME BUYER_MIDDLE_NAME BUYER_NICKNAME SELLER_FIRST_NAME SELLER_LAST_NAME SELLER_MIDDLE_NAME SELLER_NICKNAME LAWYER_FIRST_NAME LAWYER_LAST_NAME LAWYER_MIDDLE_NAME LAWYER_NICKNAME CLERK_FIRST_NAME CLERK_LAST_NAME CLERK_NICKNAME QUEUE_FIRST_NAME QUEUE_LAST_NAME …
为所有的人名加一个称谓字段 • What’s a “name”? • Did you find them all? • QUEUE is not a “name”
Day 3 with Rich Shape Design
Map bn = makeName(FIRST, LAST, MIDDLE,NICKNAME,TITLE); Map sn = makeName(FIRST, LAST, MIDDLE,NICKNAME,TITLE);
Collec?on.insert({“buyer_name”, bn, “seller_name”: sn}); Collec?on.find(pred, {“buyer_name”:1, “seller_name”:1});
NO change
Easy change
数据架构师的选择
较少的模式修改 大量的模式修改
优点 • 迁移大量数据相对容易些 • 对上层业务代码影响小 • 对数据接入层影响小
• 一次还清技术债 • 新的数据模式可以让后续的开发更具有敏捷性
• 1:n 内嵌通常会带来性能提高
缺点 • 需要在代码中实现关联 • 单值字段需要重载为多值类型
• 设计成本增加
迁移不一定要大改模式
• 高可用 • 容灾 • 水平扩展
DBA的职责
传统关系型 MongoDB
EXPERTS
ADMIN
SDLC
EXPERTS
ADMIN
SDLC
监控,备份,权限管理等 运维操作
性能测试 表修改 数据升级 上线支持 每个应用需要1-2个DBA
聚合分析任务
上线支持 性能测试
批量迁移
迁移工具
• 官方工具mongoimport • ETL工具 Pentaho/Kettle • 社区工具 Mongify / Firehose • 脚本
原厂工具: mongoimport $ head -‐1 customers.json { "name": { "last": "Dunham", "first": "Jus?n" }, "department" : "Marke?ng", "pets": [ "dog", "cat" ] , "hire": {"$date": "2012-‐12-‐14T00:00:00Z"} ,"?tle" : "Manager", "loca?onCode": "NYC23" , "benefits" : [ { "type":"Health", "plan":"Plus" }, { "type" : "Dental", "plan" : "Standard", "op?n": true }]} $ mongoimport -‐-‐db test -‐-‐collec8on customers –drop < customers.json connected to: 127.0.0.1 2014-‐11-‐26T08:36:47.509-‐0800 imported 1000 objects $ mongo MongoDB shell version: 2.6.5 connec?ng to: test Ø db.customers.findOne() {
"_id" : ObjectId("548f5c2da40d2829f0ed8be9"), "name" : { "last" : "Dunham”, “first" : "Jus?n” }, "department" : "Marke?ng", "pets" : [ "dog”"cat”], "hire" : ISODate("2012-‐12-‐14T00:00:00Z"), "?tle" : "Manager", "loca?onCode" : "NYC23", "benefits" : [ { "type" : "Health", "plan" : "Plus" },{ "type" : "Dental", "plan" : "Standard", "op?n" : true } ]
}
传统 ETL 工具
Source Database ETL
社区工具 http://mongify.com/! • SQL 到 MongoDB数据迁移工具
• MySQL,PostgreSQL, SQLServer, Oracle, DB2
• 增量迁移
社区工具 github.com/bryanreinero/Firehose! • CLI, DB-writer, JMX 集成
• 多线程
• 开发框架: 一个好的开头
迁移方式
• 全量迁移 • 增量迁移 • 应用迁移
全量迁移:小时级”切换方案
RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
Apps
MongoDB Drivers
DAL
POJOs
Apps
RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
Apps
MongoDB Drivers
DAL
POJOs
Apps
RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
Apps
MongoDB Drivers
DAL
POJOs
Apps
原系统上运行 周日晚上几个小时下线后。。。 切换到新系统
增量迁移1:“分钟级” 切换方案
RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
Apps
DAL
MongoDB Drivers
RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
Apps
DAL
MongoDB Drivers
软件切换
RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
Apps
DAL
MongoDB Drivers
暂停应用写入, 完成MongoDB同步
老系统上运行 同时写入双系统
增量迁移2:应用主导
RDBMS
JDBC
SQL / ResultSet
ORM
POJOs
Apps
DAL
MongoDB Drivers
POJOs
Apps
DAL
MongoDB Drivers
2
1. 插入请求直接进入MongoDB 2. 查询和更新请求首先被路由到MongoDB 3. 如果记录不存在,从RDBMS读出来并写入到mongoDB 4. 重复步骤1 5. 当步骤2在限定时间段(一星期、一个月)没有被调用,认为迁移完成 6. 不适用: 模式变化大,范围查询多
4
Shepherd
3
Low-level Shepherd
T 1
增量迁移实现方式 工作方式 备注
基于源库数据 每次迁移操作记录下最后一次迁移的时间点,下一次迁移只选择新的记录
要求每个迁移的表都有timestamp或者sequenceid 字段
快照方式 每一次迁移对整个数据集做一次快照,下一次迁移时候每条记录和快照对比一次
效率低,适合数据量不是特别大的场景
触发器方式 在源库内使用触发器记录所有的变化,然后对有变化的记录进行增量迁移
增加项目复杂度 触发器维护麻烦
数据库日志 通过使用数据库更新日志来同步数据
迁移DEMO
Pentaho KeAle
Sakila
hip://dev.mysql.com/doc/sakila/en/
MySQL Sakila
MongoDB 模式
CUSTOMER
name: { first: last: }
address:{ city: country: }
STORE
manager_id
address:{ city: country: }
INVENTORY
film_id store_id Inventory_id
FILM
actor: category: [ ] language:
PAYMENT
rental_id Amount Customer_id
RENTAL
rental_id customer_id rental_date return_date inventory_id payment
Demo 1: 无模式修改的迁移 payment
PAYMENT
customer_id rental_id amount payment_date last_update
PAYMENT
customer_id rental_id amount payment_date last_update
Demo 2: 表合并 film
FILM
?tle, category: [ ‘ac?on’], language: ‘english’
text: { ?tle: descrip?on: }
actor: [ { first: last: }]
Demo 3: 增量迁移 payment
PAYMENT
customer_id rental_id amount payment_date last_update
PAYMENT
customer_id rental_id amount payment_date last_update
• CLI、脚本控制迁移 • 参数支持(增量迁移) • 每次只迁移有更新的数据
安装和演示步骤
• 安装 – 下载,安装,并启动MySQL – 下载,安装,并启动MongoDB – 下载并安装Pentaho Data Integration – 下载MySQL Java Driver 并放到Data Integration的lib 目录 – 下载MySQL 样例数据Sakila 并导入到MySQL – 运行PDI设计器 (spoon.sh)
• 演示 – 检查数据 – 创建输入源:Table Input(MySQL) – 创建输出源:MongoDB Output – 制定转换规则 – 测试任务
总结 • 从迁移成本和价值的角度评估了迁移的必要性 • 迁移对技术人员的影响 • 迁移的工具:
• mongoimport • ETL • 脚本 • 第三方工具
• 迁移方式: • 全量 • 增量
• 使用Pentaho PDI来进行关系型到MongoDB的全量或增量迁移
迁移成功案例
MongoDB 可以帮助你! MongoDB 企业版 The best way to run MongoDB in your data center OpsManager 监控,备份和恢复,集群管理
技术⽀支持 24x7 线上⽀支持
开发⽀支持 Let’s get you running
咨询服务 性能调优,疑难排解,模式设计
培训服务 Get your teams up to speed.
谢谢 & KEEP IN TOUCH!
MongoDB官方网站 http://www.mongodb.com
MongoDB中文社区微信群 实时讨论 互相学习
MongoDB中文网站 技术问答 中文文档 博客 活动
http://www.mongoing.com/
MongoDB中文社区公众号 活动通知 博客推荐 相关新闻 技术分享
http://www.mongodb.com