开源的 ETL工具里面 DataX和 Kettle的人气一直高居不下,datax虽然比较年轻,但这两年发展势头很猛,不时就能听到身边的同事谈起。kettle作为老牌的 etl工具,诞生年限长,功能完善,特别是其开箱即用的数据转换算子,不得不令人叹服。因此,笔者决定对这两款工具进行深入的对比分析,有多深呢,到源码那种。
DataX 是阿里开源的离线数据同步工具/平台。DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS、Hive、ADS、HBase、TableStore(OTS)、MaxCompute(ODPS)、Hologres、DRDS 等各种异构数据源之间高效的数据同步功能。
从 GitHub上可以查到 DataX仓库的创建时间为 2018-01-18T10:09:47Z,是一个比较年轻的项目。
这里以 DataX 3.0为研究对象,从支持的数据源、界面化配置、数据转换能力、扩展性和部署难易程度等方面进行分析介绍。
下面这张表格来自 datax在 github的官方仓库:
| 类型 | 数据源 | Reader(读) | Writer(写) | 文档 |
|---|---|---|---|---|
| RDBMS 关系型数据库 | MySQL | √ | √ | 读 、写 |
| Oracle | √ | √ | 读 、写 | |
| OceanBase | √ | √ | 读 、写 | |
| SQLServer | √ | √ | 读 、写 | |
| PostgreSQL | √ | √ | 读 、写 | |
| DRDS | √ | √ | 读 、写 | |
| Apache Doris | √ | 写 | ||
| StarRocks | √ | 写 | ||
| 通用RDBMS(支持所有关系型数据库) | √ | √ | 读 、写 | |
| 阿里云数仓数据存储 | ODPS | √ | √ | 读 、写 |
| ADS | √ | 写 | ||
| OSS | √ | √ | 读 、写 | |
| OCS | √ | 写 | ||
| NoSQL数据存储 | OTS | √ | √ | 读 、写 |
| Hbase0.94 | √ | √ | 读 、写 | |
| Hbase1.1 | √ | √ | 读 、写 | |
| Phoenix4.x | √ | √ | 读 、写 | |
| Phoenix5.x | √ | √ | 读 、写 | |
| MongoDB | √ | √ | 读 、写 | |
| Hive | √ | √ | 读 、写 | |
| Cassandra | √ | √ | 读 、写 | |
| 无结构化数据存储 | TxtFile | √ | √ | 读 、写 |
| FTP | √ | √ | 读 、写 | |
| HDFS | √ | √ | 读 、写 | |
| Elasticsearch | √ | 写 | ||
| 时间序列数据库 | OpenTSDB | √ | 读 | |
| TSDB | √ | √ | 读 、写 | |
| TDengine | √ | √ | 读 、写 |
从上面这张表格可以看到,datax对流行的 mysql, oracle, sql server和 pg等关系型数据库的支持较好。另外,对 hdfs, hive, hbase等大数据存储的支持度也不错,但对于全文搜索 elasticsearch的支持度较弱,仅支持写入。
总结下,如果是同步关系型数据库、hadoop生态圈的大数据存储、文本格式(csv,json等)的文件等场景,用 datax都是一个挺好的选择。
datax官方并没有提供配置数据同步任务的界面(至少在 github上没有),另外有一个流行的界面项目 datax-web(4.2k stars),由 WeiYe-Jing发起,但遗憾的是该项目 master分支已经超过两年没有更新,最近一次更新在 2020年6月。
datax-web界面以网页形式在浏览器中进行使用,支持 hive, mysql, oracle, postgresql, sqlserver, hbase, mongodb, clickhouse等数据同步任务的可视化创建,并集成了任务调度组件,支持分布式部署,功能精炼易用。缺点是支持的数据源比 datax官方少了很多,也没有提供数据转换的配置能力。
datax官方提供的 transformer只有五个:
dx_substr
获取原字符串指定位置和长度的子字符串
dx_pad
统一字符串长度,长度超过阈值进行截断,长度不足则使用指定的字符进行填充
dx_replace
对字符串进行部分替换,可用于数据脱敏
dx_filter
支持 java的正则表达式,对数据进行过滤
dx_groovy
支持自定义 groovy脚本,可用于对数据进行复杂的转换操作
五个转换算子中,其实只有四个是可以直接使用的算子,最后一个算是对脚本进行了简单支持,满足了一定的扩展性。因为 datax一个核心设计是插件式开发,所以开发自定义 transformer也比较容易,需要继承基类 Transformer,如下:
public class DateTransformer extends Transformer {
@Override
public Record evaluate(Record record, Object... paras) {
// 自定义转换逻辑
return record;
}
}
这里主要分析核心的 reader, writer, transformer三大核心功能的扩展性。
前面已经谈到,datax的开发是插件式思维,对扩展开放。reader插件用于读取数据源,自定义 reader插件需要继承 Reader, Reader.Job, Reader.Task三个类,并实现部分接口。下面是 mysql reader的部分源码:
public class MysqlReader extends Reader {
private static final DataBaseType DATABASE_TYPE = DataBaseType.MySql;
public static class Job extends Reader.Job {
private static final Logger LOG = LoggerFactory
.getLogger(Job.class);
private Configuration originalConfig = null;
private CommonRdbmsReader.Job commonRdbmsReaderJob;
@Override
public void init() {
}
...
@Override
public void post() {
this.commonRdbmsReaderJob.post(this.originalConfig);
}
@Override
public void destroy() {
this.commonRdbmsReaderJob.destroy(this.originalConfig);
}
}
public static class Task extends Reader.Task {
private Configuration readerSliceConfig;
private CommonRdbmsReader.Task commonRdbmsReaderTask;
@Override
public void init() {
this.readerSliceConfig = super.getPluginJobConf();
this.commonRdbmsReaderTask = new CommonRdbmsReader.Task(DATABASE_TYPE,super.getTaskGroupId(), super.getTaskId());
this.commonRdbmsReaderTask.init(this.readerSliceConfig);
}
@Override
public void startRead(RecordSender recordSender) {
int fetchSize = this.readerSliceConfig.getInt(Constant.FETCH_SIZE);
this.commonRdbmsReaderTask.startRead(this.readerSliceConfig, recordSender,
super.getTaskPluginCollector(), fetchSize);
}
...
}
}
writer则是读取数据源的插件,跟 reader类似,自定义 writer插件也需要继承 Writer, Writer.Job, Writer.Task三个类,并实现部分接口。部分源码如下:
public class MysqlWriter extends Writer {
private static final DataBaseType DATABASE_TYPE = DataBaseType.MySql;
public static class Job extends Writer.Job {
private Configuration originalConfig = null;
private CommonRdbmsWriter.Job commonRdbmsWriterJob;
@Override
public void preCheck(){
this.init();
this.commonRdbmsWriterJob.writerPreCheck(this.originalConfig, DATABASE_TYPE);
}
@Override
public void init() {
this.originalConfig = super.getPluginJobConf();
this.commonRdbmsWriterJob = new CommonRdbmsWriter.Job(DATABASE_TYPE);
this.commonRdbmsWriterJob.init(this.originalConfig);
}
...
}
public static class Task extends Writer.Task {
private Configuration writerSliceConfig;
private CommonRdbmsWriter.Task commonRdbmsWriterTask;
@Override
public void init() {
this.writerSliceConfig = super.getPluginJobConf();
this.commonRdbmsWriterTask = new CommonRdbmsWriter.Task(DATABASE_TYPE);
this.commonRdbmsWriterTask.init(this.writerSliceConfig);
}
...
}
}
transformer已经在 2.3节进行了介绍,这里就不再介绍了。总的来说,datax扩展性很强,开发自定义插件的难度较小,比较适合根据业务进行二次开发和增强。
部署 datax非常简单,预先搭建好 JDK1.8+和 python2(3)的环境,然后解压已编译好的 datax安装包即可。
如果是从源码安装,则除了上述要求外还要准备好 Maven 3.x的环境。
Kettle是开源自 2005年的一款老牌 ETL工具,使用 Java进行编写,核心组件有 spoon, pan, kitchen, carte。如今已被 Pentaho收购,并更名为 Pentaho Data Integration,简称 PDI。
这里以 PDI 9.2为研究对象(9.2以后依赖 JDK11+),同样从支持的数据源、界面化配置、数据转换能力、扩展性和部署难易程度等方面进行分析介绍。
| 类型 | 数据源 | 读 | 写 |
|---|---|---|---|
| RDBMS 关系型数据库 | MySQL | √ | √ |
| Oracle | √ | √ | |
| IBM DB2 | √ | √ | |
| SQLServer | √ | √ | |
| PostgreSQL | √ | √ | |
| Teradata | √ | √ | |
| SQLite | √ | √ | |
| KingbaseES | √ | √ | |
| Sybase | √ | √ | |
| Azure SQL DB | √ | √ | |
| Apache Derby | √ | √ | |
| LucidDB | √ | √ | |
| MonetDB | √ | √ | |
| Microsoft Access | √ | √ | |
| 通用RDBMS(支持所有关系型数据库) | √ | √ | |
| NoSQL数据存储 | HBase | √ | √ |
| Hive | √ | √ | |
| MongoDB | √ | √ | |
| Cassandra | √ | √ | |
| Calpont InfiniDB | √ | √ | |
| Greenplum | √ | √ | |
| Vertica | √ | √ | |
| CouchDB | √ | ||
| SSTable | √ | ||
| 无结构化数据存储 | TxtFile(CSV, Json, LDIF, yaml, xml) | √ | √ |
| GZIP CSV | √ | ||
| Excel | √ | √ | |
| LDAP | √ | √ | |
| Cube | √ | √ | |
| Rss | √ | √ | |
| FTP | √ | √ | |
| HDFS | √ | √ | |
| Elasticsearch | √ |
上面列出的数据源只是 kettle数据源中比较常见的部分,还有一些小众的未列出。可以看到 kettle对关系型数据库的支持相当好,估计是 ETL工具的天花板了,另外对大数据存储组件的支持也比较完善。对于 es的支持则有些差强人意,官方给的支持是只能写 es,也有资料表明可以使用 kettle运行 ssh命令的功能来读取 es。
前面提到了 kettle有 spoon, pan, kitchen, carte等四个核心组件,其中 spoon就是 kettle的可视化模块,以客户端的形式存在。
spoon提供了很多核心对象,一些常用的如下:
输入
CSV文件输入、JSON input、表输入、Excel输入、LDAP 输入、LDIF 输入、YAML 输入
输出
Access 输出、Excel输出、插入/更新、数据同步、JSON output、LDAP 输出、SQL 文件输出
转换
Add a checksum、Concat fields、值映射、列拆分多行、列转行、去除重复记录、增加常量、字符串替换
脚本
Java 代码、JavaScript代码、Rules executor、公式、执行SQL脚本、正则表达式
Big Data
HBase input/output、Hadoop file input/output、MongoDB input/output、SSTable output
批量加载
Elastic bulk insert、Greenplum load、MySQL 批量加载、Oracle 批量加载
加密
PGP decrypt/encrypt stream、对称加密、生成秘钥
另外,在实际使用过程中,界面偶尔会出现卡死的现象(win7),只能重启程序。
kettle提供了相当多的数据转换算子,3.2节只是列出了部分转换算子,整体来看基本能满足日常的数据转换需求,如果不能满足的还可以编写 Java代码或者 JavaScript代码实现。
类似 datax,kettle也是支持插件的,比如 kettle官方提供的 es批量写入插件不支持 7.x版本的 es,可以从 github拉取其 es插件源码进行修改并替换。
以编写 kettle数据库插件为例,需要继承 BaseDatabaseMeta类,并实现 DatabaseInterface接口,如下:
public class DaMengDatabaseMeta extends BaseDatabaseMeta implements DatabaseInterface {
private static final String STRICT_BIGNUMBER_INTERPRETATION = "STRICT_NUMBER_38_INTERPRETATION";
@Override
public int[] getAccessTypeList() {
return new int[] { DatabaseMeta.TYPE_ACCESS_NATIVE, DatabaseMeta.TYPE_ACCESS_JNDI };
}
}
部署 kettle同样非常简单,预先搭建好 JDK1.8的环境,然后解压已编译好的 kettle安装包即可。
如果是从源码安装,则除了上述要求外还要准备好 Maven 3.x的环境。
| 名称 | 诞生时间 | GitHub流行度 | 数据源 | 界面 | 数据转换 | 扩展性 |
|---|---|---|---|---|---|---|
| DataX | 2018 | 12.1k stars, 54 contributors | 关系数据库较好,大数据存储较好,es较差,支持时序数据库 | 一般 | 一般 | 非常好 |
| Kettle | 2005 | 6.1k stars, 206 contributors | 关系数据库非常好,大数据存储较好,es较差 | 较好 | 较好 | 较好 |
datax比较年轻,且社区活跃度非常高,扩展性非常好,又属于国产化,但是数据转换算子较少,只能对数据做简单的转换,需要较大的开发量。
kettle胜在发展时间长,功能相对更加完善,特别是它的转换类算子非常多,但是架构老化,扩展性弱一些,且界面是以 客户端的形式提供,而不是浏览器页面。
datax和 kettle各有优劣,如果开发资源足够,对性能要求高,推荐使用 datax。反之,如果追求开箱即用,功能完备,就更推荐使用 kettle。
深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal
深度学习12.CNN经典网络VGG16一、简介1.VGG来源2.VGG分类3.不同模型的参数数量4.3x3卷积核的好处5.关于学习率调度6.批归一化二、VGG16层分析1.层划分2.参数展开过程图解3.参数传递示例4.VGG16各层参数数量三、代码分析1.VGG16模型定义2.训练3.测试一、简介1.VGG来源VGG(VisualGeometryGroup)是一个视觉几何组在2014年提出的深度卷积神经网络架构。VGG在2014年ImageNet图像分类竞赛亚军,定位竞赛冠军;VGG网络采用连续的小卷积核(3x3)和池化层构建深度神经网络,网络深度可以达到16层或19层,其中VGG16和VGG
目录0专栏介绍1平面2R机器人概述2运动学建模2.1正运动学模型2.2逆运动学模型2.3机器人运动学仿真3动力学建模3.1计算动能3.2势能计算与动力学方程3.3动力学仿真0专栏介绍?附C++/Python/Matlab全套代码?课程设计、毕业设计、创新竞赛必备!详细介绍全局规划(图搜索、采样法、智能算法等);局部规划(DWA、APF等);曲线优化(贝塞尔曲线、B样条曲线等)。?详情:图解自动驾驶中的运动规划(MotionPlanning),附几十种规划算法1平面2R机器人概述如图1所示为本文的研究本体——平面2R机器人。对参数进行如下定义:机器人广义坐标
网站的日志分析,是seo优化不可忽视的一门功课,但网站越大,每天产生的日志就越大,大站一天都可以产生几个G的网站日志,如果光靠肉眼去分析,那可能看到猴年马月都看不完,因此借助网站日志分析工具去分析网站日志,那将会使网站日志分析工作变得更简单。下面推荐两款网站日志分析软件。第一款:逆火网站日志分析器逆火网站日志分析器是一款功能全面的网站服务器日志分析软件。通过分析网站的日志文件,不仅能够精准的知道网站的访问量、网站的访问来源,网站的广告点击,访客的地区统计,搜索引擎关键字查询等,还能够一次性分析多个网站的日志文件,让你轻松管理网站。逆火网站日志分析器下载地址:https://pan.baidu.
LL库和HAL库简介LL:Low-Layer,底层库HAL:HardwareAbstractionLayer,硬件抽象层库LL库和hal库对比,很精简,这实际上是一个精简的库。LL库的配置选择如下:在STM32CUBEMX中,点击菜单的“ProjectManager”–>“AdvancedSettings”,在下面的界面中选择“AdvancedSettings”,然后在每个模块后面选择使用的库总结:1、如果使用的MCU是小容量的,那么STM32CubeLL将是最佳选择;2、如果结合可移植性和优化,使用STM32CubeHAL并使用特定的优化实现替换一些调用,可保持最大的可移植性。另外HAL和L
一、机器人介绍 此处是基于MATLABRVC工具箱,对ABB-IRB-1200型号的微型机械臂进行正逆向运动学分析,并利Simulink工具实现对机械臂进行具有动力学参数的末端轨迹规划仿真,最后根据机械模型设计Simulink-Adams联合仿真。 图1.ABBIRB 1200尺寸参数示意图ABBIRB 1200提供的两种型号广泛适用于各作业,且两者间零部件通用,两种型号的工作范围分别为700 mm 和 900 mm,大有效负载分别为 7 kg 和5 kg。 IRB 1200 能够在狭小空间内能发挥其工作范围与性能优势,具有全新的设计、小型化的体积、高效的性能、易于集成、便捷的接
目录一.大致如下常见问题:(1)找不到程序所依赖的Qt库version`Qt_5'notfound(requiredby(2)CouldnotLoadtheQtplatformplugin"xcb"in""eventhoughitwasfound(3)打包到在不同的linux系统下,或者打包到高版本的相同系统下,运行程序时,直接提示段错误即segmentationfault,或者Illegalinstruction(coredumped)非法指令(4)ldd应用程序或者库,查看运行所依赖的库时,直接报段错误二.问题逐个分析,得出解决方法:(1)找不到程序所依赖的Qt库version`Qt_5'
我想使用ruby-prof和JMeter分析Rails应用程序。我对分析特定Controller/操作/或模型方法的建议方法不感兴趣,我想分析完整堆栈,从上到下。所以我运行这样的东西:RAILS_ENV=productionruby-prof-fprof.outscript/server>/dev/null然后我在上面运行我的JMeter测试计划。然而,问题是使用CTRL+C或SIGKILL中断它也会在ruby-prof可以写入任何输出之前杀死它。如何在不中断ruby-prof的情况下停止mongrel服务器? 最佳答案
进行这种深度检查的最佳方法是什么:{:a=>1,:b=>{:c=>2,:f=>3,:d=>4}}.include?({:b=>{:c=>2,:f=>3}})#=>true谢谢 最佳答案 我想我从那个例子中明白了你的意思(不知何故)。我们检查子哈希中的每个键是否在超哈希中,然后检查这些键的对应值是否以某种方式匹配:如果值是哈希,则执行另一次深度检查,否则,检查值是否相等:classHashdefdeep_include?(sub_hash)sub_hash.keys.all?do|key|self.has_key?(key)&&ifs
我有一个Rails应用程序,它从WorldWeatherOnlineAPI获取响应。我正在使用rest-clientgem,响应采用JSON格式。我使用以下方法解析响应:parsed_response=JSON.parse(response)parsed_response显然是一个散列。我需要的数据是哈希内的字符串,数组内的哈希,另一个数组内的哈希,另一个哈希内的另一个哈希内的字符串。最内层的嵌套散列在["hourly"]中,这是一个由8个散列组成的数组,每个散列有20个键,拥有各种天气参数的字符串值。数组中的每个哈希值都是一天中的不同时间(预测是每三小时一次,3*8=24小时)。因此