如何使用Python将Hadoop中的数据保存到数据库中

4
我正在使用hadoop处理一个xml文件,因此我已经编写了Python的mapper文件和reducer文件。
假设需要处理的输入是test.xml
<report>
 <report-name name="ALL_TIME_KEYWORDS_PERFORMANCE_REPORT"/>
 <date-range date="All Time"/>
 <table>
  <columns>
   <column name="campaignID" display="Campaign ID"/>
   <column name="adGroupID" display="Ad group ID"/>
  </columns>
  <row campaignID="79057390" adGroupID="3451305670"/>
  <row campaignID="79057390" adGroupID="3451305670"/>
 </table>
</report>

mapper.py文件

import sys
import cStringIO
import xml.etree.ElementTree as xml

if __name__ == '__main__':
    buff = None
    intext = False
    for line in sys.stdin:
        line = line.strip()
        if line.find("<row") != -1:
        .............
        .............
        .............
        print '%s\t%s'%(campaignID,adGroupID )

reducer.py 文件

import sys
if __name__ == '__main__':
    for line in sys.stdin:
        print line.strip()

我用以下命令运行了Hadoop:

我使用以下命令运行了Hadoop:

bin/hadoop jar contrib/streaming/hadoop-streaming-1.0.4.jar 
- file /path/to/mapper.py file -mapper /path/to/mapper.py file 
-file /path/to/reducer.py file -reducer /path/to/reducer.py file 
-input /path/to/input_file/test.xml 
-output /path/to/output_folder/to/store/file

当我运行以上命令时,Hadoop 会按照我们在 reducer.py 文件中指定的格式正确创建输出文件,并将所需数据存储在其中。
现在,我想做的是,不想将输出数据存储在 Hadoop 默认创建的文本文件中,而是想将数据保存到 MYSQL 数据库中。因此,我在 reducer.py 文件中编写了一些 Python 代码,直接将数据写入 MYSQL 数据库,并尝试通过删除输出路径来运行上述命令。
bin/hadoop jar contrib/streaming/hadoop-streaming-1.0.4.jar 
- file /path/to/mapper.py file -mapper /path/to/mapper.py file 
-file /path/to/reducer.py file -reducer /path/to/reducer.py file 
-input /path/to/input_file/test.xml 

我遇到了类似以下的错误:


12/11/08 15:20:49 ERROR streaming.StreamJob: Missing required option: output
Usage: $HADOOP_HOME/bin/hadoop jar \
          $HADOOP_HOME/hadoop-streaming.jar [options]
Options:
  -input    <path>     DFS input file(s) for the Map step
  -output   <path>     DFS output directory for the Reduce step
  -mapper   <cmd|JavaClassName>      The streaming command to run
  -combiner <cmd|JavaClassName> The streaming command to run
  -reducer  <cmd|JavaClassName>      The streaming command to run
  -file     <file>     File/dir to be shipped in the Job jar file
  -inputformat TextInputFormat(default)|SequenceFileAsTextInputFormat|JavaClassName Optional.
  -outputformat TextOutputFormat(default)|JavaClassName  Optional.
   .........................
   .........................
  1. 我有一个疑问,如何在处理文件后将数据保存在数据库中?
  2. 在哪个文件(mapper.py/reducer.py)中可以编写将数据写入数据库的代码?
  3. 用于运行hadoop以将数据保存到数据库中的命令是什么?因为当我从hadoop命令中删除输出文件夹路径时,它会显示错误。

请问有谁能帮忙解决上述问题……

编辑:

处理步骤如下:

  1. 按照上述方法创建了读取xml文件并在某个文件夹中通过hadoop命令创建文本文件的mapperreducer文件

    例如:文本文件(使用hadoop命令处理xml文件的结果)所在的文件夹如下所示

    /home/local/user/Hadoop/xml_processing/xml_output/part-00000

这里的xml文件大小为1.3 GB,经过hadoop处理后创建的文本文件大小为345 MB

现在,我想做的就是尽可能快地读取上面路径中的文本文件并将数据保存到mysql数据库中

我已经尝试使用基本的python,但是它需要350秒左右来处理文本文件并将其保存到mysql数据库。

  1. 根据Nichole的提示,现在我已经下载了sqoop并解压到以下路径:

    /home/local/user/sqoop-1.4.2.bin__hadoop-0.20

然后进入bin文件夹并输入./sqoop,但是出现了下面的错误。

sh-4.2$ ./sqoop
Warning: /usr/lib/hbase does not exist! HBase imports will fail.
Please set $HBASE_HOME to the root of your HBase installation.
Warning: $HADOOP_HOME is deprecated.

Try 'sqoop help' for usage.

我也尝试了以下方法:

./sqoop export --connect jdbc:mysql://localhost/Xml_Data --username root --table PerformaceReport --export-dir /home/local/user/Hadoop/xml_processing/xml_output/part-00000 --input-fields-terminated-by '\t'

结果

Warning: /usr/lib/hbase does not exist! HBase imports will fail.
Please set $HBASE_HOME to the root of your HBase installation.
Warning: $HADOOP_HOME is deprecated.

12/11/27 11:54:57 INFO manager.MySQLManager: Preparing to use a MySQL streaming resultset.
12/11/27 11:54:57 INFO tool.CodeGenTool: Beginning code generation
12/11/27 11:54:57 ERROR sqoop.Sqoop: Got exception running Sqoop: java.lang.RuntimeException: Could not load db driver class: com.mysql.jdbc.Driver
java.lang.RuntimeException: Could not load db driver class: com.mysql.jdbc.Driver
    at org.apache.sqoop.manager.SqlManager.makeConnection(SqlManager.java:636)
    at org.apache.sqoop.manager.GenericJdbcManager.getConnection(GenericJdbcManager.java:52)
    at org.apache.sqoop.manager.SqlManager.execute(SqlManager.java:525)
    at org.apache.sqoop.manager.SqlManager.execute(SqlManager.java:548)
    at org.apache.sqoop.manager.SqlManager.getColumnTypesForRawQuery(SqlManager.java:191)
    at org.apache.sqoop.manager.SqlManager.getColumnTypes(SqlManager.java:175)
    at org.apache.sqoop.manager.ConnManager.getColumnTypes(ConnManager.java:262)
    at org.apache.sqoop.orm.ClassWriter.getColumnTypes(ClassWriter.java:1235)
    at org.apache.sqoop.orm.ClassWriter.generate(ClassWriter.java:1060)
    at org.apache.sqoop.tool.CodeGenTool.generateORM(CodeGenTool.java:82)
    at org.apache.sqoop.tool.ExportTool.exportTable(ExportTool.java:64)
    at org.apache.sqoop.tool.ExportTool.run(ExportTool.java:97)
    at org.apache.sqoop.Sqoop.run(Sqoop.java:145)
    at org.apache.hadoop.util.ToolRunner.run(ToolRunner.java:65)
    at org.apache.sqoop.Sqoop.runSqoop(Sqoop.java:181)
    at org.apache.sqoop.Sqoop.runTool(Sqoop.java:220)
    at org.apache.sqoop.Sqoop.runTool(Sqoop.java:229)
    at org.apache.sqoop.Sqoop.main(Sqoop.java:238)
    at com.cloudera.sqoop.Sqoop.main(Sqoop.java:57)

以上的sqoop命令是否有助于读取文本文件并保存到数据库的功能?因为我们需要从文本文件中处理并插入到数据库中!!!

2个回答

4
我用Python编写所有的Hadoop MR作业。但是,移动数据时您不必使用Python。请使用Sqoop:http://sqoop.apache.org/
Sqoop是一个开源工具,允许用户将关系型数据库中的数据提取到Hadoop中进行进一步处理。它非常简单易用。您需要做的只是:
1. 下载并配置Sqoop 2. 创建MySQL表模式 3. 指定Hadoop HDFS文件名、结果表名和列分隔符。
阅读此内容以获取更多信息:http://archive.cloudera.com/cdh/3/sqoop/SqoopUserGuide.html
使用Sqoop的优势是我们现在可以使用单行命令将我们的HDFS数据转换为任何类型的关系型数据库(MySQL、Derby、Hive等)以及反之。
对于您的用例,请进行必要的更改:
mapper.py
#!/usr/bin/env python

import sys
for line in sys.stdin:
        line = line.strip()
        if line.find("<row") != -1 :
            words=line.split(' ')
            campaignID=words[1].split('"')[1]
            adGroupID=words[2].split('"')[1]
            print "%s:%s:"%(campaignID,adGroupID)

流式命令

bin/hadoop jar contrib/streaming/hadoop-streaming-1.0.4.jar - file /path/to/mapper.py file -mapper /path/to/mapper.py file -file /path/to/reducer.py file -reducer /path/to/reducer.py file -input /user/input -output /user/output

mysql

create database test;
use test;
create table testtable ( a varchar (100), b varchar(100) );

sqoop

./sqoop export --connect jdbc:mysql://localhost/test --username root --table testnow --export-dir /user/output --input-fields-terminated-by ':'

注意

  1. 请根据你的需要更改映射器。
  2. 我在映射器和Sqoop命令中都使用了“:”作为我的列分隔符。按需要更改。
  3. Sqoop教程:我个人跟随了Hadoop: The Definitive Guide(Oreilly)以及http://archive.cloudera.com/cdh/3/sqoop/SqoopUserGuide.html

我开始使用Sqoop并尝试安装它,请看这个链接:http://stackoverflow.com/questions/13411525/sqoop-installation-error-on-fedora-15 - Shiva Krishna Bavandla
假设你已经安装好了Sqoop,如果没有的话,我可以帮你。HDFS输出文件应该直接使用Sqoop发送到MySQL。请回复我是否对你有所帮助。 - Nicole Hu
我清楚了,使用Hadoop命令将数据保存到/user/output文件夹中。现在我应该在哪里使用./sqoop命令?我已经尝试在终端中输入它,但是它显示“sh: "./sqoop: No such file or directory"”,我还尝试从我解压Sqoop的文件夹中运行,但结果与上述相同。 - Shiva Krishna Bavandla
请检查你解压sqoop的/bin文件夹。如果还没有,则说明您的sqoop设置存在问题,一旦您告诉我运行$SQOOP_FOLDER/bin/sqoop时出现了什么错误,我会帮助您解决这个问题。希望这可以帮到您,如果有效,请为答案点赞并标记为已解决! - Nicole Hu
已经下载并放置在lib文件夹中,但当我再次运行时,出现了以下错误,请查看此链接http://pastebin.com/h4JzD9Ea - Shiva Krishna Bavandla
显示剩余9条评论

1

将数据写入数据库的最佳位置应该是在OutputFormat中。虽然可以在Reducer级别上进行编写,但这不是最好的选择。

如果您已经使用Java编写了mapper和reducer,则可以利用DBOutputFormat

因此,您可以编写一个自定义的OutputFormat,以满足Reducer的数据输出格式(键、值)并将数据传输到MySQL。

请阅读Yahoo Developer Network上的this教程,了解如何编写自定义Output Format。


1
我正在使用Python的Hadoop,您能否从Pythonic的角度提供建议? - Shiva Krishna Bavandla
那么你最好修改你的reducer.py,直接将数据汇入数据库,因为它是仅次于OutputFormat的阶段。对于-output参数使用一个虚拟位置,以便上述命令不会失败。 - shazin
此外,对于-outputformat参数,请使用NullOutputFormat以忽略输出。 - shazin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接