【分布式计算框架】HBase数据库编程实践
【分布式计算框架】HBase数据库编程实践
🕺作者: 主页
我的专栏 C语言从0到1 探秘C++ 数据结构从0到1 探秘Linux 😘欢迎 ❤️关注 👍点赞 🙌收藏 ✍️留言
文章目录
实验四 HBase数据库编程实践
一、实验目的
- 使用HBase Shell命令完成下列任务
(1)列出所有表的相关信息
(2)向已经创建好的表添加和删除指定的列族或列
(3)清空指定表的所有记录数据
(4)统计表的行数
(5)输出指定表的所有记录数据 - 现有关系型数据库中的三张表(学生表,课程表,选课表),要求将其转换为适合HBase存储的表并插入数据。
- 编程完成以下指定功能:
(1)createTable(String tableName,String[] fields)
创建表,要求当HBase已经存在名为tableName的表的时候,先删除原有的表再创建新表
(2)addRecord(String tableName,String row,String[] fields,String[] values)
向表tableName,行row和字符串数组fields指定的单元格中添加对应的数据values。
(3)scanColumn(String tableName,String column)
浏览表tableName某一列的数据,如果某一行记录中该列数据不存在,则返回null.
二、实验环境
- centos 6.5
- java 1.7
- vmware workstation
- 伪分布式hadoop
三、实验内容
伪分布式搭建
- 上传hbase-0.98.12.1-hadoop2-bin.tar.gz
- 解压
tar -zxvf hbase-0.98.12.1-hadoop2-bin.tar.gz -C /opt/20191909/
-
配置环境变量
vi /etc/profile
export HBASE_HOME=/opt/20191909/hbase-0.98.12.1-hadoop2
PATH= P A T H : PATH: PATH:HBASE_HOME/bin
使其生效
-
配置 hbase-env.sh (路径:/opt/20191909/hbase-0.98.12.1-hadoop2/conf/)
export JAVA_HOME=/usr/java/jdk1.7.0_67
export HBASE_MANAGES_ZK=true
(4)配置 hbase-site.xml(路径:/opt/20191909/hbase-0.98.12.1-hadoop2/conf/)
<property>
<name>hbase.rootdir</name>
<value>hdfs://20191909node01:9000/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>20191909node01</value>
</property>
<property>
<name>hbase.master.info.port</name>
<value>60010</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/var/20191909/zk</value>
</property>
(5)启动HBase
start-hbase.sh //内置zookeeper
jps /查看进程
使用HBase Shell命令完成任务
//ctrl+Backspace 退格
(1)列出所有表的相关信息
> list
(2)向已经创建好的表添加和删除指定的列族或列
向名为 student
的表添加一个新的列族 info3
,可以执行以下命令:
> alter 'student', {NAME=>'info3'}
(3)清空指定表的所有记录数据
清空名为 student
的表的所有数据,可以执行以下命令:
> truncate 'student'
(4)统计表的行数
统计名为 student
的表的行数,可以执行以下命令:
> count 'student'
(5)输出指定表的所有记录数据
输出名为 student 的表的所有记录数据,可以执行以下命令:
> scan 'student'
转换适合HBase存储的表并插入数据
现有关系型数据库中的三张表(学生表,课程表,选课表),要求将其转换为适合HBase存储的表并插入数据。
学生(Student)表:
学号(S_No) | 姓名(S_Name) | 性别(S_Sex) | 年龄(S_Age) |
---|---|---|---|
2015001 | Zhangsan | male | 23 |
2015002 | Mary | female | 22 |
2015003 | Lisi | male | 24 |
create 'Student','S_No','S_Name','S_Sex','S_Age'
put 'Student','s001','S_No','2015001'
put 'Student','s001','S_Name','Zhangsan'
put 'Student','s001','S_Sex','male'
put 'Student','s001','S_Age','23'
put 'Student','s002','S_No','2015002'
put 'Student','s002','S_Name','Mary'
put 'Student','s002','S_Sex','female'
put 'Student','s002','S_Age','22'
put 'Student','s003','S_No','2015003'
put 'Student','s003','S_Name','Lisi'
put 'Student','s003','S_Sex','male'
put 'Student','s003','S_Age','24'
课程(Course)表:
课程号(C_No) | 课程名(C_Name) | 学分(C_Credit) |
---|---|---|
123001 | Math | 2.0 |
123002 | Computer Science | 5.0 |
123003 | English | 3.0 |
create 'Course','C_No','C_Name','C_Credit'
put 'Course','c001','C_No','123001'
put 'Course','c001','C_Name','Math'
put 'Course','c001','C_Credit','2.0'
put 'Course','c002','C_No','123002'
put 'Course','c002','C_Name','Computer'
put 'Course','c002','C_Credit','5.0'
put 'Course','c003','C_No','123003'
put 'Course','c003','C_Name','English'
put 'Course','c003','C_Credit','3.0'
选课(SC)表:
学号(SC_Sno) | 课程号(SC_Cno) | 成绩(SC_Score) |
---|---|---|
2015001 | 123001 | 86 |
2015001 | 123003 | 69 |
2015002 | 123002 | 77 |
2015002 | 123003 | 99 |
2015003 | 123001 | 98 |
2015003 | 123002 | 95 |
create 'SC','SC_Sno','SC_Cno','SC_Score'
put 'SC','sc001','SC_Sno','2015001'
put 'SC','sc001','SC_Cno','123001'
put 'SC','sc001','SC_Score','86'
put 'SC','sc002','SC_Sno','2015001'
put 'SC','sc002','SC_Cno','123003'
put 'SC','sc002','SC_Score','69'
put 'SC','sc003','SC_Sno','2015002'
put 'SC','sc003','SC_Cno','123002'
put 'SC','sc003','SC_Score','77'
put 'SC','sc004','SC_Sno','2015002'
put 'SC','sc004','SC_Cno','123003'
put 'SC','sc004','SC_Score','99'
put 'SC','sc005','SC_Sno','2015003'
put 'SC','sc005','SC_Cno','123001'
put 'SC','sc005','SC_Score','98'
put 'SC','sc006','SC_Sno','2015003'
put 'SC','sc006','SC_Cno','123002'
put 'SC','sc006','SC_Score','95'
编程完成指定功能
(1)新建一个java 项目
导入hbase包和JUnit:
- 右击项目-build path-add libraries
导入jar包:
- 菜单:add external JARS
- 选择hbase安装目录\lib里所有jar包,除了ruby
- 项目里导入hbase_jars包 //右击项目名-build path-configure build path-java build path-libraries-add library-use library-
(2) 新建一个com.hxq类
(3) 导入配置文件(hbase-site.xml,regionservers)
编程完成以下指定功能。
-
createTable(String tableName, String[]fields)。
创建表,参数 tableName为表的名称,字符串数组fields为存储记录各个域名称的数组。要求当HBase已经存在名为tableName的表的时候,先删除原有的表,再创建新的表。 -
addRecord(String tableName, String row, String ] fields, String[] values)。
向表tableName、行row(用S_Name表示)和字符串数组fields指定的单元格中添加对应的数据 values。其中,如果fields中每个元素对应的列族下还有相应的列限定符,用“columnFamily:column”表示。例如同时向“Math”“Computer Science”“English”3列添加成绩时,字符串数组fields为{“Score:Math”,“Score:Computer Science”,“Score:English”},数组 values存储这3门课的成绩。 -
scanColumn(String tableName, String column)。
浏览表 tableName某一列的数据,如果某一行记录中该列数据不存在,则返回null。要求当参数column为某一列族名称时,如果底下有若干个列限定符,则列出每个列限定符代表的列的数据:当参数column为某一列具体名称(如“Score:Math”)时,只需要列出该列的数据。 -
modifyData(String tableNameString rowStringcolumn)。
修改表tableName、行row(可以用学生姓名SName表示)、列column指定的单元格的数据。 -
deleteRow(String tableName, String row)。
删除表tableName中row指定的行的记录。
在实验结果中
四、出现的问题及解决方案
无
五、实验结果
(HBase Shell命令及执行结果)
(程序源代码及程序运行结果)
package com.hxq;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.TableNotFoundException;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.HBaseAdmin;
import org.apache.hadoop.hbase.client.HTable;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.util.Bytes;
public class CreateTable {
static Configuration conf;
static HBaseAdmin admin;
static HTable htable;
public static void main(String[] args) throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
String name = "hxq";
String[] s = {"info","Do"};
init();
// creatTable(name,s);
// addRecord(name,"20191909",new String[]{"name","age"},new String[]{"hxq","20"});
scanColumn(name,"name");
}
public static void init() throws MasterNotRunningException, ZooKeeperConnectionException, IOException{
conf=HBaseConfiguration.create();
admin=new HBaseAdmin(conf);
}
public static void creatTable(String tableName,String[] fields) throws IOException{
//(2)删除已存在的同名表
if(admin.tableExists(tableName)){
admin.disableTable(tableName);
admin.deleteTable(tableName);
}
//(1)表描述
HTableDescriptor desc=new HTableDescriptor(TableName.valueOf(tableName));
for(String s:fields) {
HColumnDescriptor cf=new HColumnDescriptor(s.getBytes());
desc.addFamily(cf);
}
admin.createTable(desc);
}
public static void addRecord(String tableName,String row,String[] fields,String[] values) throws IOException {
int f =fields.length-1,v=values.length-1;
String temp = "info";
htable=new HTable(conf,tableName.getBytes());
Put put=new Put(row.getBytes());
for(int i=0,j=0;i<=f;i++,j++) {
if(j>v) {
put.add(temp.getBytes(),fields[i].getBytes(),"null".getBytes());
}else if(i==f&&j<v) {
put.add(temp.getBytes(),fields[i].getBytes(),values[j].getBytes());
i=0;
}else {
put.add(temp.getBytes(),fields[i].getBytes(),values[j].getBytes());
}
}
htable.put(put);
}
public static void scanColumn(String tableName,String column) throws TableNotFoundException, IOException {
htable=new HTable(conf,tableName.getBytes());
Get get=new Get(Bytes.toBytes("20191909"));
Result rs=htable.get(get);
Cell cell=rs.getColumnLatestCell("info".getBytes(), column.getBytes());
System.out.println(new String(CellUtil.cloneValue(cell)));
// }
}
}
六、实验思考题
- 请以实例说明HBase数据类型。
HBase中的数据类型主要包括以下几种:
- Row Key(行键):行键是HBase表中每行数据的唯一标识符,类似于传统数据库中的主键。行键通常以字节数组形式存储,可以是任意长度的字节数组。
- Column Family(列族):列族是HBase表中的逻辑分组,用于组织和存储列。每个列族在底层存储时会被存储在不同的存储文件中,因此在设计表结构时需要合理划分列族。
- Column Qualifier(列限定符):列限定符是列族下的具体列,在HBase中以字节数组形式存储。一个列族可以包含多个列限定符,用于存储不同的数据。
- Cell(单元格):单元格是HBase中最小的数据单元,由行键、列族和列限定符唯一确定。每个单元格存储一个特定的数值或数据。
示例:假设有一张HBase表存储学生成绩数据,其中包含列族“Score”,列族下有列限定符“Math”、“Computer Science”、“English”。每个单元格存储对应科目的成绩数据。在这个例子中,行键表示学生ID,列族为“Score”,列限定符为具体的科目,每个单元格存储某个学生特定科目的成绩数据。
- 执行start-hbase.sh,启动了哪些进程?
执行start-hbase.sh脚本会启动HBase服务,包括以下进程:
- HMaster:HBase的主节点服务,负责管理整个HBase集群,包括表的创建、删除、负载均衡等任务。
- HRegionServer:HBase的数据节点服务,负责实际存储表数据并处理读写请求。
- HQuorumPeer:内置的ZooKeeper服务,用于协调HBase集群中各节点之间的通信和协作。
通过执行start-hbase.sh脚本,以上进程会被启动以构建一个完整的HBase集群环境。
- 编程中创建了哪些java对象?
在编程中创建了以下Java对象:
- Configuration对象:用于配置HBase客户端连接参数,如ZooKeeper地址等。
- HBaseAdmin对象:用于与HBase集群进行交互,执行管理操作,如创建表、删除表等。
- HTable对象:用于与HBase表进行交互,进行数据的读写操作。
- HColumnDescriptor对象:用于描述列族的属性,如名称、版本等。
- Put对象:用于插入数据到HBase表的指定行的单元格中。
- Get对象:用于从HBase表中获取指定行的数据。
- Result对象:用于存储从HBase表中获取的行数据结果。
- Cell对象:用于表示HBase表中的单元格数据,包含行键、列族、列限定符等信息。
理读写请求。
- HQuorumPeer:内置的ZooKeeper服务,用于协调HBase集群中各节点之间的通信和协作。
通过执行start-hbase.sh脚本,以上进程会被启动以构建一个完整的HBase集群环境。
- 编程中创建了哪些java对象?
在编程中创建了以下Java对象:
- Configuration对象:用于配置HBase客户端连接参数,如ZooKeeper地址等。
- HBaseAdmin对象:用于与HBase集群进行交互,执行管理操作,如创建表、删除表等。
- HTable对象:用于与HBase表进行交互,进行数据的读写操作。
- HColumnDescriptor对象:用于描述列族的属性,如名称、版本等。
- Put对象:用于插入数据到HBase表的指定行的单元格中。
- Get对象:用于从HBase表中获取指定行的数据。
- Result对象:用于存储从HBase表中获取的行数据结果。
- Cell对象:用于表示HBase表中的单元格数据,包含行键、列族、列限定符等信息。
更多推荐
所有评论(0)