简介:Kettle 6.0(Pentaho Data Integration)是一款成熟的开源 ETL 工具,面向数据仓库工程师、数据分析师及数据集成开发者,用于解决多源数据抽取、清洗、转换与加载等核心问题。该资源为完整发行压缩包,共 2000 个文件,以 1353 个 jar 插件库为主,另含 200 个 ktr 转换、19 个 kjb 作业、82 个 xml 配置、23 个 properties 及 bat/sh 启动脚本等,包体约 849.79 MB,可直接部署运行。目前已有 607 人学习浏览。压缩包内置 Spoon、Kitchen、Carte 等可执行程序,连同示例转换、数据库驱动、日志及配置文件,能帮助用户快速搭建 Kettle 6.0 环境,熟悉作业调度、并行处理、数据源连接和插件扩展机制。对于正在构建数据仓库或准备 ETL 开发实战的读者,这份资源兼具学习参考与生产部署价值。 做数据开发这么多年,手头用的工具换了一茬又一茬,但ETL这块,Kettle 6.0在我心里的位置一直很稳。这工具虽然名字听着老旧,版本号停在6.0也好多年了,但直到今天,很多公司的生产环境核心数据同步、清洗、转换,跑的还是它。我甚至见过有同行从Kettle 5.x一路用到8.x,最后又退回6.0的项目,理由很简单:稳定、够用、社区资料多,遇到问题搜一搜基本都有答案。
这篇东西我不打算写成官方文档的复读机,而是以一个实际用过、也被它坑过、最终把它理顺了的从业者身份,把Kettle 6.0的完整使用链路、核心设计思路和日常运维中的真实体验,一次说清楚。适用人群包括刚接触ETL的数据新人,被领导安排接手老同步任务的开发,以及正在做技术选型、纠结要不要在2024年还上新项目用6.0的架构师。你可以把它当作一份带经验的实战手册来看,配合你的实际业务去调整使用。
1. 内容整体设计与思路拆解
1.1 为什么Kettle 6.0至今还有大量存量用户
先聊一个很多人私下问过我的问题:Kettle都已经出了8.x、9.x,甚至改名叫Pentaho Data Integration了,为什么还有大量项目跑在6.0上?
答案不复杂,三个字:换不起。
Kettle的作业和转换文件(.kjb和.ktr)虽然理论上有向后兼容,但实际在跨大版本迁移时经常遇到插件差异、数据库驱动不兼容、界面配置项变化导致的执行行为不一致。我们曾经做过一次从6.0升到8.2的验证,几十个作业里有一半需要手工调整配置,有几个自定义的JavaScript步骤在8.x里直接跑挂。迁移成本核算下来,相当于把核心链路重做一遍。对业务方来说,数据同步每天都要跑,夜间批处理窗口就那几个小时,谁敢拍着胸脯说“停两周,我们换个新版”?
Kettle 6.0自己也很争气。它的核心功能——基于图形化的ETL流程设计、丰富的步骤组件、多数据库支持、集群与分区能力——在6.0版本已经非常成熟。对于绝大多数企业的数据量级(每天几百万到几千万行),单机或简单集群模式完全能扛住。加上6.0对JDK 1.7/1.8兼容良好,老服务器上跑起来毫无压力。说白了,它就是ETL工具里的“老款丰田”,皮实耐用,配件好找,修车师傅都会修。
1.2 从整体架构看Kettle 6.0的典型应用场景
聊完版本选择,再来看Kettle 6.0在实际项目中到底扮演什么角色。
我把Kettle的典型应用场景分成四大类,你可以对照自己的业务需求去套:
第一类:异构数据源之间的批量同步。比如把Oracle库里的订单表同步到MySQL数仓,或者把SQL Server里的业务数据推送到Hadoop。这是Kettle最基础的活,通过“表输入”和“表输出”两个步骤就能搞定,中间可以加字段映射、类型转换。Kettle 6.0对主流数据库的支持很全——Oracle、MySQL、SQL Server、PostgreSQL、DB2、Sybase,以及通过JDBC/ODBC桥接的其他数据源,都能直接连。
第二类:数据清洗与质量校正。源系统里的数据往往脏得离谱——空值、重复值、格式混乱、编码错误。Kettle的“过滤记录”“字段选择”“字符串替换”“值映射”等步骤,就是干这个的。我见过一个做会员数据治理的项目,几千万条会员记录用Kettle清洗,把手机号格式统一、去重、补全省市区,一个转换跑完,数据质量从惨不忍睹提升到能直接进数仓。
第三类:定时调度与复杂工作流编排。单个转换只能解决“一段数据处理”,但真实业务往往是多步骤串行或并行的。Kettle作业(Job)可以编排多个转换的执行顺序,支持条件判断、循环、发送邮件、SFTP下载、文件校验等。每天凌晨2点先同步增量数据,再跑汇总存储过程,最后导出报表文件发到指定目录——这种场景用Kettle作业来实现,非常顺手。
第四类:轻量级数据中台的底座。很多中小公司没有财力上Informatica、DataStage这类商业ETL工具,也不愿意用代码写一堆Python脚本去维护。Kettle 6.0以极低的学习成本和部署门槛,承担了从业务库到数仓、从数仓到应用库的全部数据搬运工作。说白了,它就是这帮团队的数据基础设施。
2. 核心细节解析与实操要点
2.1 作业与转换的核心区别:别把流程画成一锅粥
很多人刚开始用Kettle,最容易犯的错就是分不清“作业”(Job)和“转换”(Transformation),把所有的步骤全部堆在一个转换里,最后整个图大得滚动条都拖半天。
这里我给出自己多年使用的划分原则:转换负责“数据流”,作业负责“控制流”。转换里跑的是“行数据”的处理——从表输入查数据,经过过滤、转换、输出,数据像水一样流过一个个步骤。作业里跑的是“任务节点”的调度——先执行A转换,成功后再执行B作业,失败了就发告警邮件。
举个例子。你有一个需求:每天从业务库同步订单表到数仓,同步前先truncate目标表,同步完成后再执行一个存储过程刷新汇总表。这个流程如果全塞在一个转换里,truncate和存储过程的调用会非常别扭,而且没法做“失败就停止后续步骤”的控制。正确做法是建一个作业,里面放三个作业项:先是一个“SQL脚本”作业项执行truncate,然后是一个“转换”作业项跑同步数据,最后再来一个“SQL脚本”作业项执行存储过程。每个作业项之间用连线连接,双击连线可以设置“成功时执行下一个”还是“失败时执行下一个”。
再补充一个容易忽略的点:作业项之间传递数据是受限的,作业项之间传递数据是受限的,作业的结果(比如影响行数、执行状态)能传递,但数据流本身不行。如果两个步骤之间需要传递数据集,必须用转换内部的步骤连接,或者借助中间表/临时文件。
2.2 命名规范与变量体系:Kettle项目后期维护的救命稻草
Kettle项目做到后期,最大的痛苦不是写不出来,而是看不懂自己三个月前画的是什么。变量命名和作业组织规范,这时候就显得格外重要。
Kettle的变量体系分为三层:全局变量、作业内变量、转换内变量。
全局变量在kettle.properties文件里定义,作用于整个JVM实例,适合存放数据库连接串、文件根目录、环境标识这类全局配置。作业内变量通过“设置变量”作业项定义,可以在作业内多个转换之间共享。转换内变量则通过“复制记录到结果”“设置变量”等步骤实现,作用域限于单个转换。
我这里给你一个经过实战检验的命名规范模板:
# 环境标识 ENV=prod # 数据源连接信息 DB_ERP_IP=192.168.1.10 DB_ERP_PORT=3306 DB_ERP_NAME=erp_db DB_ERP_USER=etl_user DB_ERP_PASS=encrypted:xxxx # 文件路径 DATA_ROOT=/data/etl DATA_ARCHIVE=/data/etl/archive DATA_TMP=/data/etl/tmp # 同步参数 SYNC_BATCH_SIZE=10000所有转换里的数据库连接方式,一律用${DB_ERP_HOST}这种变量引用,不许出现硬编码的IP。所有输出文件路径,都以${DATA_ROOT}作为前缀。这样做的直接好处是:开发环境、测试环境、生产环境之间切换,只需要改一份kettle.properties,所有作业和转换无需任何调整。
对了,kettle.properties文件的位置在Kettle安装目录下的.kettle文件夹里,Linux下是~/.kettle/kettle.properties,Windows下是C:\Users\<用户名>\.kettle\kettle.properties。改完要重启Spoon才能生效,这个坑不少人踩过。
2.3 数据库连接与驱动兼容性:80%的报错都出在这里
Kettle 6.0的数据库连接配置,本质上就是包装了一层JDBC。你在“数据库连接”里选择数据库类型,填IP、端口、库名、用户名、密码,Kettle会调用相应的JDBC驱动去建立连接。
这里最容易出的问题就是驱动版本不匹配。Kettle 6.0自带的驱动往往比较旧,比如自带的MySQL驱动只支持到MySQL 5.x,如果你连的是MySQL 8.x,就会报“Public Key Retrieval is not allowed”或者“Communications link failure”。解决办法是去MySQL官网下载对应版本的Connector/J驱动jar包,放到Kettle安装目录的lib文件夹下,重启Spoon即可。
不同数据库的驱动放置方式稍有区别,我整理了一份常用对照表:
| 数据库类型 | 驱动类名 | 常用jar包 | 注意点 |
|---|---|---|---|
| MySQL | com.mysql.jdbc.Driver | mysql-connector-java-5.1.49.jar | MySQL 8.x建议用8.0.x驱动 |
| Oracle | oracle.jdbc.OracleDriver | ojdbc6.jar / ojdbc8.jar | 11g用ojdbc6,12c+建议ojdbc8 |
| SQL Server | com.microsoft.sqlserver.jdbc.SQLServerDriver | mssql-jdbc-7.2.2.jre8.jar | 注意JRE版本要匹配 |
| PostgreSQL | org.postgresql.Driver | postgresql-42.2.5.jar | 9.6以上建议42.x驱动 |
| DB2 | com.ibm.db2.jcc.DB2Driver | db2jcc4.jar | 老版本有db2jcc.jar的兼容问题 |
连接配置方面还有一个技巧:URL里的参数不要裸奔。比如MySQL连接建议加上useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai,避免因为时区或编码问题导致数据错乱。配置好以后,点击“测试”按钮,如果弹窗提示连接成功,再进入下一步。
3. 实操过程与核心环节实现
3.1 第一个转换:从零搭建一条订单增量同步链路
理论讲再多,不如亲手画一个转换。下面我以一个最常见、也最典型的场景作为案例:从MySQL业务库同步订单增量数据到PostgreSQL数仓。增量字段用的是订单的update_time。
打开Spoon,新建一个转换,按以下步骤操作:
第一步:添加表输入步骤。在左侧“核心对象”树的“输入”分类下,找到“表输入”,拖到画布上。双击打开配置,选择或新建一个MySQL数据库连接。SQL查询语句写:
SELECT order_id, user_id, order_amount, order_status, create_time, update_time FROM t_order WHERE update_time > ?注意这里的问号是参数占位符。勾选下方的“替换SQL语句里的变量”,然后在“插入数据步骤”处选择“获取变量”,填入变量名LAST_UPDATE_TIME,默认值写'1970-01-01 00:00:00'。这样每次运行时,Kettle会用变量值替换SQL里的问号,实现增量抽取。这个设计比把时间硬编码在SQL里要优雅得多,后续接调度系统只需要传参。
第二步:添加字段选择与转换。从“转换”分类下拖入“字段选择”,双击配置。在“选择和修改”页签里,把不需要的字段移除,或者在“元数据”页签里调整字段类型。比如order_amount在MySQL里是DECIMAL(10,2),到了PostgreSQL里可能希望映射成NUMERIC(10,2),在这里就可以指定。这一步我建议别图省事跳过,因为源库和目标库的字段类型往往有差异,提前在这里统一掉,省得表输出步骤报错。
第三步:添加表输出步骤。从“输出”分类下拖入“表输出”。双击配置,选择或新建PostgreSQL连接。目标表选择ods_order。“提交记录数量”我建议填1000到5000之间,这是分批批量提交的条数,能显著降低数据库提交频率、提升写入性能。关键一步:勾选“指定数据库字段”,进入“数据库字段”页签,手动映射源字段和目标字段的对应关系。如果你让Kettle自动映射,它有时候会因为字段名不一致或者类型不匹配给你报错。
第四步:连接步骤并运行。用鼠标从“表输入”底部的输出箭头拖到“字段选择”的输入口,同样连接“字段选择”和“表输出”。点击工具栏上的“运行”按钮,选择“本地执行”,观察底部“执行结果”面板中的日志。如果一切顺利,你会看到类似“Finished processing, total rows: 520”的日志输出。
3.2 作业编排:定时任务与异常通知的完整配置
单条数据链路搞定后,还需要一个作业来定时调度它,并且在失败时通知值班人员。
新建一个作业,按以下方式编排:
第一个作业项:设置变量。从“作业”分类下找到“设置变量”,拖入画布。配置变量名LAST_UPDATE_TIME,值类型选“当前日期”,格式写yyyy-MM-dd HH:mm:ss,增量偏移设为-2 hours。这样每次运行时,变量会自动取当前时间往前推2小时的时间点。为什么是2小时?因为很多源系统的数据写入有延迟(比如订单状态异步回调),取2小时前的增量能避免漏数据。这个偏移量你可以根据业务容忍度自行调整,我见过有人设15分钟的,也见过有人设1天的。
第二个作业项:执行转换。从“作业”分类下拖入“转换”,双击浏览选中刚才设计的同步转换文件(.ktr)。这里不需要额外配置,转换会自动从作业继承变量。
第三个作业项:校验结果并发送通知。从“作业”分类下找到“校验字段的值”,拖入画布,把它接到“转换”的“成功”出口上。配置要检查的值为${LAST_UPDATE_TIME},期望值类型选择“字符串”,比较规则可以选“不小于”之类的(这里是给你提供一个占位思路,按实际需求定)。再接一个“发送邮件”作业项到“校验”的成功出口上,配置SMTP服务器、发件人、收件人,邮件主题写“订单同步任务失败”。
连线时注意:从“转换”到“校验”的那条线上,双击可以设置“结果”为“成功”时才往下走。这样设计之后,整个作业的执行逻辑就是:设置增量时间 -> 跑同步转换 -> 若转换成功,检查结果变量 -> 若结果异常,发告警邮件。
这套作业在Kettle里点击“运行”就能手动触发;要定时调度,可以用Windows任务计划程序或Linux crontab调用Kettle的Kitchen命令行工具。命令大概是:
/opt/data-integration/kitchen.sh -file:/opt/etl/jobs/sync_order.kjb -level:Basic >> /var/log/kettle/sync_order.log 2>&1-level参数建议日常运行用Basic级别记录日志,排查问题时再临时改成Debug,避免日志刷爆磁盘。
3.3 性能调优:从慢到快的一次实战优化记录
这里分享一次真实优化案例。有一张日增量约200万行的订单明细表,最初同步到PostgreSQL需要约40分钟,已经挤占了后面的作业窗口。通过三个调整,最终压缩到9分钟以内。
第一个调整:表输入加翻页游标。如果SQL里有ORDER BY update_time,Kettle 6.0默认是一次性把所有结果集拉到客户端再做处理。200万行数据全量拉到本地,内存和网络开销都很大。解决办法是在“表输入”步骤的高级选项里勾选“使用游标”,并设置游标大小(比如50000),让Kettle以分批读取的方式从数据库拉数。
第二个调整:表输出开批量提交。前面提到“提交记录数量”要设置,这里具体说一下为什么。Kettle 6.0默认的提交记录数量是1000,这个值对大多数场景够用,但如果有大批量写入需求,可以调到5000甚至10000。Batch提交能显著减少数据库的事务开销和网络往返次数。注意别调得太极端,比如设成100000,万一中途出错回滚代价会很大,内存也可能被撑爆。
第三个调整:表输出关闭“自动提交”并启用PreparedStatement。在“表输出”步骤的数据库连接属性里,把useServerPrepStmts设为true,rewriteBatchedStatements设为true。这两个参数是MySQL和PostgreSQL JDBC驱动支持的连接参数,开启后驱动的批量插入性能会有量级提升。如果连接是MySQL,还可以把useCompression=true加上,在带宽紧张的环境里也能省点时间。
调完之后的效果对比:
| 项目 | 优化前 | 优化后 |
|---|---|---|
| 同步总耗时 | 40分钟 | 9分钟 |
| 内存峰值 | 2.5GB | 900MB |
| 目标库CPU占用 | 85% | 40% |
| 源库IO压力 | 高 | 中 |
4. 常见问题与排查技巧实录
4.1 数据库连接失败的几类典型原因
No database connection found之类的问题,是Kettle新手遇到最多的报错。虽然报错信息长得很吓人,但原因通常就那么几类,排查起来有章可循。
第一类是驱动缺失或版本不匹配,前面已经详细说过,解决方式就是确认库类型、去官网下对应版本的jar包、放进lib目录、重启Spoon。第二类是网络不通,比如防火墙挡了数据库端口,或者数据库监听地址只绑定了本机。用telnet 数据库IP 端口测一下,十秒钟就能定位。第三类是账号权限问题,Kettle连接报“Access denied for user”时,去数据库管理端查一下这个账号是否有从Kettle所在主机远程登录的权限。MySQL里'etl_user'@'localhost'和'etl_user'@'%'是两个完全不同的账号。
还有一个很隐蔽的坑:数据库连接配置页面里的“选项”页签,有时会默认带上驱动无法识别的参数。曾经我遇到一个PostgreSQL连接,报错提示“Unknown parameter: sslmode”,排查半天发现是Kettle的PostgreSQL连接自动附加了sslmode=require参数,而目标库不支持SSL。解决方式是在连接URL里明确指定sslmode=disable,覆盖默认参数。
4.2 内存溢出与执行卡死的应对策略
Kettle 6.0默认的JVM堆内存设置比较保守(我记得默认是-Xmx512m),数据量稍大就会出现OutOfMemoryError。这个问题的解决思路分三步。
第一步,修改Spoon启动脚本。Windows下是Spoon.bat,Linux下是Spoon.sh,找到类似-Xmx512m的参数,改大。我自己在16GB内存的机器上,通常设为-Xmx4096m。如果是定时作业用Kitchen跑,同样要修改Kitchen.bat或Kitchen.sh里的内存参数。
第二步,作业设计上避免“大爆炸”。不要试图把一个几十G的文件一次性读进内存处理,Kettle的“表输入”步骤默认就会这样做。合理的做法是分页读取、分批处理,或者用“排序记录”的“内存”模式改成“临时文件”模式,让硬盘分担内存压力。
第三步,注意Kettle 6.0的并发执行机制。如果作业里设置了并行执行多个转换,每个转换默认是独立线程跑在同一个JVM里,内存是共享的。所以说,修改启动脚本的内存参数时,要给并发场景留足余量,不是设个4GB就能随意霍霍的。
4.3 数据错乱与乱码问题的排查路径
中文乱码可以说是ETL开发遇到频率最高的“玄学”问题。我在Kettle 6.0里总结出一套排查路径,按顺序走一遍,基本能定位:
先看源端配置。MySQL连接URL里有没有指定characterEncoding=utf8?没有的话,Kettle默认用平台字符集读取,如果平台是Windows中文环境(GBK),读UTF-8数据就直接乱掉。统一在JDBC URL里强制指定编码,是第一步。
再看Kettle转换里的“字段选择”步骤。如果字段元数据里的“格式”被强制设成了某种编码(比如GBK),而实际数据是UTF-8,转换输出就会乱。检查元数据页签中每个字段的编码设置,没必要的强制编码全部改为“无”。
再看目标端。PostgreSQL数据库本身的字符集,以及表级别的字符集,都需要和写入的数据编码保持一致。如果目标表是非UTF-8编码,Kettle写入时即使数据是好的,落库后也会变乱码。
最后一招,用“文本文件输出”步骤临时把数据导成CSV,用16进制编辑器或者直接文本打开看文件字节。这一步能帮你区分“转换过程中乱了”还是“展示乱了”。数据进库后再乱,跟Kettle就没关系了,那是数据库或业务系统展示层的问题。
4.4 增量同步重复与丢失数据的避坑指南
增量同步是ETL里最容易埋雷的区域,搞不好就出现“数据重复”或者“数据少了”。我最常遇到、也希望你避免的是这几种情况:
重复数据案例:用update_time >= 上次增量时间做SQL查询,但在同一个时间戳上,刚好有新数据写入和旧数据更新的并发发生,上一轮同步和这一轮同步会把同一条记录都捞走。解决思路是:增量时间字段不要用update_time这种业务字段,优先用自增ID或数据库层面的binlog/redo log标记;如果只能用时间字段,检查业务的高水位机制,或者把同步时间往前多退几分钟,配合目标表的唯一键去重。
丢数据案例:作业失败后手动重跑,但增量时间变量已经被更新到了新值,导致重跑只覆盖了上次失败到现在的一小段区间,中间的数据被跳过了。解决思路是:在作业开始执行同步之前,把原始增量时间记录到一张本地状态表,作业执行完后再更新状态;如果失败重跑,从状态表里读回上次的开始时间,从头跑。这是典型的“先写状态、再跑任务”的思路,Kettle里可以用“SQL脚本”作业项和“表输入”步骤配合实现。
拆库导致主键冲突案例:多分片数据库同步到同一个目标表,各分片的主键范围重叠。解决思路是,在源端查询时就对主键做位运算或字符串拼接,比如CONCAT(shard_id, '_', order_id),在“字段选择”步骤里把生成的新主键映射到目标表主键字段。
5. 将Kettle 6.0嵌入自动化运维体系
5.1 命令行工具链:Spoon只是冰山一角
很多人用Kettle只停留在图形界面,事实上生产环境的自动化运维,核心靠的是它附带的几个命令行程序。除了前面提到的Kitchen用于执行作业,还有Pan用于执行转换,以及Carte用于分布式执行。
我在生产环境里的做法是:开发用Spoon,测试用Pan/Kitchen,生产调度全部走命令行配合zabbix或自研的调度平台。每当有新的或修改后的作业,先在测试服务器上通过Pan/Kitchen命令行跑通,确认无误后,把作业文件通过Git发布到生产服务器,再更新调度系统的执行命令。这样整个过程可回滚、可追踪、可审计。
命令行执行转换的Pan命令模板:
/opt/data-integration/pan.sh -file:/opt/etl/trans/clean_order.ktr -level:Basic -param:LAST_UPDATE_TIME=2024-01-01-00:00:00-param参数可以直接从外部给Kettle变量传值,这使得同一套转换可以被不同的调度任务重用以不同的参数跑,无需复制多份文件。
5.2 监控与日志:让ETL任务有迹可循
Kettle 6.0自带日志功能,但默认配置下日志比较分散,不好统一查看。我的习惯是让所有作业在运行时把日志落盘,文件名带时间戳:
/opt/data-integration/kitchen.sh -file:/opt/etl/jobs/sync_order.kjb -level:Basic -logfile:/var/log/kettle/sync_order_$(date +%Y%m%d_%H%M%S).log同时,在每个转换里加一个“写日志”步骤,把关键步骤处理的行数、耗时打印出来,让同步过程透明化、可审计。比如表输入完成后,写一行日志“抽取完成,行数:5200”;表输出完成后,写一行“写入完成,行数:5200”。这样一旦目标库数据和源库对不上,直接看日志就能定位到是哪个环节丢了行。
监控体系的推荐做法是,把Kettle作业的执行结果写入一张etl_job_log表(表结构可以自定义:作业名、开始时间、结束时间、状态、影响行数、错误信息),再用Grafana或自研DashBoard去展示和告警。这样整个运维数据都是企业内部的,不依赖Kettle自身的控制台,非常可控。以下是一段创建日志表的SQL参考:
CREATE TABLE etl_job_log ( id BIGINT AUTO_INCREMENT PRIMARY KEY, job_name VARCHAR(128), status VARCHAR(16), start_time DATETIME, end_time DATETIME, affected_rows BIGINT, error_message TEXT, log_date DATE );6. 经验沉淀与长期维护建议
Kettle 6.0这个工具本身很简单,真正容易失控的是随着时间推移,作业数量从几个长到几百个之后的维护问题。到那个阶段,比画图能力更重要的,是管理能力。
我的建议是:每个作业和转换文件头部,用“注释”步骤写清楚业务含义、负责人、创建日期、修改记录。定期梳理线上运行的作业清单,下线没人用的“僵尸作业”。如果团队有多个人协作开发,建立一个约定:任何人修改共享的数据库连接或变量定义,必须同步更新团队维护的一份说明文档。
另外一个容易被忽略的点:Kettle 6.0的作业依赖的是jdk版本,生产环境的JDK升级要慎重。我遇到过开发机用JDK 1.8跑得好好的作业,部署到线上JDK 1.7环境后,某些步骤报NoSuchMethodError。最终的解决方式是给生产服务器单独装一个JDK 1.8,用PATH或启动脚本里的JAVA_HOME单独指定,才彻底消除问题。
根据我个人的经验,不管项目里是用Kettle 6.0还是别的ETL工具,数据同步这类活得老老实实、规规矩矩地做,把边界条件、异常分支都考虑到,比追求花哨的新特性和性能调优更重要。Kettle 6.0的价值不在于它多先进,而在于很多团队用它在安静地支撑着每天几百万人看的报表和后台数据。把稳定性做扎实,比什么版本都吃香。
本文还有配套的精品资源,点击获取