HBase分布式数据库操作与编程目录
- 一、实验目的
- 二、实验内容
一、实验目的
1.掌握HBase操作常用Shell命令;
2.掌握HBase数据表的创建、添加数据、查看数据、删除数据、删除表、查询历史数据等操作;
3.掌握HBase APIs编程实践方法
二、实验内容
第1题 HBase 练习
【实验内容】
1.实现HBase的配置并完成http://dblab.xmu.edu.cn/blog/install-hbase/上的javac程序练习。
1、切换到/usr/local/hbase目录并编辑/.bashrc文件(在/.bashrc文件中export PATH这行追加/usr/local/hbase/bin)
2、编辑完成后,再执行source命令使上述配置在当前终端立即生效
3、添加HBase权限(将hbase下的所有文件的所有者改为hadoop,hadoop是当前用户的用户名)
4、 查看HBase版本,确定hbase安装成功(看到以下输出消息表示HBase已经安装成功)
5、用vi命令打开并编辑hbase-env.sh
配置JAVA环境变量如图,配置HBASE_MANAGES_ZK为true,表示由hbase自己管理zookeeper,不需要单独的zookeeper
6、打开并编辑hbase-site.xml
在启动HBase前需要设置属性hbase.rootdir,用于指定HBase数据的存储位置(以防每次重启系统都会丢失数据)
7、测试运行(首先切换目录至HBase安装目录/usr/local/hbase;再启动HBase)
8、打开shell命令行模式(用户可以通过输入shell命令操作HBase数据库)
9、退出shell命令行模式,停止HBase运行
10、配置/usr/local/hbase/conf/hbase-env.sh
配置JAVA_HOME,HBASE_CLASSPATH,HBASE_MANAGES_ZK.
HBASE_CLASSPATH设置为本机Hadoop安装目录下的conf目录(即/usr/local/hadoop/conf)
11、用命令vi打开并编辑hbase-site.xml
hbase.rootdir指定HBase的存储目录;hbase.cluster.distributed设置集群处于分布式模式
12、登陆ssh,切换目录至/usr/local/hadoop ,启动hadoop
13、命令jps(能看到NameNode,DataNode和SecondaryNameNode都已经成功启动,表示hadoop启动成功)
14、切换目录至/usr/local/hbase,启动HBase(输入命令jps,看到以下界面说明hbase启动成功)
15、进入shell界面
16、退出shell界面,停止HBase运行
编程实践
1、HBase中用create命令创建表
2、通过describe命令查看“student”表的基本信息
3、添加数据( 当运行命令:put ‘student’,’95001’,’Sname’,’LiYing’时,即为student表添加了学号为95001,名字为LiYing的一行数据,其行键为95001 )
4、为95001行下的course列族的math列添加了一个数据
5、为95001行下的course列族的Sage列添加了一个数据
6、为95001行下的course列族的Sdept列添加了一个数据
7、删除数据,删除了student表中95001行下的Ssex列的所有数据
8、get命令,(用于查看某一行数据,返回的是‘student’表‘95001’行的数据)
9、scan命令(用于查看某个表的全部数据)
10、删除student表中的95001行的全部数据
11、删除表有两步,第一步先让该表不可用,第二步删除表
12、在创建表的时候,指定保存的版本数(假设指定为5)
13、put命令,插入数据然后更新数据,使其产生历史版本数据
14、询时,指定查询的历史版本数。默认会查询出最新的数据。(有效取值为1到5)
15、Eclipse编写java程序,来对HBase数据库进行增删改查等操作
ExampleForHbase类代码如下
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import java.io.IOException;
public class ExampleForHbase{
public static Configuration configuration;
public static Connection connection;
public static Admin admin;
//主函数中的语句请逐句执行,只需删除其前的//即可,如:执行insertRow时请将其他语句注释
public static void main(String[] args)throws IOException{
//创建一个表,表名为Score,列族为sname,course
createTable("Score",new String[]{"sname","course"});
//在Score表中插入一条数据,其行键为95001,sname为Mary(因为sname列族下没有子列所以第四个参数为空)
//等价命令:put 'Score','95001','sname','Mary'
insertRow("Score", "95001", "sname", "", "Mary");
//在Score表中插入一条数据,其行键为95001,course:Math为88(course为列族,Math为course下的子列)
//等价命令:put 'Score','95001','score:Math','88'
//insertRow("Score", "95001", "course", "Math", "88");
//在Score表中插入一条数据,其行键为95001,course:English为85(course为列族,English为course下的子列)
//等价命令:put 'Score','95001','score:English','85'
//insertRow("Score", "95001", "course", "English", "85");
//1、删除Score表中指定列数据,其行键为95001,列族为course,列为Math
//执行这句代码前请deleteRow方法的定义中,将删除指定列数据的代码取消注释注释,将删除制定列族的代码注释
//等价命令:delete 'Score','95001','score:Math'
//deleteRow("Score", "95001", "course", "Math");
//2、删除Score表中指定列族数据,其行键为95001,列族为course(95001的Math和English的值都会被删除)
//执行这句代码前请deleteRow方法的定义中,将删除指定列数据的代码注释,将删除制定列族的代码取消注释
//等价命令:delete 'Score','95001','score'
//deleteRow("Score", "95001", "course", "");
//3、删除Score表中指定行数据,其行键为95001
//执行这句代码前请deleteRow方法的定义中,将删除指定列数据的代码注释,以及将删除制定列族的代码注释
//等价命令:deleteall 'Score','95001'
//deleteRow("Score", "95001", "", "");
//查询Score表中,行键为95001,列族为course,列为Math的值
//getData("Score", "95001", "course", "Math");
//查询Score表中,行键为95001,列族为sname的值(因为sname列族下没有子列所以第四个参数为空)
//getData("Score", "95001", "sname", "");
//删除Score表
//deleteTable("Score");
}
//建立连接
public static void init(){
configuration = HBaseConfiguration.create();
configuration.set("hbase.rootdir","hdfs://localhost:9000/hbase");
try{
connection = ConnectionFactory.createConnection(configuration);
admin = connection.getAdmin();
}catch (IOException e){
e.printStackTrace();
}
}
//关闭连接
public static void close(){
try{
if(admin != null){
admin.close();
}
if(null != connection){
connection.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
/**
* 建表。HBase的表中会有一个系统默认的属性作为主键,主键无需自行创建,默认为put命令操作中表名后第一个数据,因此此处无需创建id列
* @param myTableName 表名
* @param colFamily 列族名
* @throws IOException
*/
public static void createTable(String myTableName,String[] colFamily) throws IOException {
init();
TableName tableName = TableName.valueOf(myTableName);
if(admin.tableExists(tableName)){
System.out.println("talbe is exists!");
}else {
HTableDescriptor hTableDescriptor = new HTableDescriptor(tableName);
for(String str:colFamily){
HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(str);
hTableDescriptor.addFamily(hColumnDescriptor);
}
admin.createTable(hTableDescriptor);
System.out.println("create table success");
}
close();
}
/**
* 删除指定表
* @param tableName 表名
* @throws IOException
*/
public static void deleteTable(String tableName) throws IOException {
init();
TableName tn = TableName.valueOf(tableName);
if (admin.tableExists(tn)) {
admin.disableTable(tn);
admin.deleteTable(tn);
}
close();
}
/**
* 查看已有表
* @throws IOException
*/
public static void listTables() throws IOException {
init();
HTableDescriptor hTableDescriptors[] = admin.listTables();
for(HTableDescriptor hTableDescriptor :hTableDescriptors){
System.out.println(hTableDescriptor.getNameAsString());
}
close();
}
/**
* 向某一行的某一列插入数据
* @param tableName 表名
* @param rowKey 行键
* @param colFamily 列族名
* @param col 列名(如果其列族下没有子列,此参数可为空)
* @param val 值
* @throws IOException
*/
public static void insertRow(String tableName,String rowKey,String colFamily,String col,String val) throws IOException {
init();
Table table = connection.getTable(TableName.valueOf(tableName));
Put put = new Put(rowKey.getBytes());
put.addColumn(colFamily.getBytes(), col.getBytes(), val.getBytes());
table.put(put);
table.close();
close();
}
/**
* 删除数据
* @param tableName 表名
* @param rowKey 行键
* @param colFamily 列族名
* @param col 列名
* @throws IOException
*/
public static void deleteRow(String tableName,String rowKey,String colFamily,String col) throws IOException {
init();
Table table = connection.getTable(TableName.valueOf(tableName));
Delete delete = new Delete(rowKey.getBytes());
//删除指定列族的所有数据
//delete.addFamily(colFamily.getBytes());
//删除指定列的数据
//delete.addColumn(colFamily.getBytes(), col.getBytes());
table.delete(delete);
table.close();
close();
}
/**
* 根据行键rowkey查找数据
* @param tableName 表名
* @param rowKey 行键
* @param colFamily 列族名
* @param col 列名
* @throws IOException
*/
public static void getData(String tableName,String rowKey,String colFamily,String col)throws IOException{
init();
Table table = connection.getTable(TableName.valueOf(tableName));
Get get = new Get(rowKey.getBytes());
get.addColumn(colFamily.getBytes(),col.getBytes());
Result result = table.get(get);
showCell(result);
table.close();
close();
}
/**
* 格式化输出
* @param result
*/
public static void showCell(Result result){
Cell[] cells = result.rawCells();
for(Cell cell:cells){
System.out.println("RowName:"+new String(CellUtil.cloneRow(cell))+" ");
System.out.println("Timetamp:"+cell.getTimestamp()+" ");
System.out.println("column Family:"+new String(CellUtil.cloneFamily(cell))+" ");
System.out.println("row Name:"+new String(CellUtil.cloneQualifier(cell))+" ");
System.out.println("value:"+new String(CellUtil.cloneValue(cell))+" ");
}
}
}
编程实例代码运行结果
执行完插入数据后,在shell界面中执行scan ‘Score’
第2题. HBase Shell数据库表创建
【实验内容】
根据以下关系型数据库表,使用HBase Shell设计并创建适宜的HBase数据表。
1、启动hadoop、hbase
2、进入hbase的shell界面
3、创建表格“Student”
4、创建表格“Score”和“SC”
5、查看已有的表格
6、给“Student”表学号为“2020001”添加姓名、性别、年龄
7、给“Student”表学号为“2020003”添加姓名、性别、年龄
8、给“Student”表学号为“2020005”添加姓名、性别、年龄
9、scan命令查看“Student”表格信息
10、给“Course”表学号为“123001、123002、123003”分别添加对应的课程名称
11、给“Course”表学号为“123001、123002、123003”添加学分
12、查看“Course”表格的全部数据
13、向学生表添加课程列族
14、scan命令查看“Student”表格信息
第3题 HBase Shell数据访问操作
【实验内容】
(1)使用HBase Shell命令向第1题所构建的HBase数据表中添加适宜数据;
(2)使用HBase Shell命令从第1题所构建的HBase数据表中查询出数据;
(3)使用HBase Shell命令从第1题所构建的HBase数据表中删除任一数据;
(4)使用HBase Shell命令统计第1题所构建的HBase数据表的行数。【实验过程】(步骤、记录、数据、程序等)
请提供相应Shell操作命令或相应Shell界面截图证明。
1、在“Student”添加数据
2、查询出数据
3、删除任一数据
4、统计“Student”表的行数
第4题 HBase Java API编程
【实验内容】
根据第1,2题所建立的表,请编程完成以下指定功能:
(1)createTable(String tableName, String[] fields)
创建表,参数tableName为表的名称,字符串数组fields为存储记录各个域名称的数组。要求当HBase已经存在名为tableName的表的时候,先删除原有的表,然后再创建新的表。
(2)addRecord(String tableName, String row, String[] fields, String[] values)
向表tableName、行row(用S_Name表示)和字符串数组files指定的单元格中添加对应的数据values。其中fields中每个元素如果对应的列族下还有相应的列限定符的话,用“columnFamily:column”表示。例如,同时向“Math”、“Computer Science”、“English”三列添加成绩时,字符串数组fields为{“Score:Math”,”Score;Computer Science”,”Score:English”},数组values存储这三门课的成绩。
(3)scanColumn(String tableName, String column)
浏览表tableName某一列的数据,如果某一行记录中该列数据不存在,则返回null。要求当参数column为某一列族名称时,如果底下有若干个列限定符,则要列出每个列限定符代表的列的数据;当参数column为某一列具体名称(例如“Score:Math”)时,只需要列出该列的数据。
(4)modifyData(String tableName, String row, String column)
修改表tableName,行row(可以用学生姓名S_Name表示),列column指定的单元格的数据。
(5)deleteRow(String tableName, String row)
删除表tableName中row指定的行的记录。1、创建java工程
2、菜单函数,java程序代码如下
HBaseModifyStudent类代码如下
import java.io.IOException;
import java.util.Scanner;
public class HBaseModifyStudent {
public static void main(String[] args) throws IOException{
HBaseStudentOperation h1=new HBaseStudentOperation();
@SuppressWarnings("resource")
Scanner in = new Scanner(System.in);
while(true){
System.out.println("**********************基于JAVA的Hbase数据库表及表的基本操作**********************");
System.out.println("1、创建学生选课表");
System.out.println("2、向创建的表中添加学生信息");
System.out.println("3、浏览创建的选课表中指定列的数据");
System.out.println("4、修改指定单元格的数据");
System.out.println("5、删除指定行的数据");
System.out.println("0、退出!");
System.out.print("请输入你的选择:");
int a=in.nextInt();
switch(a){
case 1: h1.createTable("StudentScore",new String[]{"student","Math","ComputerScience","English"});break;
case 2: h1.addRecord("StudentScore","Zhangsan",new String[]{"student:S_No","student:S_Name","student:S_Sex","student:S_Age","Math:C_No","Math:C_Name","Math:C_Credit","Math:SC_Score","English:C_No","English:C_Name","English:C_Credit","English:SC_Score"}, new String[]{"2020001","Zhangsan","male","23","123001","Math","2.0","86","123003","English","3.0","69"});break;
case 3: h1.scanColumn("StudentScore", "Math");break;
case 4: h1.modifyData("StudentScore","Zhangsan","Math:SC_Score","89");break;
case 5: h1.deleteRow("StudentScore","Zhangsan");break;
case 0: return;
}
}
}
}
3、连接和关闭Hbase数据库的JAVA代码
HBaseStudentOperation类代码如下
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.*;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import java.io.IOException;
import java.util.Scanner;
public class HBaseStudentOperation{
public static Configuration configuration;
public static Connection connection;
public static Admin admin;
//建立连接
public static void init(){
configuration = HBaseConfiguration.create();
configuration.set("hbase.rootdir","hdfs://localhost:9000/hbase");
try{
connection = ConnectionFactory.createConnection(configuration);
admin = connection.getAdmin();
}catch (IOException e){
e.printStackTrace();
}
}
//关闭连接
public static void close(){
try{
if(admin != null){
admin.close();
}
if(null != connection){
connection.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
/**
* 建表。HBase的表中会有一个系统默认的属性作为主键,主键无需自行创建,默认为put命令操作中表名后第一个数据,因此此处无需创建id列
* @param myTableName 表名
* @param colFamily 列族名
* @throws IOException
*/
public static void createTable(String myTableName,String[] colFamily) throws IOException {
@SuppressWarnings("resource")
Scanner in = new Scanner(System.in);
init();
TableName tableName = TableName.valueOf(myTableName);
if(admin.tableExists(tableName)){
System.out.println("该表已经存在!");
System.out.println("是否删除该表重新创建?");
System.out.println("1、是");
System.out.println("2、否");
System.out.print("请输入你的选择:");
int a=in.nextInt();
switch(a){
case 1:if (admin.tableExists(tableName)) {
admin.disableTable(tableName);
admin.deleteTable(tableName);
System.out.println("表:"+tableName+"已成功删除");
}
HTableDescriptor hTableDescriptor = new HTableDescriptor(tableName);
for(String str:colFamily){
HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(str);
hTableDescriptor.addFamily(hColumnDescriptor);
}
admin.createTable(hTableDescriptor);
System.out.println("表创建成功!");break;
case 2:break;
}
}else {
HTableDescriptor hTableDescriptor = new HTableDescriptor(tableName);
for(String str:colFamily){
HColumnDescriptor hColumnDescriptor = new HColumnDescriptor(str);
hTableDescriptor.addFamily(hColumnDescriptor);
}
admin.createTable(hTableDescriptor);
System.out.println("表创建成功!");
}
close();
}
public void addRecord(String tableName,String rowKey,String []fields,String [] values) throws IOException {
init();
Table table = connection.getTable(TableName.valueOf(tableName));
for (int i = 0; i < fields.length; i++) {
Put put = new Put(rowKey.getBytes());
String [] cols = fields[i].split(":");
if(cols.length==1){
put.addColumn(cols[0].getBytes(), "".getBytes(), values[i].getBytes());//因为当输入的是单列族,split仅读出一个字符字符串,即cols仅有一个元素
}
else {
put.addColumn(cols[0].getBytes(), cols[1].getBytes(), values[i].getBytes());
}
table.put(put);
}
System.out.println("数据插入成功");
table.close();
close();
}
public void scanColumn (String tableName,String column) throws IOException{
init();
Table table = connection.getTable(TableName.valueOf(tableName));
Scan scan = new Scan();
String [] cols = column.split(":");
if(cols.length==1){
scan.addFamily(Bytes.toBytes(column));
}
else {
scan.addColumn(Bytes.toBytes(cols[0]),Bytes.toBytes(cols[1]));
}
ResultScanner scanner = table.getScanner(scan);
for (Result result = scanner.next(); result !=null;result = scanner.next()) {
showCell(result);
}
table.close();
close();
}
public void modifyData(String tableName,String rowKey,String column,String value) throws IOException{
init();
Table table = connection.getTable(TableName.valueOf(tableName));
Put put = new Put(rowKey.getBytes());
String [] cols = column.split(":");
if(cols.length==1){
put.addColumn(column.getBytes(),"".getBytes() , value.getBytes());//qualifier:列族下的列名
}
else {
put.addColumn(cols[0].getBytes(),cols[1].getBytes() , value.getBytes());//qualifier:列族下的列名
}
System.out.println("信息修改成功!");
table.put(put);
table.close();
close();
}
public void showCell(Result result){
Cell[] cells = result.rawCells();
for(Cell cell:cells){
System.out.println("RowName:"+new String(CellUtil.cloneRow(cell))+" ");
System.out.println("Timetamp:"+cell.getTimestamp()+" ");
System.out.println("column Family:"+new String(CellUtil.cloneFamily(cell))+" ");
System.out.println("row Name:"+new String(CellUtil.cloneQualifier(cell))+" ");
System.out.println("value:"+new String(CellUtil.cloneValue(cell))+" ");
}
}
public void deleteRow(String tableName,String rowKey) throws IOException{
init();
Table table = connection.getTable(TableName.valueOf(tableName));
Delete delete = new Delete(rowKey.getBytes());
table.delete(delete);
System.out.println("删除成功!");
table.close();
close();
}
}
4、创建学生信息表
5、添加学生选课信息
6、浏览学生选课信息表
7、修改学生选课信息
8、删除学生选课信息
运行结果如下
选择1,创建学生选课表
再次创建,提示该表已经存在
选择2,学生Zhangsan选课信息的录入
Scan命令,查看插入成功的结果
选择3,进行学生Zhangsan数学课程信息的查询,结果如下
选择4,进行学生Zhangsan数学成绩的修改
Scan命令查询结果(之前是86分,现在89分)
选择5,进行学生Zhangsan一行的信息的删除
Scan命令查询结果(可见,zhangshan的信息已经被全部删除)