以tcl脚本语言+mysql DB 为例 介绍ETL调度系统搭建过程

来源:互联网 发布:工作压力 知乎 编辑:程序博客网 时间:2024/05/12 11:13


前言

市面上ETL调度工具很多,用起来比较方便,但每一种工具往往具有局限性,可能某些个别的功能不支持。其实我们只要明白了调度系统的思想,底层的实现,完全可以自己手动搭建一个,用开源的语言,数据库,再配合shell脚本。这样做的好处是便于我们对流程细节上的控制,有新需求也较容易扩展实现,只要我们编写的核心控制程序设计合理,层次分明,修改维护起来也较容易。

目前有一款较火应用在hadoop分布式系统上的oozie框架,此工具提供了对hadoop,java,ql,pig等的工作流的调度支持,新的需求也可以通过actionexecutor 类来扩展,据说成为了雅虎ETL的标准。infoQ 上有三篇关于它的不错的文章,但它能否应用到任何一个复杂的分布式系统中,目前正在探究。。。

java有一个叫quartz的框架,也可以用做调度程序的实现,用过,还不错。


下面介绍一个调度系统大体搭建过程:

编程语言访问数据库进行相关操作,必须依赖访问接口,亦驱动程序,所以安装前必须准备驱动。准备工作:tcl环境搭建,确保mysql相关类库和文件存在。另外mysql数据表要确保使用InnoDB引擎,否则并发访问日志表时会出现问题。

安装

从此网站www.xdobry.de/选择下载相应开发包(根据开发环境),例如:mysqltcl-3.05.tar.gz,解压之后的目录如下:


Doc目录存放的是帮助文档,据我观察不是很全。

generic目录放的是驱动源代码:mysqltcl.c,此c源文件具体定义了访问mysql数据库的接口函数,除了查看帮助文档,还可以查看此文件,来具体了解其中一些接口函数的用法,相当于查看jdbc源代码。

Tests目录存放开源组织提供的一些例子程序,例如连接数据库,增删改查的操作等。

Configure文件是编译前检查配置相关信息,makefile文件就是编译的具体脚本,里面有些参数可能需要修改,比如tcl的安装路径,mysql lib的位置等,因为编译时会用到tcl.h和mysql.q两个c源文件,找不到编译会报错。编译成功后就会生成libmysqltcl3.05.so的文件。

编译语句:

./configure 

--with-mysql-include=/export/servers/mysql/include--with-mysql-lib=/export/servers/mysql/lib

--with-tcl=/opt/bi/ai_etl/aitools/lib--with-tclinclude=/opt/bi/ai_etl/aitools/include

Mysql的两个目录分别存放mysql.h头文件和,mysql相关类库

Tcl两个目录要有tclconfig.sh文件和tcl相关类库,这些都是在编译时必须用到的。

然后在编写tcl脚本中加载此so文件,load so文件时不提示任何错误,就表明编译基本成功,便可以使用其中的接口访问mysql数据库了

开发环境搭建

相应的环境变量要设置正确,可以配置用户级的配置文件,也可以修改全局的,但建议修改用户的。

在原有的tcl开发目录下,建个软连接指向so文件,便于以后版本的替换。

编写common.tcl脚本,定义dss脚本直接访问的函数,dss脚本是应用程序的入口。

在这里,dss相当于java的控制器,common.tcl相当于service层,而dao层则由db_mysql.tcl来实现就可以了(本系统省略这一层,将具体业务逻辑都写到common里了,以后有时间可以分层,完善)。

Dss脚本主要功能是,检查应用程序运行环境及所需资源是否加载完毕,然后调用具体的应用程序去执行。

Common.tcl要定义具体的业务逻辑的操作,比如数据库的连接,增删改查,提交,回滚,记录日志等功能,这些操作再去调用直接跟数据库打交道的db_mysql.tcl即可。当然db_mysql.tcl也是需要编写的。

开发过程并没有具体的顺序,可以根据需求随时修改相应层的脚本。

应用程序脚本里的应用可以处理sql语句,也可以是任何可以在linux平台(或可以包装在linux平台)下运行的命令,比如HIVE 的ql,hbase shell ,java 执行命令等。

调度系统设计                                                                      

我们用一个名叫agent.tcl的脚本程序去实现,主要功能是:去依赖表里查询满足一定的条件可以运行的应用程序脚本名称,然后用后台子进程去执行,即将应用程序脚本名作为参数传递给dss入口程序执行。核心sql:


select case when count(S_CODE)=count(CMD_CODE) then T_CODE end
  from T_ETL_CMD_RELATION a left outer join
       (select * from T_ETL_CMD_LOG where status = 3 and OP_TIME = '$op_time' ) b on a.S_CODE = b.CMD_CODE
  where a.T_CODE not in (
      select CMD_CODE
      from T_ETL_CMD_LOG
      where OP_TIME = '$op_time')
  and a.VALID_FLAG in (1,2)
  group by T_CODE
  having case when count(S_CODE)=count(CMD_CODE) then T_CODE end is not null


剩下的问题就是写具体的数据处理脚本,在表里配置依赖关系,启动运行。

如果再做的完善一点,就是写一个前端web程序,来进行可视化任务的配置,管理并查看流程状态,而不是直接操作数据库表,在数据库里查看运行日志。


搭建过程遇到的问题

1.  编译时报skipping incompatible /usr/lib/mysql/libmysqlclient.so whensearching for –lmysqlclient 错误。

处理方式,将makefile里的路径/usr/lib 改为/usr/lib64,初步估计原因可能是软件版兼容的问题(可以修改makefile.in)

2.  Mysql和oracle访问数据库的机制有所不同,oracle是基于本地tns监听,来连接本地或远程数据库,并且logon后仅获得logon handle,一个logon handle可以打开多个statement handle 去操作数据库,而mysql直接通过connect (host,port,user,pwd,dbname)直接获取操作数据的handle,写接口函数时需注意。

3.  Load 时报不能加载mysqlclient so 文件问题,要配置环境变量LD_LIBRARY_PATH.


原创粉丝点击