SmartCode.ETL 这不是先有鸡还是蛋的问题!

发布日期:2019-06-17

继国庆节 SmartCode 正式版(SmartCode.Generator)发布之后,SmartCode 迎来了新的能力 SmartCode.ETL !

SmartCode 正式版从开始发布就从未说过自己仅仅是个代码生成器,这点上从我第一次宣布SmartCode正式开源的文章就可以说明:《SmartCode 不只是代码生成器》,这不仅仅是一句推广语!

SmartCode.Generator

相信不少同学都用过各种代码生成器,这里我就不做详细介绍了,如果想体验 SmartCode.Generator 请至 https://www.cnblogs.com/Ahoo-Wang/p/SmartCode-intro.html 配置好数据库连接,一键生成解决方案。

Why SmartCode.ETL

相信不少已经落地微服务架构方案的同学都会遇到同样的问题:

    业务方的查询需求似乎总是跨微服务DB的领导层需要查看的报表数据总是全局的(需要聚合跨微服务DB的)

So SmartCode.ETL

    从多个微服务DB 同步业务聚合查询数据到 all_biz DB (解决:微服务架构一定会遇到的业务方需要跨微服务DB查询的问题)从 all_biz DB 同步聚合分析数据到 report DB (解决:领导层查看的报表数据聚合问题)

How SmartCode.ETL

    安装 SmartCode from dotnet-cli

    dotnet tool install --global SmartCode.CLI使用 SmartCode.Generator 生成 同步Sql表结构脚本,以及 SmartCode.ETL 构建配置执行Sql同步脚本初始化表结构使用任务调度(crontab) + SmartCode.ETL 同步分析数据

    通过持久化 etl_task 监控 etl执行情况(目前支持PostgreSql)

简单来说就是SmartCode生成SmartCode,任务调度执行SmartCode命令行。(这真的不是先有鸡还是蛋的问题.....)

SmartCode 插件概览

{ "SmartCode": { "Version": "v1.16.15" "Plugins": [ { "Type": "SmartCode.IDataSourceSmartCode" "ImplType": "SmartCode.NoneDataSourceSmartCode" } { "Type": "SmartCode.IBuildTaskSmartCode" "ImplType": "SmartCode.App.BuildTasks.ClearBuildTaskSmartCode.App" } { "Type": "SmartCode.IBuildTaskSmartCode" "ImplType": "SmartCode.App.BuildTasks.ProjectBuildTaskSmartCode.App" } { "Type": "SmartCode.IBuildTaskSmartCode" "ImplType": "SmartCode.App.BuildTasks.MultiTemplateBuildTaskSmartCode.App" } { "Type": "SmartCode.IBuildTaskSmartCode" "ImplType": "SmartCode.App.BuildTasks.ProcessBuildTaskSmartCode.App" } { "Type": "SmartCode.IOutputSmartCode" "ImplType": "SmartCode.App.Outputs.FileOutputSmartCode.App" } { "Type": "SmartCode.IDataSourceSmartCode" "ImplType": "SmartCode.Generator.DbTableSourceSmartCode.Generator" } { "Type": "SmartCode.IBuildTaskSmartCode" "ImplType": "SmartCode.Generator.BuildTasks.TableBuildTaskSmartCode.Generator" } { "Type": "SmartCode.IBuildTaskSmartCode" "ImplType": "SmartCode.Generator.BuildTasks.SingleBuildTaskSmartCode.Generator" } { "Type": "SmartCode.INamingConverterSmartCode" "ImplType": "SmartCode.Generator.TableNamingConverterSmartCode.Generator" } { "Type": "SmartCode.TemplateEngine.ITemplateEngineSmartCode.TemplateEngine" "ImplType": "SmartCode.TemplateEngine.Impl.HandlebarsTemplateEngineSmartCode.TemplateEngine" } { "Type": "SmartCode.TemplateEngine.ITemplateEngineSmartCode.TemplateEngine" "ImplType": "SmartCode.TemplateEngine.Impl.OfficialRazorTemplateEngineSmartCode.TemplateEngine" } { "Type": "SmartCode.Generator.IDbTypeConverterSmartCode.Generator" "ImplType": "SmartCode.Generator.DbTypeConverter.DefaultDbTypeConverterSmartCode.Generator" } { "Type": "SmartCode.IDataSourceSmartCode" "ImplType": "SmartCode.ETL.ExtractDataSourceSmartCode.ETL" } { "Type": "SmartCode.IBuildTaskSmartCode" "ImplType": "SmartCode.ETL.BuildTasks.TransformBuildTaskSmartCode.ETL" } { "Type": "SmartCode.ETL.ITransformEngineSmartCode.ETL" "ImplType": "SmartCode.ETL.TransformEngine.RazorTransformEngineSmartCode.ETL" } { "Type": "SmartCode.IBuildTaskSmartCode" "ImplType": "SmartCode.ETL.BuildTasks.LoadBuildTaskSmartCode.ETL" } { "Type": "SmartCode.ETL.IETLRepositorySmartCode.ETL" "ImplType": "SmartCode.ETL.NoneETLRepositorySmartCode.ETL" } { "Type": "SmartCode.ETL.IETLRepositorySmartCode.ETL" "ImplType": "SmartCode.ETL.PostgreSql.PGETLRepositorySmartCode.ETL.PostgreSql" "Paramters": { "ConnectionString": "Server=localhostPort=5432User Id=postgresPassword=SmartSql Database=smartcode_etl" } } ] }}

ETL 构建配置

Author: Ahoo WangDataSource: Name: Extract Paramters: DbProvider: SqlServer ConnectionString: Data Source=.Initial Catalog=SmartSqlDBIntegrated Security=True Query: SELECT [Id][UserName][Status][LastLoginTime][CreationTime][ModifyTime][Deleted] FROM [T_User] With(NoLock) Where ModifyTime>@LastMaxModifyTime PKColumn: Id AutoIncrement: true ModifyTime: ModifyTimeParamters: ETLCode: SmartCode.ETL.Test ETLRepository: PGBuild: Transform: Type: Transform Paramters: Script: Load2PostgreSql: Type: Load Paramters: DbProvider: PostgreSql ConnectionString: Server=localhostPort=5432User Id=postgresPassword=SmartSql Database=smartsql_db Table: t_user__temp PreCommand: CREATE TABLE t_user__temp( LIKE t_user ) PostCommand: "Delete From t_user as source Where EXISTS(select * from t_user__temp temp where temp.id=source.id) Insert Into t_user SELECT * From t_user__temp Drop Table t_user__temp " ColumnMapping: [{Column: IdMapping: id} {Column: UserNameMapping: user_name} {Column: StatusMapping: status} {Column: LastLoginTimeMapping: last_login_time} {Column: CreationTimeMapping: creation_time} {Column: ModifyTimeMapping: modify_time} {Column: DeletedMapping: deleted}]

根 Paramters

参数名说明
ETLCodeETL任务Code区分任务类型,唯一
ETLRepositoryETL任务持久化仓储,None/PG

DataSource 参数说明

属性 Name:Extract使用 ExtractDataSource 插件作为数据源

ExtractDataSource.Paramters

参数名说明
DbProvider数据驱动提供者:MySqlMariaDBPostgreSqlSqlServerOracleSQLite
ConnectionString连接字符串
Query查询命令,需要抽取的数据。默认会自动注入三个参数 LastMaxIdLastMaxModifyTimeLastQueryTime 作为查询条件
PKColumn主键列名
AutoIncrement是否为自增主键,true 自动计算抽取的最大主键值(MaxId)
ModifyTime最近一次修改时间列名,设置后自定计算抽取的最大修改时间列(MaxModifyTime)

Build.Load 参数说明

属性 Type:Load使用 LoadBuildTask 插件作为构建任务

Build.Load.Paramters

参数名说明
DbProvider数据驱动提供者:MySqlMariaDBPostgreSqlSqlServerOracleSQLite
ConnectionString连接字符串
Table目标表名
PreCommand执行批量插入任务之前执行的命令
PostCommand执行批量插入任务之后执行的命令
ColumnMapping列映射

同步策略

LastMaxId

LastMaxId 即上一次抽取的数据最大Id值(第一次抽取时LastMaxId为-1),该模式使用于数据插入后不再变更的数据表。

LastMaxModifyTime

LastMaxModifyTime 即上一次抽取的数据最大ModifyTime值(第一次抽取时LastMaxModifyTime为1970-01-01 08:00:00),适用于插入数据后还会变更的数据表。

并发任务同步

    对 Id 取模分拆不同任务,同时并发执行

大数据量同步

    使用 Top/Limit 限制数据抽取数量,分多次同步执行完成整个数据同步。

ETL_Task 任务监控

性能监控

运行环境

    源抽取库:Windows Server 2012 8 vCPU 16 GB + SSD + SqlServer-2014目标分析库:CentOS-7 8 vCPU 16 GB + SSD + PostgreSql-11 + SmartCode

ETL_Task.Extract

以下是数据抽取性能,抽取数量为 1434678,耗时 41267 毫秒。

{ "MaxId": 1755822 "PKColumn": "Id" "QuerySize": 1434678 "QueryTime": "2018-11-01T11:31:53.6191084+08:00" "QueryCommand": { "Taken": 41267 "Command": "Select * From T_ProductSearchLog With(NoLock) Where Id>@LastMaxId" "Paramters": { "LastMaxId": -1 "LastQueryTime": "1970-01-01T08:00:00" } }}

ETL_Task.Load

以下是数据加载性能,批量插入数据量为 1434678,耗时 21817 毫秒,平均每秒插入 65759.6 条数据。

{ "Size": 1434678 "Table": "t_product_search_log" "Taken": 21817 "PreCommand": null "PostCommand": null}


目前 SmartCode.ETL 已经落地到我们的生产环境了(11-01上线截至目前执行了 26069 次同步任务,暂无error日志抛出)

PS: 虽然 SmartCode.ETL 只花了周末俩天时间完成扩展,但已经可以满足我们至少90%的应用场景。这足以见得 SmartCode 扩展能力是多么令人意外了。当然SmartCode的其他能力还得后续等各位一起发掘!!!