目录
部署一个Mysql数据库,要求可以远程访问一、在Centos7安装MySQL5.71.安装mysql repo:
3.启动MySQL的mysqld进程(该进程是MySQL的服务端进程):
5.登录mysql注:Mysql5.7默认安装之后root是有密码的。
5.2登陆#第一次登录后需要修改密码才可以继续使用mysql
创建一个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使用代码,访问虚拟机,并把其中的数据运行出来。