二次开发DataX以支持HIVE分区表

问题

        最近在一个大数据的项目开发中使用到了数据同步工具DataX,但在使用过程中发现了DataX对HIve分区表的支持不太友好。

        具体体现在将数据库中的数据同步到HIVE分区表时,写入目录为HIVE表分区为dt=XXXX,如果不提前创建该分区,会报目录不存在的错误,如下图:

8cdbc6874e4846a7b12cc840a5ba7a15.png

 

原因分析 

         这个错误是由于DataX不支持在HDFS上创建目录导致的。

 

解决办法

        二次开发DataX,在写入时检测目录,若目录不存在自动创建此分区目录。

步骤:1.从GitHub下载datax源码  链接

           2.修改hdfswriter目录下的HdfsWriter.java源码,重写里面的prepare方法:

    @Override
    public void prepare() {
        //若路径已经存在,检查path是否是目录
        if (hdfsHelper.isPathexists(path)) {
            if (!hdfsHelper.isPathDir(path)) {
                throw DataXException.asDataXException(HdfsWriterErrorCode.ILLEGAL_VALUE,
                        String.format("您配置的path: [%s] 不是一个合法的目录, 请您注意文件重名, 不合法目录名等情况.",
                                path));
            }
            //根据writeMode对目录下文件进行处理
            Path[] existFilePaths = hdfsHelper.hdfsDirList(path, fileName);
            boolean isExistFile = false;
            if (existFilePaths.length > 0) {
                isExistFile = true;
            }
            if ("append".equalsIgnoreCase(writeMode)) {
                LOG.info(String.format("由于您配置了writeMode append, 写入前不做清理工作, [%s] 目录下写入相应文件名前缀  [%s] 的文件",
                        path, fileName));
            } else if ("nonconflict".equalsIgnoreCase(writeMode) && isExistFile) {
                LOG.info(String.format("由于您配置了writeMode nonConflict, 开始检查 [%s] 下面的内容", path));
                List<String> allFiles = new ArrayList<String>();
                for (Path eachFile : existFilePaths) {
                    allFiles.add(eachFile.toString());
                }
                LOG.error(String.format("冲突文件列表为: [%s]", StringUtils.join(allFiles, ",")));
                throw DataXException.asDataXException(HdfsWriterErrorCode.ILLEGAL_VALUE,
                        String.format("由于您配置了writeMode nonConflict,但您配置的path: [%s] 目录不为空, 下面存在其他文件或文件夹.", path));
            } else if ("truncate".equalsIgnoreCase(writeMode) && isExistFile) {
                LOG.info(String.format("由于您配置了writeMode truncate,  [%s] 下面的内容将被覆盖重写", path));
                hdfsHelper.deleteFiles(existFilePaths);
            }
        } else {
            LOG.info(String.format("您配置的路径: [%s] 不存在,自动为您创建此路径", path));
            hdfsHelper.createPath(path);
        }
    }

           3.修改hdfswriter目录下的HdfsHelper.java源码,在里面添加createPath方法:

    public boolean createPath(String filePath) {
        Path path = new Path(filePath);
        boolean exist = false;
        try {
            if (fileSystem.exists(path)) {
                String message = String.format("文件路径[%s]已存在,无需创建!",
                        "message:filePath =" + filePath);
                LOG.info(message);
                exist = true;
            } else {
                exist = fileSystem.mkdirs(path);
            }
        } catch (IOException e) {
            String message = String.format("创建文件路径[%s]时发生网络IO异常,请检查您的网络是否正常!",
                    "message:filePath =" + filePath);
            LOG.error(message);
            throw DataXException.asDataXException(HdfsWriterErrorCode.CONNECT_HDFS_IO_ERROR, e);
        }
        return exist;
    }

           4.打包修改后的源码,并替换掉集群的datax安装目录datax/plugin/writer/hdfswriter/hdfswriter-0.0.1-SNAPSHOT.jar即可。(在DataX-master根目录下的pom.xml文件核心组件、公共组件、reader/writer插件都以module的方式组装到一起了,把不需要的注释掉可加快打包速度)

 

处理结果

        二次开发后完美运行:

        b23e8af0324d435b9500f0bdcd335d10.png

 

 

下面是一个将 PG 数据库中的数据同步到 Hive 分区表DataX Job 的 json 脚本示例: ```json { "job": { "setting": { "speed": { "channel": "3" } }, "content": [ { "reader": { "name": "pgsqlreader", "parameter": { "column": [ "id", "name", "age", "gender" ], "connection": [ { "jdbcUrl": "jdbc:postgresql://localhost:5432/test", "table": "(select * from test_table) as t", "username": "username", "password": "password" } ], "splitPk": "id", "where": "" } }, "writer": { "name": "hdfswriter", "parameter": { "column": [ "id", "name", "age", "gender" ], "fieldDelimiter": "\t", "fileType": "text", "path": "/user/hive/warehouse/test.db/test_table", "fileName": "", "writeMode": "append", "compress": "NONE", "dateFormat": "yyyy-MM-dd", "encoding": "UTF-8", "nullFormat": "\\N", "header": "false", "footer": "false", "mergeSmallFiles": "false", "partition": [ { "name": "dt", "type": "string", "format": "yyyyMMdd", "value": "${date}" } ], "hiveConf": [ { "name": "hive.exec.dynamic.partition.mode", "value": "nonstrict" } ], "preSql": "", "postSql": "" } }, "transformer": { "name": "dt", "parameter": { "column": [ "id", "name", "age", "gender" ] } } } ] } } ``` 在这个示例中,我们使用 PGSQL Reader 读取 test_table 表中的数据,并使用 Hive Writer 将数据写入Hive 分区表 test_table 中。在 Hive Writer 中,我们指定了数据的分区字段为 dt,格式为 yyyyMMdd,并且指定了 Hive 表的路径为 /user/hive/warehouse/test.db/test_table。在 partition 中,我们使用了 ${date} 变量来动态指定数据的分区。 注意:在运行这个 DataX Job 之前,需要先创建好 Hive 表,并且在 Hive 中添加好对应的分区。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值