跳到主要内容

Kettle工具使用

· 阅读需 7 分钟

最近使用了Kettle这款ETL工具、对于多数据源进行数据之间的同步,迁移,转换,修正等功能进行了解与使用。

做业务系统时经常会遇到这样的需求:老系统的数据要搬到新系统,两边表结构不一样;或者要把多个库的数据汇总到一个报表库里,字段名、状态码、数据类型都对不上。这类活如果全靠手写脚本,SQL 加导入导出程序写一堆,改一次需求就要改一次代码,维护起来很累。ETL 工具解决的就是这个问题——把抽取(Extract)、转换(Transform)、加载(Load)这三步流程化、可视化,Kettle 是这类工具里比较有代表性的一个开源实现。

Kettle-水壶、顾名思义就是把各种数据源中的表数据都当做水流、从多个水流汇总、分流、解析的工具。它是一款开源的数据集成工具,它提供了丰富的数据处理功能,包括数据抽取、转换和加载(ETL)等。Kettle的核心是一个基于图形化界面的设计工具,用户可以通过简单的拖拽和连接操作来构建数据处理流程。Kettle还提供了强大的数据处理引擎,支持多线程和分布式处理,可以高效地处理大规模数据。同时,Kettle还支持多种数据来源和目标,包括关系型数据库、文件、Web服务等,可以方便地与各种数据源进行集成。Kettle还提供了丰富的插件机制,用户可以自定义开发插件,扩展Kettle的功能。总之,Kettle是一款功能强大、易用性好、可扩展性强的数据集成工具,广泛应用于数据仓库、商业智能、数据分析等领域。

工作方式

Kettle 里有两个基本概念:转换(Transformation)和作业(Job)。转换负责具体的数据流处理,由一个个步骤(Step)用连线(Hop)串起来,数据以行为单位在步骤之间流动;作业则是更上层的调度单位,可以把多个转换按顺序或条件组织起来执行。图形化设计器里画出来的流程,保存后就是一份 XML 描述文件,既可以在设计器里直接跑,也可以交给命令行工具在服务器上定时执行。

每个步骤在运行时是独立线程,上游步骤产出一行数据就往下游推一行,整个流程是流水线式的,不需要等前一步全部处理完。这也是它能处理较大数据量的原因之一——数据不会一次性全部装进内存。

无需任何编程、只需要手动拖动配置组件。即可完成复杂的数据处理功能。Kettle对于CDC层面来说,是基于查询的方式进行数据的读取与转换,适合一次性的数据迁移与转换。不能用于实时性要求较高场景。

这里稍微展开一下:CDC(Change Data Capture,变更数据捕获)常见有两类实现思路。一类是基于日志的,比如解析 MySQL 的 binlog,数据库每发生一次变更就能近乎实时地捕获到;另一类是基于查询的,靠定时执行 SQL、比对时间戳或自增主键来找出变化的数据。Kettle 属于后者,它拿到的是查询那一刻的快照,两次查询之间的中间状态是感知不到的,删除操作也不容易发现。所以它适合做一次性迁移、定时批量同步这类场景,要做实时同步就得换基于日志的方案。

数据迁移小例子

kettle 提供了相当多的组件可以应付不同场景的数据转移,导入,导出,值映射等功能。并可以数据导出excel文件。上图就是一个典型的迁移流程:从源库查出数据,经过中间几步清洗转换,最后写入目标库。下面按流程中出现的顺序说说这些常用组件。

表输入:从数据库中执行sql从而查询出导入数据。这是整个流程的起点,写一条 SELECT 语句,查询结果的每一行都会作为数据流的一行往下游传递。SQL 里可以用变量做参数化,方便同一个转换在不同环境下复用。

表输出:从Kettle中运行得到最终结果集向表中输出数据。它是流程的终点,把流入的每一行数据 INSERT 到目标表。可以配置批量提交的条数,批量写入比逐条提交快得多。

字段名称完善:可赛选数据列,设置列别名等。源表和目标表字段名往往不一致,比如老库叫 user_name 新库叫 username,在这一步统一改名,后面的步骤就不用再关心源表的命名了。不需要的列也可以在这里直接丢弃,减少后续步骤的处理量。

排序:可以根据数据字段进行排序。单独看用处不大,但它常常是为下一步服务的——Kettle 的合并类组件通常要求两路输入按关联字段有序,所以合并前一般要先各自排序。

数据合并:把两个不同来源的数据进行合并、类似于mysql join功能。两个表输入的数据流按指定字段关联到一起,跨库的表也能"join",这是纯 SQL 做不到的。前提如上所说,两路数据都要先按关联字段排好序。

值映射:很多数据库状态值1,2,3的状态码 在新数据库中可能为 4,5,6 则可以使用值映射进行值替换。本质上是一张配置在组件里的对照表,源值到目标值一一对应,还可以设置默认值兜住没有匹配上的情况。

字段修正:修正数据源的字段名称与数据类型。以方便迁移到新数据源中。典型场景是老库用字符串存日期、新库是 datetime 类型,或者数值精度需要调整,都在这一步转换掉,避免写入目标库时报类型错误。

新增、更新:对目标数据源执行新增数据操作。如果已有对应id则进行更新操作。也就是常说的 upsert:按指定的关键字段去目标表查找,查不到就插入,查到了就更新。做增量同步时用它代替表输出,可以让转换重复执行而不产生重复数据。

踩坑与注意

1)中文乱码:数据库连接的字符集要和库本身一致,MySQL 连接参数里最好显式指定编码,否则迁移完发现中文全是问号就要返工重来。

2)合并前忘记排序:数据合并类组件依赖输入有序,漏了排序步骤不一定报错,但关联结果会不对,这种问题比报错更难发现,务必核对结果行数。

3)批量提交与事务:表输出默认的提交条数可以调大来提速,但要想清楚失败后怎么办——中途出错时已提交的数据不会回滚,重跑前要么清空目标表,要么改用"新增、更新"组件保证幂等。

4)大表迁移:一条不带条件的 SELECT 全表拉取,对源库压力不小,尽量在业务低峰执行,或按主键、时间分批跑。

小结

合理使用Kettle 可以帮助我们简化对数据库的数据管理,在项目进行大版本变更时,数据库结构与新老数据做兼容处理时,Kettle就是不错的工具之一。它的定位很清楚:批处理式的数据搬运和清洗,图形化流程降低了维护成本,让这类一次性或周期性的数据任务不必再写一堆临时脚本。至于实时同步的需求,就交给基于日志的 CDC 方案去做,工具各司其职。

评论 / COMMENTS