1、前言:
最近项目准备上线,要先做一下并行,所以要把调用接口的请求 请求到生产环境的同时也请求到并行环境。我刚开始,写了一个程序,多线程去生产数据库(接口有记录表,记录请求报文)取到请求报文,然后再拼接成curl请求命令,请求到并行环境,结果跑了没半天就差点儿把生产数据库搞挂。原因是,我的程序每五分钟调用一次,调用会获取11个数据库连接,结果因为生产上数据量大,五分钟没有处理完成,另一个调度就调起来了,这样一下午累积下来,产生了上百个连接,生成cpu飙到了%90以上,触发了告警,领导收到了告警短信才发现了问题。
之后应领导要求,我的并行程序不能直接连接生产库,需要异步处理(需要数据库做中转),那么就涉及到一个如何获取生产数据库中的报文数据的问题。通过上网查询,大体有三个方案:
1.1 使用触发器
在接口报文记录表上添加一个触发器,每次请求的报文插入生产记录表的同时触发器插入到中转数据库。
优点:编程简单,只需要几行
缺点:会影响生产数据库性能,同时该触发器需要配合dblink,可能存在潜在危险。
-- 一个简单的oracle触发器
CREATE OR REPLACE TRIGGER MY_TGR
BEFORE INSERT ON jd.ims_json_soap_1_0
FOR EACH ROW--对表的每一行触发器执行一次,插入test_b的同时插入test_a
BEGIN
insert into cd.ims_json_soap_1_0(name,age,school,home,ext) values(:NEW.name,:NEW.age,:NEW.school,:NEW.home,:NEW.ext);
END;
1.2 使用canal
canal是阿里巴巴提供的一个开源工具,通过监听数据库binlog日志,解析出语句,然后执行,该程序对于mysql很友好,但是oracle(归档日志)貌似支持部分.太新的版本应该还不支持,这个还没有尝试。
1.3 使用kettle
kettle是一款国外的开源ETL工具,使用的时候只需要下载解压就可以使用,数据抽取速度可以达到每秒上万条数据的同步。
2、kettle的使用
2.1 下载安装kettle
我这里使用的是pdi-ce-7.1.0.0-12
2.2 表同步生成ktr文件
因为生产数据是实时有调用记录插入的,所以我的同步方案是增量同步。
通过目标表的最新时间到生产源表里面获取最新的记录
2.2.1 最终转换效果
2.2.2 MaxDate
获取目标表(中转数据库中的表)最大时间做为一个表输入。
2.2.3 常规(生产数据库)
注意下面的从步骤插入数据,sql语句中的问号会在执行的时候替换为下面的MaxData(该名字需要和上一步中的步骤名称保持一致)
2.2.4 表输出
这里其实还可以使用 插入/更新 但是这种方式相对慢一些,但是更灵活,可以自定义同步的字段,由于我这里表结构都是相同的,所以我采用表输出的方式,这样的效率更高。
最后按住shirt通过拖拉将两个输入和一个输出连接起来就可以了
我这里应为分表的关系有十张分表都需要同步,所以我复制了十个这样的转换。
2.3 执行ktr文件
转换过程
3、java整合kettle,通过程序调用执行ktr文件
由于我的需要放在服务器上去定时调度,所以我采用的是Java + crontab的方式实现的定时调度执行ktr文件。
/**
* 执行ktr文件
* @param args
*/
public static void main(String[] args) throws KettleException {
//初始化ketlle
KettleEnvironment.init();
//创建转换元数据对象
//TransMeta meta = new TransMeta("etl/update_insert_Trans.ktr");
TransMeta meta = new TransMeta("D:\\Tools\\Kettle\\save\\常规到紧急0分表.ktr");
Trans trans = new Trans(meta);
trans.prepareExecution(null);
trans.startThreads();
// 等待执行完成
trans.waitUntilFinished();
if(trans.getErrors()!=0){
System.out.println("执行失败!");
}
}