Hadoop 存储数据

目录

部署一个Mysql数据库,要求可以远程访问一、在Centos7安装MySQL5.71.安装mysql repo: ​

 ​2.在线安装mysql: 

3.启动MySQL的mysqld进程(该进程是MySQL的服务端进程):

4.查看MySQL服务端是否启动成功:

5.登录mysql注:Mysql5.7默认安装之后root是有密码的。

5.1 获取MySQL的临时密码

5.2登陆#第一次登录后需要修改密码才可以继续使用mysql 

5.3修改密码注:如果密码设置太简单出现以下的提示

根据题目要求:

创建一个Configuration对象,任何作用的配置信息通过Configuration传递

注意 以下的20210322094--master为虚拟机中的名字。 可自行更改

永远获取前一天的时间:

查看数据库下文件。

创建Job的对象并用Job的静态方法.getInstance

创建两个类的对象

总结:


部署一个Mysql数据库,要求可以远程访问
一、在Centos7安装MySQL5.7
1.安装mysql repo: 

rpm -ivh http://repo.mysql.com/mysql57-community-release-el7-8.noarch.rpm


 

rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022


 

2.在线安装mysql: 

yum install -y mysql-community-client mysql-community-devel mysql-community-server


3.启动MySQL的mysqld进程(该进程是MySQL的服务端进程):

systemctl start mysqld


4.查看MySQL服务端是否启动成功:

systemctl status mysqld


5.登录mysql
注:Mysql5.7默认安装之后root是有密码的。

5.1 获取MySQL的临时密码
cat /var/log/mysqld.log | grep "password"


 这里获取的临时密码每台计算机不同,可以自行查看你的密码。

5.2登陆
#第一次登录后需要修改密码才可以继续使用mysql
 
mysql -u root -p

5.3修改密码
注:如果密码设置太简单出现以下的提示

如:ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';

如何解决ERROR 1819 (HY000): Your password does not satisfy the current policy requirements呢?

提供一个方法:

修改两个全局参数: 
首先,修改validate_password_policy参数的值

set glodal validate_password_policy=0;


 再修改密码的长度:

set global validate_password_length=1;


 

 再次执行修改密码就可以了

ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';

根据题目要求:

        编写一个MapReduce程序,每天凌晨2点统计前一天的新能源车辆数据是否有重复数据(所有字段都相同的两条数据则认为是重复数据),并将有重复数据的车辆信息写入到第一题的Mysql数据库的repeat表中(表必须包含字段:数据生成日期、车架号、重复次数。比如2023-01-01这一天,vin0001有两条重复数据,则mysql表中的记录则为2023-01-01、vin0001、2);

在IDEA中创建一个 RepetitionData 类。在类中打入代码。 

创建一个Configuration对象,任何作用的配置信息通过Configuration传递

 Configuration conf =  new Configuration();
设置fs.defaultFS属性,告诉hdfs的路径。 

注意 以下的20210322094--master为虚拟机中的名字。 可自行更改

conf.set("fs.defaultFS","hdfs://20210322094--master:9000");

永远获取前一天的时间:

       SimpleDateFormat tempDate = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = new GregorianCalendar();
        calendar.add(calendar.DATE, -1);
        String tomorrow = tempDate.format(calendar.getTime());

查看数据库下文件。

        //数据的路径,文件以hdfs路径为主
        String input = "/wyndata/"+tomorrow+"/*.json";
        //输出的路径,文件以hdfs路径为主
        String out = "/wyndata2/repeat/"+tomorrow;

创建Job的对象并用Job的静态方法.getInstance

 Job job = Job.getInstance(conf,"json to mysql");
        //设置job所用的类在哪个包或者类下
        job.setJarByClass(RepetitionData2.class);
        //设置实现Mapper类的类名称
        job.setMapperClass(MyMapper.class);
        //设置实现Reducer类的类名称
        job.setReducerClass(MyReducer.class);

        //设置Mapper输出到Reducer的key类型
        job.setMapOutputKeyClass(Text.class);
        //设置Mapper输出到Reducer的value类型
        job.setMapOutputValueClass(Text.class);

        //设置Reducer输出的key类型
        job.setOutputKeyClass(NullWritable.class);
        //设置Reducer输出的value类型
        job.setOutputValueClass(NullWritable.class);

        //指定要处理的输入路径
        FileInputFormat.addInputPath(job,new Path(input));
        //指定要处理的输出路径
        FileOutputFormat.setOutputPath(job,new Path(out));
        //将job交给集群运行
        job.waitForCompletion(true);
    }

创建两个类的对象

(一)

    static class MyMapper extends Mapper<LongWritable,Text,Text, Text>{
        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            //创建gson对象
            Gson gson = new Gson();
            //将json数据转换为对象
            Datas datas = gson.fromJson(value.toString(),Datas.class);
            //StringUtils.substringBefore截取字符串,删除:后面的字符串,保留日期
            String sss = StringUtils.substringBefore(datas.collectTime,":");
            //字符串拼接
            String ss = sss+","+datas.vin;
            //将日期和车号作为key,全部数据作为value传入下阶段
            context.write(new Text(ss),value);
        }
    }

(二)

 static class MyReducer extends Reducer<Text,Text, NullWritable,NullWritable>{
        //创建Connection类对象
        private Connection conn;
        public MyReducer() {
            try {
                // 导入驱动jar包
                // 注册驱动
                Class.forName("com.mysql.cj.jdbc.Driver");
                //定义字符串内容为mysql地址 mydata表示数据库名称,可以改变
                String url = "jdbc:mysql://192.168.65.3:3306/wyndata?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false";
                //获取数据库连接对象
                this.conn = DriverManager.getConnection(url,"root","Aa123-456");
            }catch (Throwable e){
                System.out.println(Throwables.getStackTraceAsString(e));
            }
        }
  @Override
        protected void reduce(Text key, Iterable<Text> values,Context context) throws IOException, InterruptedException {
            //创建HashMap,为将values的值去重和添加数据重复的条数
            HashMap<Text,Integer> map = new HashMap<>();
            int sum=0;
            //将传入的数据values进行遍历
            for (Text val:values){
                //判定这个map是否有val,如果有则map的key不变,value+1,代表有重复值;没有则将val添加到key,将1赋予给value,代表没有重复值
                if (map.containsKey(val)){
                    map.put(val,map.get(val)+1);
                }else {
                    map.put(val,1);
                }
            }
            //在对map的values进行遍历,不管value的值为多少,只要map的value>1,则是重复值的,sum+1
            for (Integer value : map.values()) {
                if (value>1){
                    sum+=1;
                }
            }
            //由于key的值是日期+车号,所以对其用split方法进行字符串分割,为接下来传入mysql内容做准备
            String[] a = key.toString().split(",");
            String sql = "insert into `repeat` values(?,?,?)";
            try {
                if (sum>0){
                    PreparedStatement preparedStatement = this.conn.prepareStatement(sql);
                    preparedStatement.setString(1, a[0]);
                    preparedStatement.setString(2,a[1]);
                    preparedStatement.setInt(3,sum);
                    preparedStatement.execute();}
            }catch (Throwable e){
                Throwables.getStackTraceAsString(e);
            }
        }
    }
    public static class Datas{
        String collectTime;
        String vin;
        public Datas(String collectTime, String vin) {
            this.collectTime = collectTime;
            this.vin = vin;
        }
    }
}

总代码:

package 作业三第一小题;


import com.google.common.base.Throwables;
import com.google.gson.Gson;
import org.apache.commons.lang.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;


public class RepetitionData2 {
    public static void main(String[] args) throws IOException, InterruptedException, ClassNotFoundException {
        //创建一个Configuration对象,任何作用的配置信息通过Configuration传递
        Configuration conf =  new Configuration();
        //设置fs.defaultFS属性,告诉hdfs的路径
        conf.set("fs.defaultFS","hdfs://20210322094--master:9000");

        //永远获取前一天的时间
        /// yyyy表示年份mm表示月份dd表示日期
        SimpleDateFormat tempDate = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = new GregorianCalendar();
        calendar.add(calendar.DATE, -1);
        String tomorrow = tempDate.format(calendar.getTime());

        //数据的路径,文件以hdfs路径为主
        String input = "/wyndata/"+tomorrow+"/*.json";
        //输出的路径,文件以hdfs路径为主
        String out = "/wyndata2/repeat/"+tomorrow;

        //创建Job的对象并用Job的静态方法.getInstance(Configuration对象,"随意取名称")
        Job job = Job.getInstance(conf,"json to mysql");
        //设置job所用的类在哪个包或者类下
        job.setJarByClass(RepetitionData2.class);
        //设置实现Mapper类的类名称
        job.setMapperClass(MyMapper.class);
        //设置实现Reducer类的类名称
        job.setReducerClass(MyReducer.class);

        //设置Mapper输出到Reducer的key类型
        job.setMapOutputKeyClass(Text.class);
        //设置Mapper输出到Reducer的value类型
        job.setMapOutputValueClass(Text.class);

        //设置Reducer输出的key类型
        job.setOutputKeyClass(NullWritable.class);
        //设置Reducer输出的value类型
        job.setOutputValueClass(NullWritable.class);

        //指定要处理的输入路径
        FileInputFormat.addInputPath(job,new Path(input));
        //指定要处理的输出路径
        FileOutputFormat.setOutputPath(job,new Path(out));
        //将job交给集群运行
        job.waitForCompletion(true);
    }
    static class MyMapper extends Mapper<LongWritable,Text,Text, Text>{
        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            //创建gson对象
            Gson gson = new Gson();
            //将json数据转换为对象
            Datas datas = gson.fromJson(value.toString(),Datas.class);
            //StringUtils.substringBefore截取字符串,删除:后面的字符串,保留日期
            String sss = StringUtils.substringBefore(datas.collectTime,":");
            //字符串拼接
            String ss = sss+","+datas.vin;
            //将日期和车号作为key,全部数据作为value传入下阶段
            context.write(new Text(ss),value);
        }
    }
    static class MyReducer extends Reducer<Text,Text, NullWritable,NullWritable>{
        //创建Connection类对象
        private Connection conn;
        public MyReducer() {
            try {
                // 导入驱动jar包
                // 注册驱动
                Class.forName("com.mysql.cj.jdbc.Driver");
                //定义字符串内容为mysql地址 mydata表示数据库名称,可以改变
                String url = "jdbc:mysql://192.168.65.3:3306/wyndata?serverTimezone=UTC&characterEncoding=utf-8&useSSL=false";
                //获取数据库连接对象
                this.conn = DriverManager.getConnection(url,"root","Aa123-456");
            }catch (Throwable e){
                System.out.println(Throwables.getStackTraceAsString(e));
            }
        }

        @Override   //该方法能使Reducer结束后被调用一次,重写其,使资源关闭
        protected void cleanup(Reducer<Text, Text, NullWritable, NullWritable>.Context context) throws IOException, InterruptedException {
            try {
                this.conn.close();
            }catch (Throwable e){
                System.out.println(Throwables.getStackTraceAsString(e));
            }
        }

        @Override
        protected void reduce(Text key, Iterable<Text> values,Context context) throws IOException, InterruptedException {
            //创建HashMap,为将values的值去重和添加数据重复的条数
            HashMap<Text,Integer> map = new HashMap<>();
            int sum=0;
            //将传入的数据values进行遍历
            for (Text val:values){
                //判定这个map是否有val,如果有则map的key不变,value+1,代表有重复值;没有则将val添加到key,将1赋予给value,代表没有重复值
                if (map.containsKey(val)){
                    map.put(val,map.get(val)+1);
                }else {
                    map.put(val,1);
                }
            }
            //在对map的values进行遍历,不管value的值为多少,只要map的value>1,则是重复值的,sum+1
            for (Integer value : map.values()) {
                if (value>1){
                    sum+=1;
                }
            }
            //由于key的值是日期+车号,所以对其用split方法进行字符串分割,为接下来传入mysql内容做准备
            String[] a = key.toString().split(",");
            String sql = "insert into `repeat` values(?,?,?)";
            try {
                if (sum>0){
                    PreparedStatement preparedStatement = this.conn.prepareStatement(sql);
                    preparedStatement.setString(1, a[0]);
                    preparedStatement.setString(2,a[1]);
                    preparedStatement.setInt(3,sum);
                    preparedStatement.execute();}
            }catch (Throwable e){
                Throwables.getStackTraceAsString(e);
            }
        }
    }
    public static class Datas{
        String collectTime;
        String vin;
        public Datas(String collectTime, String vin) {
            this.collectTime = collectTime;
            this.vin = vin;
        }
    }
}

总结:

        在本节中,在虚拟机中把之前学到的MySQL运用到虚拟机并且访问数据库并展示出来,再IDEA使用代码,访问虚拟机,并把其中的数据运行出来。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值