sql: 在sql的数据库中包含两种元素:即模式(比较强的表结构)和元组(数据记录)
nosql: 在nosql里面一般更强调元组而弱化模式,有些nosql中没有模式,有些nosql有比较弱的模式,比方说有表而没有明确的字段,或者有表有更为广义上的字段组
hbase是nosql的一种,它的设计和使用都是反模式的。它里面不是完全没有模式,它的模式分为三层
1.namespace 类似于mysql的database
2.table 类似于mysql的table
3.column cluster(COLUMN FAMILIES)(列簇) 可以把它认为是mysql里面一个表的多个字段按照某个条件分成多组
mysql和Hbase没有任何的联系 ,但是我们怎么把mysql中的数据写入Hbase呢???利用MapReduce,读取mysql表中的数据,再将数据写入Hbase中,是一种方法。
首先做好项目的准备工作。添加依赖
<dependency>
<groupId>org.apache.hadoopgroupId>
<artifactId>hadoop-clientartifactId>
<version>2.7.3version>
dependency>
<dependency>
<groupId>org.apache.hbasegroupId>
<artifactId>hbase-clientartifactId>
<version>1.3.1version>
dependency>
<dependency>
<groupId>org.apache.hbasegroupId>
<artifactId>hbase-serverartifactId>
<version>1.3.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.38version>
dependency>
在创建过程中,以前老是把数据库依赖给忘掉,后来再运行的时候会报bug,未找到数据库加载驱动。
不要忘了添加hbase-site.xml,log4j.properties这两个配置文件。
从mysql数据库中读取数据的时候我们需要创建一个实体类来存储数据
public class User implements DBWritable,WritableComparable{
private int id;
private String name;
private int age;
@Override
public void write(DataOutput out) throws IOException {
out.writeInt(id);
out.writeUTF(name);
out.writeInt(age);
}
@Override
public void readFields(DataInput in) throws IOException {
id=in.readInt();
name=in.readUTF();
age=in.readInt();
}
@Override
public int compareTo(User o) {
return id-o.id;
}
@Override
public void write(PreparedStatement statement) throws SQLException {
statement.setInt(1, id);
statement.setString(2, name);
statement.setInt(3, age);
}
@Override
public void readFields(ResultSet resultSet) throws SQLException {
id=resultSet.getInt(1);
name=resultSet.getString(2);
age=resultSet.getInt(3);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
public class MysqlToHbase1 {
public static void main(String[] args) throws Exception {
Configuration conf = HBaseConfiguration.create();
// 设置我们需要链接的数据库
// 使用远程登录权限的用户,需要进行远程访问
DBConfiguration.configureDB(conf, "com.mysql.jdbc.Driver",
"jdbc:mysql://master:3306/hadoop_mapreduce_001?characterEncoding=utf-8", "sk", "123456");
Job job = Job.getInstance(conf,"ggg");
job.setJarByClass(MysqlToHbase1.class);
job.setMapperClass(MysqlToHBaseMapper.class);
// 设置输出格式,添加数据到Hbase中
TableMapReduceUtil.initTableReducerJob("bd:user", MysqlToHBaseReduce.class, job);
job.setMapOutputKeyClass(User.class);
job.setMapOutputValueClass(NullWritable.class);
// 设置输入格式为数据库:数据裤读取
job.setInputFormatClass(DBInputFormat.class);
// select filenames from tablename where condition orderby
DBInputFormat.setInput(job, User.class, "user", null, "id", "id","name", "age");
// 数据库操作必定要使用驱动,把jar上传到hdfs做成缓存文件,供每台机器使用
// 否则就要上传jar到每一台机器
job.addFileToClassPath(new Path("hdfs://master:9000/mysql-connector-java-5.1.38.jar"));
boolean completion = job.waitForCompletion(true);
System.exit(completion?0:1);
}
public static class MysqlToHBaseMapper extends Mapper<LongWritable, User, User, NullWritable> {
@Override
protected void map(LongWritable key, User value, Mapper.Context context)
throws IOException, InterruptedException {
context.write(value, NullWritable.get());
}
}
//定义reducer对接输出到hbase
//reduce的输入类型KEYIN, VALUEIN
//reduce输出的key的类型KEYOUT,写入hbase中reduce的输出key并不重要,重要的是value,value的数据会被写入hbase表,key的数据不重要,
//只需要保证reduce的输出value是put类型就可以了
//create 'bd:user','i'
public static class MysqlToHBaseReduce extends TableReducer<User, NullWritable, NullWritable> {
private Put outputValue;
@Override
protected void reduce(User key, Iterable value,
Reducer.Context context)
throws IOException, InterruptedException {
outputValue = new Put(Bytes.toBytes(key.getId()));
outputValue.addColumn(Bytes.toBytes("i"), Bytes.toBytes("age"), Bytes.toBytes(key.getAge()));
context.write(NullWritable.get(), outputValue);
}
}
}
数据已经成功添加。
来一瓶娃哈哈哈哈哈哈哈矿泉水歇歇。