内容简介

  • 一、Hadoop与数据库交互简介
  • 二、操作前的准备
    • 1.创建表
    • 2.将数据插入表words中
    • 2.将MySQL的驱动分发到所有的Hadoop节点
  • 三、Hadoop与MySQL交互实现
    • 1.创建Java工程,添加Maven支持
    • 2.创建并编写类MySqlDBWritable
    • 3.创建并编写类MapByMysql
    • 4.创建并编写类ReducerByMysql
    • 5.创建并编写作业类MapByMysqlApp
    • 6.打包作业提交到集群
    • 7.执行程序查看结果
  • 四、总结

一、Hadoop与数据库交互简介

Hadoop在处理数据过程中接触得较多的就是文本文件即TextInputFormat,这也是MapReducer框架默认的输入格式,但是在某些情况下Hadoop需要与关系型数据库,如MySQL、Oracle等进行交互,有以下原因:

  • 需要将关系型数据库的数据作为处理的数据输入
  • 需要将数据的统计结果存储进关系型数据库以备分析
  • 将关系型数据库的数据迁移进HDFS

第于第三点而言,更为流行的做法就是使用Apache 的 Sqoop,先挖个坑这个以后会介绍。为此,Hadoop提供DBInputFormat输入类,满足这个需求。DBInputFormat使用JDBC从关系型数据库中读取数据,而与之对应的输出类是DBOutputFormat,它也是使用JDBC将数据写入关系型数据库中。

为了演示全面,本次操作将完成这样一个任务,从数据库的words表中读取单词,然后统计单词个数后将结果写入stats表中。具体做法是先编写类MySqlDBWritable,对从关系型数据库中取出的数据进行串行化与逆串行化,然后编写常规的Map与Reducer统计单词个数,并将数据分装进MySqlDBWritable中写入数据库。

二、操作前的准备

Hadoop版本是:2.6.0-cdh5.7.0
开发工具是:IDEA2018
关系型数据库是:MySQL5.6.26

1.创建表

在MySQL中执行如下命令:
创建表words:create table words(id int primary key auto_increment,line varchar(256)),其中字段line代表一行空格分隔的单词。
创建表status:create table stats(word varchar(25),count int),其中字段word 代表统计的单词,count 是其统计个数。

2.将数据插入表words中

hello world hello hadoop
hello spark hello hbase
hello hive hello hadoop
hello kafka hello flume
hello flink hello sqoop
hello spark hello hbase
hello kafka hello flume
hello spark hello hbase

插入数据后words表数据为:

2.将MySQL的驱动分发到所有的Hadoop节点

这一步很关键,因为DBInputFormat和DBOutputFormat需要使用JDBC与MySQL进行交互,而Hadoop默认情况下是没有MySQL的驱动,所以需要将MySQL的驱动分发至所有数据节点上,具体路径是:$HADOOP_HOME/share/hadoop/common/lib下。

三、Hadoop与MySQL交互实现

1.创建Java工程,添加Maven支持

完整的Maven依赖如下:

  <properties><hadoop.version>2.6.0-cdh5.7.0</hadoop.version></properties><repositories><repository><id>cloudera</id><url>https://repository.cloudera.com/artifactory/cloudera-repos</url></repository></repositories><dependencies><dependency><groupId>org.apache.hadoop</groupId><artifactId>hadoop-client</artifactId><version>${hadoop.version}</version></dependency></dependencies><build><pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --><plugins><plugin><artifactId>maven-clean-plugin</artifactId><version>3.0.0</version></plugin><!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging --><plugin><artifactId>maven-resources-plugin</artifactId><version>3.0.2</version></plugin><plugin><artifactId>maven-compiler-plugin</artifactId><version>3.7.0</version></plugin><plugin><artifactId>maven-surefire-plugin</artifactId><version>2.20.1</version></plugin><plugin><artifactId>maven-jar-plugin</artifactId><version>3.0.2</version></plugin><plugin><artifactId>maven-install-plugin</artifactId><version>2.5.2</version></plugin><plugin><artifactId>maven-deploy-plugin</artifactId><version>2.8.2</version></plugin></plugins></pluginManagement><finalName>mysqlapp1.0.0</finalName></build>

2.创建并编写类MySqlDBWritable

/*** 1.封装words表和stats表的字段以及对其串行化和逆串行化* 2.读取words表封装进该类进行串行化* 3.讲统计结果封装进该类进行逆串行化后写入MySQL*/
public class MySqlDBWritable implements DBWritable, Writable {//words表字段private  int id;private String line;//stats表字段private String word;private int count;public int getId() {return id;}public String getWord() {return word;}public void setWord(String word) {this.word = word;}public int getCount() {return count;}public void setCount(int count) {this.count = count;}public void setId(int id) {this.id = id;}public String getLine() {return line;}public void setLine(String line) {this.line = line;}//串行化@Overridepublic void write(DataOutput out) throws IOException {out.writeInt(id);out.writeUTF(line);out.writeUTF(word);out.writeInt(count);}//逆串行化@Overridepublic void readFields(DataInput in) throws IOException {id = in.readInt();line = in.readUTF();word = in.readUTF();count = in.readInt();}//往数据库表stats写入数据@Overridepublic void write(PreparedStatement statement) throws SQLException {statement.setString(1,word);statement.setInt(2,count);}//在数据库表words中读取数据@Overridepublic void readFields(ResultSet resultSet) throws SQLException {id = resultSet.getInt(1);line = resultSet.getString(2);}
}

3.创建并编写类MapByMysql

/*** 从MySQL中的words表读取数据* 并将其映射为(word,1)元组*/
public class MapByMysqlClass extends Mapper<LongWritable,MySqlDBWritable, Text, IntWritable> {@Overrideprotected void map(LongWritable key, MySqlDBWritable value, Context context) throws IOException, InterruptedException {//将words表的line字段取出来以空格分隔String[] words = value.getLine().split(" ");//映射为(word,1)元组for(String word:words){context.write(new Text(word),new IntWritable(1));}}
}

4.创建并编写类ReducerByMysql

/*** 对(word,1)元组中的word聚合* 并结果写入MySqlDBWritable中*/
public class ReducerByMysqlClass extends Reducer<Text, IntWritable,MySqlDBWritable, NullWritable> {@Overrideprotected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {int count  = 0;MySqlDBWritable mySqlDBWritable = new MySqlDBWritable();//迭代统计for(IntWritable i : values){count += i.get();}//将统计结果写入MySqlDBWritable中mySqlDBWritable.setWord(key.toString());mySqlDBWritable.setCount(count);context.write(mySqlDBWritable,NullWritable.get());}
}

5.创建并编写作业类MapByMysqlApp

public class MapByMysqlApp {public static void main(String[] args) throws Exception{Configuration conf = new Configuration();//MySQL驱动String classDriver = "com.mysql.jdbc.Driver";//MySQL连接串,后面跟存放你创建表的数据库String url="jdbc:mysql://hadoop00:3306/jdbc";//账号密码String userName = "root";String password = "root";//实例化作业Job job = Job.getInstance(conf,"MapByMysqlApp");//设置作业主类job.setJarByClass(MapByMysqlApp.class);//设置数据库输入类型job.setInputFormatClass(DBInputFormat.class);//设置数据库输出类型job.setOutputFormatClass(DBOutputFormat.class);//设置Map类job.setMapperClass(MapByMysqlClass.class);//设置Map类Key的输出类型job.setMapOutputKeyClass(Text.class);//设置Map类Value的输出类型job.setMapOutputValueClass(IntWritable.class);//设置Reducer类job.setReducerClass(ReducerByMysqlClass.class);//设置Reducer类Key的输出类型job.setOutputKeyClass(MySqlDBWritable.class);//设置Reducer类Value的输出类型job.setOutputValueClass(NullWritable.class);//配置数据库信息DBConfiguration.configureDB(job.getConfiguration(),classDriver,url,userName,password);//输入类型为数据库关系类型,通过SQL语句将查询的数据封装进MySqlDBWritable中DBInputFormat.setInput(job,MySqlDBWritable.class,"select * from words","select count(*) from words");//输出类型为数据库关系类型,将数据插入到status表中,字段分别是word,countDBOutputFormat.setOutput(job,"stats","word","count");//提价作业job.waitForCompletion(true);}
}

6.打包作业提交到集群


在工程项目路径下的target文件夹下有生成的jar包,把它提交到集群主机上。

7.执行程序查看结果

执行命令:hadoop jar mysqlapp1.0.0.jar com.hadoop.mysql.MapByMysqlApp,第一个参数是你的jar包的路径,第二个参数是作业主类的全路径。进入MySQL中执行SQL语句:select * from stats查看单词统计结果:

至此,Hadoop交互MySQL的全部过程已经完成。

四、总结

本次操作演示了Hadoop交互MySQL,包括从数据库中读取数据和将将数据写入数据库,这也是非常之常见的操作。其实,Hadoop所处理的数据类型可以混合搭配使用,比如说可以使用TextInputFormat从HDFS读取数据,处理后使用DBOutputFormat将数据写入到关系型数据库,非常的灵活,还支持多种格式同时输入等等,这些后面都会介绍。非常感您的阅读,如有错误请不吝赐教!

Hadoop学习之路(五):Hadoop交互关系型数据库(MySQL)相关推荐

  1. 3台云腾讯云开始hadoop学习之路笔记二

    3台云腾讯云开始hadoop学习之路笔记二(接上) 大三党开始学习hadoop之路了,菜鸟学习hadoop,有啥错误请大佬指教.由于自己电脑配置不够,只能买3台腾讯云服务器来学习了.以下笔记都是记录我 ...

  2. java 设置年轻代堆大小,[JVM学习之路]五堆(一)堆的内存结构参数设置分代思想内存分配...

    [JVM学习之路]五堆(一)堆的内存结构参数设置分代思想内存分配 [JVM学习之路]五.堆(一)堆的内存结构.参数设置.分代思想.内存分配策略及TLAB 一.堆的核心概述 堆的特点: 1.一个jvm实 ...

  3. SpringBoot学习笔记(9)----SpringBoot中使用关系型数据库以及事务处理

    在实际的运用开发中,跟数据库之间的交互是必不可少的,SpringBoot也提供了两种跟数据库交互的方式. 1. 使用JdbcTemplate 在SpringBoot中提供了JdbcTemplate模板 ...

  4. SEEK学习论坛-JavaWeb开发实训课题 (数据库MySQL+js+Ajax+Servlet)

    关于这次学校实训,我们做了一个类似于CSDN博客的项目,然后我们小组取名叫SEEK,一个学习论坛,前面ppt有介绍,我主要是负责后端数据库的,与MySQL交互,由我的组长写好js代码,然后将前端所获取 ...

  5. 什么是腾讯云关系型数据库(MySQL/SQL Server/MariaDB/PostgreSQL详解)

    什么是腾讯云关系型数据库?腾讯云关系型数据库提供 MySQL.SQL Server.MariaDB.PostgreSQL详细介绍.腾讯云关系型数据库让您在云中轻松部署.管理和扩展的关系型数据库,提供安 ...

  6. mysql事务四个特性_关系型数据库mysql事务四大特性

    关系型数据库mysql 事务四大特性 一.首先我们先说一下什么是事务 在mysql中对数据进行增删改查中的任何一次操作的过程都可以被认为是一次事务,事务是一系列严密的操作,事务的结束有两种结果,当事务 ...

  7. 我的hadoop学习之路

    Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFS.HDFS有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上. Ha ...

  8. Hadoop学习之路一 Single Node Setup

    从研究生入学到现在,快一年的时间了.和很多人一样,我迷茫着,一直没想明白自己想要干什么.年轻的时候真的想和所有人不一样,直到最后选择了大数据方向,更多的也是感觉.青春的魅力在于可能性.没有过多的犹豫纠 ...

  9. Hadoop学习之路(二)Hadoop发展背景

    Hadoop产生的背景 1. HADOOP最早起源于Nutch.Nutch的设计目标是构建一个大型的全网搜索引擎,包括网页抓取.索引.查询等功能,但随着抓取网页数量的增加,遇到了严重的可扩展性问题-- ...

最新文章

  1. CATransform3DRotate 实现左右,上下翻转效果
  2. 文明,在于传承,而不在于遗忘。
  3. 【计算机网络】深入浅出网络层(看不懂你来打我.上)
  4. before伪类的超有用应用技巧——水平菜单竖线分隔符
  5. Angular新建组件以及组件之间的调用
  6. Python函数——.strip()
  7. 坦克乘员协同训练模拟系统
  8. c语言输入的成绩由高到低该怎么,c语言编程:输入学生信息(姓名年龄分数)并按照分数由高到低输出...
  9. 调试Python的方式
  10. 计算机语言语法语义,程序设计语言语义
  11. lisp6 暖通cad_这些高效插件,学CAD的基本用过两种以上
  12. 百度网盘如何提高下载速度
  13. 计算机桌面出现蓝色底色,电脑桌面图标有蓝色阴影怎么去掉
  14. php7 memcached sasl,启用MemCached的SASL认证
  15. SVN主干到分支的详细操作!
  16. c语言nba球星信息系统,NBA:超神控卫
  17. 运营商业务系统基于 KubeSphere 的容器化实践
  18. 删除服务残留注册表_流氓软件卸载残留?不存在的!软件里的扫地僧来了~
  19. 宾果消消乐和宾果消消消_手机游戏软件宾果消消消和开心消消乐各有什么优点?...
  20. 如何在不知道密码的情况下解除excel的工作表中的保护

热门文章

  1. 图灵社区一个有关Express的文章
  2. FineCMS V5.3 开发日志
  3. 世界排名前3名的Linux桌面系统,快如闪电!立马让老旧电脑变废为宝
  4. Android 自定义View :虚线矩形
  5. 经典CS算法整理REVIEW1
  6. Android开发艺术探索PDF版
  7. 左手猎人游戏本,右手智能手表,荣耀如此长袖善舞
  8. Allegro 如何设置DSN与brd默认文件的打开方式
  9. CSDN 免费视频教程
  10. java停车场管理系统,实现功能即可,要求图形界面。