• 精品分享—数睿通ETL异构数据库迁移工具(支持集成开发)


    介绍

    今天分享一款非常实用的异构数据库迁移工具,可以进行多种常见数据库之间的数据或结构迁移,相比于其他的数据迁移工具,它还支持字段索引,默认值,字段约束的信息同步,mysql 的主键递增等,支持基于正则表达式转换的表名与字段名映射转换。

    同步方式分为全量和增量同步两种类型,同步算法借鉴了 kettle 的数据同步算法,支持手动和定时执行。目前支持的数据库类型有 MySQL/MariaDB/Oracle/SQL Server/PostgreSQL/Greenplum/DB2/DMDB/Kingbase8/HighGo/Hive/SQLite,后续会不断开放更多的数据库类型。(源码文档获取方式见文末)

    后端技术栈

    • 开发框架:Spring Boot 2.3
    • 微服务框架:Spring Cloud Hoxton.SR9
    • 任务调度:Quartz
    • 持久层框架:MyBatis Plus
    • 数据库连接池:Hikaricp
    • 客户端负载均衡:Ribbon
    • 熔断组件:Hystrix
    • 网关组件:Spring Cloud Gateway
    • 日志管理:Logback

    前端技术栈

    • JS框架:Vue、nodejs
    • 组件库:ElementUI
    • 打包构建工具:Webpack

    功能介绍

    提供源端数据库向目的端数据库的批量迁移同步功能,支持数据的全量和增量方式同步。包括:

    • 结构迁移

    支持字段类型、主键信息、建表语句等的转换,并生成建表SQL语句。

    支持基于正则表达式转换的表名与字段名映射转换。

    支持字段索引,默认值,字段约束的信息同步。

    • 数据同步

    基于JDBC的分批次读取源端数据库数据,分批次写入目的数据库。

    支持有主键表的增量变更同步,算法借鉴了 kettle 的基于主键的同步算法。

    模块导航

    middle-service-etl-web – 前端工程[8080]
    middle-ground-api – 后端工程
    ├── middle-common – 系统公共模块
    ├ ├── middle-core – 公共核心包,控制环境变量
    ├ ├── middle-db-core – 数据库核心包
    ├ ├── middle-dbswtich-- 数据库迁移核心组件包
    ├ ├── middle-http – 网络相关组件包
    ├── middle-eureka – 注册中心[8610]
    ├── middle-gateway – Spring Cloud Gateway网关[8082]
    ├── middle-service-etl-- 数据库迁移业务代码

    核心代码介绍

    该系统的核心代码是它的数据迁移的相关组件包,位于 middle-common 下的 middle-dbswtich 中,其中 middle.ground.dbswitch.data.service.MigrationService 和middle.ground.dbswitch.data.handler.MigrationHandler 两个类是数据迁移的主要逻辑和算法相关的代码,通过调用 MigrationService 的 run 方法可以启动数据迁移,然后异步调用 MigrationHandler 的 get 方法运行相关逻辑,完成数据迁移。感兴趣的朋友可以自行查阅相关代码,静下心来看就能捋顺其中的逻辑。

    系统开发部署

    jdk 1.8(特别注意: 在Java9及以上版本默认情况下不允许应用程序查看来自JDK的所有类,但在数据迁移组件中利用反射计算对象的字节大小,所以需要在JVM启动时需要增加如下参数:)

    --add-opens java.base/jdk.internal.loader=ALL-UNNAMED --add-opens jdk.zipfs/jdk.nio.zipfs=ALL-UNNAMED
    
    • 1

    数据库版本为 mysql5.7 及以上版本

    导入 db 文件夹下的 sql 脚本middle_service_etl.sql

    把系统导入 idea 中,等待 maven 依赖下载完毕

    修改 middle-service-etl 模块的 yml 配置文件(配置文件生效配置在 middle-common/middle-core 的 yml 文件中指定),把 mysql 的用户名密码改成自己数据库的用户名和密码

    依次执行 middle-eureka 下的 EurekaApplication,middle-gateway 下的 GatewayApplication,middle-service-etl 下的 MiddleServiceEtlApplication

    本地安装稳定版 node.js,把 middle-service-etl-web 导入 hbuidx 或 vscode,执行 npm install 命令,然后执行 npm run dev 即可,若运行报错,安装 jsx 依赖,再次执行 npm run dev 即可:

    npm install babel-plugin-transform-vue-jsx
    npm install babel-helper-vue-jsx-merge-props
    npm install babel-plugin-syntax-jsx
    
    • 1
    • 2
    • 3

    访问 http://localhost:8080

    数据迁移配置项说明

    配置参数配置说明示例备注
    dbswitch.source[i].url来源端JDBC连接的URLjdbc:oracle:thin:@127.0.0.1:1521:orcl可为:oracle/mysql/mariadb/sqlserver/postgresql/db2/dm/kingbase8/highgo 等
    dbswitch.source[i].driver-class-name来源端数据库的驱动类名称oracle.jdbc.driver.OracleDriver对应数据库的驱动类
    dbswitch.source[i].username来源端连接帐号名root
    dbswitch.source[i].password来源端连接帐号密码root
    dbswitch.source[i].fetch-size来源端数据库查询时的fetch_size设置10000需要大于100 有效
    dbswitch.source[i].source-schema来源端的schema名称test多个之间用英文逗号分隔
    dbswitch.source[i].source-includes来源端schema下的表中需要包含的表名称users1支持多个表(多个之间用英文逗号分隔);支持正则表达式(不能含有逗号)
    dbswitch.source[i].source-excludes来源端schema下的表中需要过滤的表名称users,orgs不包含的表名称,多个之间用英文逗号分隔
    dbswitch.source[i].regex-table-mapper基于正则表达式的表名称映射关系[{“from-pattern”: “^”,“to-value”: “T_”}]为list类型,元素存在顺序关系
    dbswitch.source[i].regex-column-mapper基于正则表达式的字段名映射关系[{“from-pattern”: “$”,“to-value”: “_x”}]为list类型,元素存在顺序关系
    dbswitch.target.url目的端JDBC连接的URLjdbc:postgresql://127.0.0.1:5432/test可为:oracle/sqlserver/postgresql/greenplum/mysql/mariadb/db2/dm/kingbase8/highgo 等
    dbswitch.target.driver-class-name目的端 数据库的驱动类名称org.postgresql.Driver对应数据库的驱动类
    dbswitch.target.username目的端连接帐号名root
    dbswitch.target.password目的端连接帐号密码root
    dbswitch.target.target-schema目的端的schema名称public目的端的schema名称只能有且只有一个
    dbswitch.target.target-drop是否执行先drop表然后create表命令,当target.datasource-target.drop=true时有效true可选值为:true、false
    dbswitch.target.create-table-auto-increment是否执启用支持create表时主键自增(只支持mysql)true可选值为:true、false
    dbswitch.target.writer-engine-insert是否使用insert写入数据false可选值为:true为insert写入、false为copy写入,只针对目的端数据库为PostgreSQL/Greenplum的有效
    dbswitch.target.change-data-sync是否启用增量变更同步,dbswitch.target.target-drop为 false 时且表有主键情况下有效false可选值为:true、false

    注意:

    • (1)支持源端为多个数据源类型,如果dbswitch.source[i]为数组类型,i为编号,从0开始的整数;
    • (2)如果dbswitch.source[i].source-includes不为空,则按照包含表的方式来执行;
    • (3)如果dbswitch.source[i].source-includes为空,则按照dbswitch.source[i].source-excludes排除表的方式来执行。
    • (4)如果dbswitch.target.target-drop=falsedbswitch.target.change-data-synch=true;时会对有主键表启用增量变更方式同步
    • (5)对于regex-table-mapperregex-column-mappe,为基于正则表达式替换的表名映射和字段名映射,均可以为空(代表原名映射,即源的表t_a映射到目的端也为t_a)
    • (6)在配置字段映射时,可以通过将字段映射为空的方式排除制定字段

    提示:如果要将源端所有表名(或者字段名)添加前缀,可以配置"from-pattern": "^","to-value": "T_";

    • (7)支持的数据库产品及其JDBC驱动连接示例如下:

    MySQL/MariaDB数据库

    jdbc连接地址:jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false&nullNamePatternMatchesAll=true&useSSL=false&rewriteBatchedStatements=true
    jdbc驱动名称: com.mysql.jdbc.Driver
    
    • 1
    • 2
    jdbc连接地址:jdbc:mariadb://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false&zeroDateTimeBehavior=convertToNull&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true&tinyInt1isBit=false&rewriteBatchedStatements=true&useCompression=true
    jdbc驱动名称: org.mariadb.jdbc.Driver
    
    • 1
    • 2

    Oracle数据库

    jdbc连接地址:jdbc:oracle:thin:@127.0.0.1:1521:ORCL  或   jdbc:oracle:thin:@//127.0.0.1:1521/ORCL
    jdbc驱动名称:oracle.jdbc.driver.OracleDriver
    
    • 1
    • 2

    SQL Server(>=2005)数据库

    jdbc连接地址:jdbc:sqlserver://127.0.0.1:1433;DatabaseName=test
    jdbc驱动名称:com.microsoft.sqlserver.jdbc.SQLServerDriver
    
    • 1
    • 2

    PostgreSQL/Greenplum数据库

    jdbc连接地址:jdbc:postgresql://127.0.0.1:5432/test
    jdbc驱动名称:org.postgresql.Driver
    
    • 1
    • 2

    DB2数据库

    jdbc连接地址:jdbc:db2://127.0.0.1:50000/testdb:driverType=4;fullyMaterializeLobData=true;fullyMaterializeInputStreams=true;progressiveStreaming=2;progresssiveLocators=2;
    jdbc驱动名称:com.ibm.db2.jcc.DB2Driver
    
    • 1
    • 2

    达梦DMDB数据库

    jdbc连接地址:jdbc:dm://127.0.0.1:5236
    jdbc驱动名称:dm.jdbc.driver.DmDriver
    
    • 1
    • 2

    人大金仓Kingbase8数据库

    jdbc连接地址:jdbc:kingbase8://127.0.0.1:54321/MYTEST
    jdbc驱动名称:com.kingbase8.Driver
    
    • 1
    • 2

    翰高HighGo数据库(可按PostgreSQL使用)

    jdbc连接地址:jdbc:postgresql://127.0.0.1:5866/highgo
    jdbc驱动名称:org.postgresql.Driver
    
    • 1
    • 2

    Apache Hive数据库

    jdbc连接地址:jdbc:hive2://172.17.2.12:10000/default
    jdbc驱动名称:org.apache.hive.jdbc.HiveDriver
    
    • 1
    • 2

    注意:当前只支持hive version 3.x的账号密码认证方式。

    SQLite数据库

    jdbc连接地址:jdbc:sqlite:/tmp/test.db   或者  jdbc:sqlite::resource:http://172.17.2.12:8080/test.db
    jdbc驱动名称:org.sqlite.JDBC
    
    • 1
    • 2

    集成开发

    数据迁移相关组件可以引入到其他项目中单独使用,把 middle-common 下的 middle-dbswtich 模块安装到 maven 中(在文件夹下执行 mvn clean install)

    引入 maven 依赖:

    <dependency>
        <artifactId>middle-dbswtichartifactId>
        <groupId>middle-groundgroupId>
        <version>1.0version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    代码开发示例:

    DbswichProperties dbswichProperties = new DbswichProperties();
        //构建源表参数
        SourceDataSourceProperties dataSourceProperties = new SourceDataSourceProperties();
        List<SourceDataSourceProperties> sourceProperties = new ArrayList<>(10);
        sourceProperties.add(dataSourceProperties);
        dbswichProperties.setSource(sourceProperties);
        dataSourceProperties.setUrl("jdbc:oracle:thin:@127.0.0.1:1521:orcl");
        dataSourceProperties.setDriverClassName(DbType.ORACLE.getDriveClassName());
        dataSourceProperties.setUsername("TEST");
        dataSourceProperties.setPassword("root");
        dataSourceProperties.setFetchSize(10000);
        dataSourceProperties.setSourceSchema("TEST");
        //表名映射关系
        List<PatternMapper> tableNameMapper = new ArrayList<>(1);
        PatternMapper patternMapper = new PatternMapper();
        patternMapper.setFromPattern("test");
        patternMapper.setToValue("sync_test");
        tableNameMapper.add(patternMapper);
        dataSourceProperties.setRegexTableMapper(tableNameMapper);
        //字段映射关系
        List<PatternMapper> columnMapper = new ArrayList<>(10);
        dataSourceProperties.setRegexColumnMapper(columnMapper);
        PatternMapper columnPattern = new PatternMapper();
        columnPattern.setFromPattern("test");
        columnPattern.setToValue("test");
        columnMapper.add(columnPattern);
        PatternMapper columnPattern1 = new PatternMapper();
        columnPattern.setFromPattern("test1");
        //设置为null会不同步这个字段
        columnPattern.setToValue(null);
        columnMapper.add(columnPattern1);
        //目标表参数
        TargetDataSourceProperties targetDataSourceProperties = new TargetDataSourceProperties();
        dbswichProperties.setTarget(targetDataSourceProperties);
        targetDataSourceProperties.setUrl("jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&useLegacyDatetimeCode=false&serverTimezone=Asia/Shanghai&autoReconnect=true&failOverReadOnly=false&nullNamePatternMatchesAll=true&useSSL=false&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true");
        targetDataSourceProperties.setDriverClassName(DbType.MYSQL.getDriveClassName());
        targetDataSourceProperties.setUsername("root");
        targetDataSourceProperties.setPassword("root");
        targetDataSourceProperties.setTargetSchema("test");
        targetDataSourceProperties.setTargetDrop(true);
        targetDataSourceProperties.setIndexCreate(true);
        targetDataSourceProperties.setLowercase(true);
        //主键自动递增
        targetDataSourceProperties.setCreateTableAutoIncrement(true);
        targetDataSourceProperties.setChangeDataSync(false);
        MigrationService service = new MigrationService(dbswichProperties);
        //运行数据同步
        service.run();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    系统运行展示

    任务调度.png

    资源概览.png

    数据源管理.png

    数据资产.png

    调度配置.png

    调度日志.png

    日志.png

    关于.png

    结语

    经测试,该 ETL 系统的同步效率跟市面上主流的 ETL 工具无异,但如果有大字段类型比如:text,clob 等,同步速度会明显降低,这一点需要注意。通过集成系统的数据同步模块,也可以将其应用到自己的系统之中,对于大数据应用,数据处理系统有着不错的使用和参考价值,代码模块划分明确,方便进行二次开发。

    好了,本文到这里就结束了,希望对你有所帮助,我们下次更新,再见!

    关注公众号 螺旋编程极客 可进群讨论,反馈相关问题,进群备注 “etl交流”。

    点击获取源码文档

  • 相关阅读:
    React 像 vue 一样配置页面路由,并支持重定向路由,路由守卫等(使用 useRoutes 完成)...
    【滤波】概率、高斯和贝叶斯
    复杂四则运算的中缀表达式转后缀表达式(逆波兰表达式)Java版
    Linux NVMe Driver学习笔记之6:Admin Queue与Blk-mq初始化
    Java实用类-Enum(枚举)
    Flowable 已经执行完毕的流程去哪找?
    【力扣练习题】加一
    2024年04月09日 Go生态洞察:2024年上半年Go开发者调查报告洞察
    计算机网络---物理层疑难点总结
    LeetCode 刷题系列 -- 1425. 带限制的子序列和
  • 原文地址:https://blog.csdn.net/m0_37719874/article/details/126459117