1,概念
hbase 是一个可以建立在 hdfs 上的分布式 nosql 数据库。
hbase 有三种安装方式:单机,伪分布式,完全分布式。
单机 hbase:hbase 数据库的数据文件存在单一的一台设备上,使用的是该设备的文件系统。
伪分布式 hbase:hbase 数据库的数据文件存在一台设备构成的 hdfs 上,数据库分主从结构。
完全分布式 hbase:hbase 数据库的数据文件存在多台设备构成的 hdfs 上,数据库分主从结构。
2,术语
1)hregion:指的是 hbase 的数据库存储是以区快(region)存储的
2)hregionservers:hbase 数据库从机。存具体数据。
3)hmaster:hbase 主机。存储元数据。
4)行(row)与行键(rowkey):
hbase 中一条完整的数据即一行,由一个唯一的行键+多个列键值构成。
行键:每一行都有一个内置的主键,用于区别其他行数据。
5)列簇(columnfamily):
hbase 中列簇指的是一个大列,这个大的列可以有0个(列簇即列)或多个(column)列构成。
新建表时只需要指定列簇,不需要指定列。
6)列键(column):
hbase 中第一行数据都是由很多列键构成的,其中一个列一般都有一个或多个列键。
每一个列键值都由行键,单元格值,时间戳,版本 构成。
7)单元格(cell 或者 列键值):
3,hbase安装
1)获取 hbase 安装包并解压到 node1 的 /home/hduser 下
2)配置 hbase 核心配置文件(/conf/hbase-site.xml)
<!-- 设置 hbase 在 hdfs 数据的存储位置 -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://node1:9000/hbase</value>
</property>
<!-- 设置 hbase 是完全分布式类型 -->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!-- hbase 的访问地址 -->
<property>
<name>hbase.master</name>
<value>node1:60000</value>
</property>
<!-- hbase 的家庭成员(主从机的网络用户名)-->
<property>
<name>hbase.zookeeper.quorum</name>
<value>node1,node2,node3</value>
</property>
3)配置 hbase 环境配置文件(/conf/hbase-env.sh)
修改 JAVA_HOME 配置:export JAVA_HOME=/usr/java/jdk1.8.0_171
增加 HADOOP_HOME 配置:export HADOOP_HOME=/home/hduser/hadoop
增加 HBASE_HOME 配置:export HBASE_HOME=/home/hduser/hbase-1.2.0
增加启用 hbase 内置zookeeper 配置:export HBASE_MANAGERS_ZK=true
export JAVA_HOME=/usr/java/jdk1.8.0_171
export HADOOP_HOME=/home/hduser/hadoop
export HBASE_HOME=/home/hduser/hbase-1.2.0
export HBASE_MANAGERS_ZK=true
4)配置从机网络用户名(/conf/regionservers)
node2
node3
5)拷贝 node1 的 hbase 的主目录到 node2,node3
scp -r /home/hduser/hbase-1.2.0/ hduser@node2:/home/hduser/
scp -r /home/hduser/hbase-1.2.0/ hduser@node3:/home/hduser/
4,hbase 的启动与关闭
1)启动(启动前必须保证 hdfs 已经启动):
$>hbase 主目录下/bin/start-hbase.sh
2)关闭:
$>hbase 主目录下/bin/stop-hbase.sh
3)浏览器测试:访问:http://node1:16010
4)命令测试(登陆进入数据库):$>hbase 主目录下/bin/hbase shell
5,hbase sql 使用
命令都在 hbase 主目录下/bin/下,可以配置 bin 到环境变量 PATH 下
1)查所有表:$hbase>list
2)新建表,列,列簇:$hbase>create 表名,'列簇1,、、、,'列簇n'
样例:新建播放记录表 music
$hbase>create 'music','song','singer','playdate'
3)插入数据:$hbase>put 表名,'主键值','列名','单元格值'
样例:插入播放记录
$hbase>put music,'1001','song','music1'
$hbase>put music,'1001','singer','singer1'
$hbase>put music,'1001','playdate','2019-11-1'
4)扫描一张表:$hbase>scan 表名
样例:查询 music 表所有记录
$hbase>scan music
5)查询一行数据(不筛选):$hbase>get 表名 行主键名
样例:只查看 1001 的数据
$hbase>get music '1001'
6)查询一行中某些单元格的数据(筛选):$hbase>get 表名 行主键名 {CLOUMNS=>[列1,列2]}
7)删除数据(删除一行中一部分):$hbase>delete 表名 行主键名 {CLOUMNS=>[列1,列2]}
8)删除一行:$hbase>deleteall 表名 行主键名
9)删除表:
$hbase>disable 表名 //更改表结构,需要先禁用表
$hbase>drop 表名 //删除表
10)删除表:禁用后启用表:$hbase>enbale 表名
11)查看表结构:$hbase>desc 表名
6,eclipse 开发 hbase(java 操作 hbase)
6.1,术语
1)HBaseConfiguration:是Configuration的子类,主要用于 hbase 的配置文件管理
2)Admin:是hbase的系统管理对象,主要用于查询所有表,新增表,修改表,删除表等DDL操作
3)TableName:是一个表类型。
TableName.valueOf(Bytes.toBytes("字符串表名"))
6.2,环境搭建
1)新建 mapreduce 项目 hbasedemo
2)增加配置文件 core-site.xml,hbase-site.xml
3)增加 jar 包
hbase-client.jar
hbase-server.jar
hbase-common.jar
hbase-protocol.jar
htrace-core.jar
netty-all.jar
6.3,操作
6.3.1,DDL操作(admin)
1)DDL加载配置文件,获取连接,获取数据库管理对象(admin)
2)查询所有表
6.3.2,DML操作(connection)
1)
2)
6.3.3,hbase 与 java 类型的转换
1)字符串转字节数组
byte[] b = Bytes.toBytes("字符串");
2)数字转字节数组
byte[] b = Bytes.toBytes(数字);
3)字节数组转字符串
String str = Bytes.toString(字节数组);
4)字符数组转数字
int num = Bytes.toInt(字节数组);
6.4,java代码如下:
package cn.kgc1803;
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.TableName;
import org.apache.hadoop.hbase.TableNotFoundException;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Connection;
import org.apache.hadoop.hbase.client.ConnectionFactory;
import org.apache.hadoop.hbase.client.Get;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.client.ResultScanner;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.client.Table;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class TestHbase {
private Admin admin;
private Connection conn;
@Before
public void before() throws IOException{
//DDL 加载配置文件
Configuration conf = HBaseConfiguration.create();
//获取连接
conn = ConnectionFactory.createConnection(conf);
}
//查询所有表
@Test
public void fun1() throws IOException{
//获取数据库管理对象
admin = conn.getAdmin();
//表名是 TableName 数组类型
TableName[] tns = admin.listTableNames();
for(TableName tableName:tns){
System.out.println(tableName);
}
}
//查询一行数据
@Test
public void fun2() throws IllegalArgumentException, IOException{
//获取一张现有表
Table tb = conn.getTable(TableName.valueOf(Bytes.toBytes("scores")));
//get scores ,1001,一个Get对象就是查询一行
Get get = new Get(Bytes.toBytes("1001"));
Result rs = tb.get(get);
System.out.println(rs.value());
}
//新建一张表
@Test
public void fun3() throws IOException{
//新表
TableName tn = TableName.valueOf(Bytes.toBytes("music1"));
HTableDescriptor tableDesc = new HTableDescriptor(tn);
//设置列簇
HColumnDescriptor colDesc =new HColumnDescriptor(Bytes.toBytes("song"));
HColumnDescriptor colDes1 =new HColumnDescriptor(Bytes.toBytes("singer"));
HColumnDescriptor colDes2 =new HColumnDescriptor(Bytes.toBytes("playdate"));
//将新定义的列簇定义到TableName中去
tableDesc.addFamily(colDesc);
tableDesc.addFamily(colDes1);
tableDesc.addFamily(colDes2);
//将该操作更新到数据库
admin.createTable(tableDesc);
}
//增加或删除列簇
@Test
public void fun4() throws TableNotFoundException, IOException{
// 新表
TableName tn = TableName.valueOf(Bytes.toBytes("music1"));
HTableDescriptor tableDesc = admin.getTableDescriptor(tn);
// 设置列簇
HColumnDescriptor colDesc = new HColumnDescriptor(Bytes.toBytes("playtime"));
// 将新定义的列簇定义到TableName中去
tableDesc.addFamily(colDesc);
// 将TableName的列簇去除
tableDesc.removeFamily(Bytes.toBytes("playdate"));
// 将该操作更新到数据库
admin.modifyTable(tn, tableDesc);
}
//删除表
@Test
public void fun5() throws IOException{
TableName tn = TableName.valueOf(Bytes.toBytes("music1"));
if(admin.tableExists(tn)){ //判断表是否存在
admin.disableTable(tn); //禁用表
admin.deleteTable(tn); //删除表
}
}
//新增数据
@Test
public void fun6() throws IOException{
TableName tn = TableName.valueOf(Bytes.toBytes("music1"));
Table tb = conn.getTable(tn); //from music1
Put put = new Put(Bytes.toBytes("1001")); //指定行键
//确定列键值
put.addColumn(Bytes.toBytes("song"), Bytes.toBytes(""), Bytes.toBytes("music"));
put.addColumn(Bytes.toBytes("singer"), Bytes.toBytes(""), Bytes.toBytes("zhangsan"));
put.addColumn(Bytes.toBytes("playdate"), Bytes.toBytes(""), Bytes.toBytes("2018-11-12"));
tb.put(put);
}
//按行查询
@Test
public void fun7() throws IOException{
TableName tn = TableName.valueOf(Bytes.toBytes("music1"));
Table tb = conn.getTable(tn); //from music1
//确定一行
Get get = new Get(Bytes.toBytes("1001"));
//筛选列
get.addFamily(Bytes.toBytes("song"));
Result rs = tb.get(get);
//rs.listCells(); //查询结果中所有单元格的值
System.out.println("列簇\t列名\t值");
for(Cell c:rs.listCells()){
System.out.println(
CellUtil.cloneFamily(c)+"\t"+ //列簇
CellUtil.cloneQualifier(c)+"\t"+ //列键
CellUtil.cloneValue(c)); //值
}
}
//全表查询
@Test
public void fun8() throws IOException{
TableName tn = TableName.valueOf(Bytes.toBytes("music1"));
Table tb = conn.getTable(tn); //from music1
Scan sc = new Scan(); //不加下面的 addFamily 查询所有行
sc.addFamily(Bytes.toBytes("song")); //筛选列
ResultScanner rsc = tb.getScanner(sc);
for(Result rs:rsc){ //遍历出一行
for(Cell c:rs.listCells()){
System.out.println(
CellUtil.cloneFamily(c)+"\t"+ //列簇
CellUtil.cloneQualifier(c)+"\t"+ //列键
CellUtil.cloneValue(c)); //值
}
}
}
//删除列键数据
@Test
public void fun9(){
TableName tn = TableName.valueOf(Bytes.toBytes("music1"));
}
//删除整行
@Test
public void fun10(){
TableName tn = TableName.valueOf(Bytes.toBytes("music1"));
}
@After
public void after(){
}
}