本文主要通过Hbase JavaAPI在Hbase中进行建表及插入数据及HBase的DDL和DML,让你更加了解关于Hbase的相关原理。
如需获取更多源码,笔记,教程,请访问本人仓库,你的关注是我创作的动力!
链接:https://gitee.com/fanggaolei/learning-notes-warehouse
1.0 Hbase原理及基本说明
HBase 数据模型的关键在于稀疏、分布式、多维、排序的映射。其中映射 map指代非关系型数据库的 key-Value 结构。
Hbase存储数据的原貌:
"office_info":{ #列族
"tel":"010-1111111", #tel列
"address":"atguigu" #address列
}
数据模型介绍
(1)Name Spase数据模型:相当于Mysql中的database,下面可以存放多张表
(2)Table:相当于数据库中的表
(3)Row:HBase 表中的每行数据都由一个 RowKey 和多个 Column(列)组成,数据是按照 RowKey
的字典顺序存储的,并且查询数据时只能根据 RowKey 进行检索,所以 RowKey 的设计十分重要。
(4)Column:每个列都由 Column Family(列族)和 Column Qualifier(列限定符)进行限定,例如 info: name,info:age。建表时,只需指明列族,而列限定符无需预先定义。
(5)Time Stamp:用于标识数据的不同版本(version),每条数据写入时,系统会自动为其加上该字段,
其值为写入 HBase 的时间。
(6)Cell:由{rowkey, column Family:column Qualifier, timestamp} 唯一确定的单元。cell 中的数
据全部是字节码形式存贮。
架构说明:
1)Master
实现类为 HMaster,负责监控集群中所有的 RegionServer 实例。主要作用如下:
(1)管理元数据表格 hbase:meta,接收用户对表格创建修改删除的命令并执行
(2)监控 region 是否需要进行负载均衡,故障转移和 region 的拆分。
通过启动多个后台线程监控实现上述功能:
①LoadBalancer 负载均衡器
周期性监控 region 分布在 regionServer 上面是否均衡,由参数 hbase.balancer.period 控制周期时间,默认 5 分钟。
②CatalogJanitor 元数据管理器
定期检查和清理 hbase:meta 中的数据。meta 表内容在进阶中介绍。
③MasterProcWAL master 预写日志处理器
把 master 需要执行的任务记录到预写日志 WAL 中,如果 master 宕机,让 backupMaster读取日志继续干。
2)Region Server
Region Server 实现类为 HRegionServer,主要作用如下:
(1)负责数据 cell 的处理,例如写入数据 put,查询数据 get 等
(2)拆分合并 region 的实际执行者,有 master 监控,有 regionServer 执行。
3)Zookeeper
HBase 通过 Zookeeper 来做 master 的高可用、记录 RegionServer 的部署信息、并且存储有 meta 表的位置信息。 HBase 对于数据的读写操作时直接访问 Zookeeper 的,在 2.3 版本推出 Master Registry模式,客户端可以直接访问 master。使用此功能,会加大对 master 的压力,减轻对 Zookeeper的压力。
4)HDFS
HDFS 为 Hbase 提供最终的底层数据存储服务,同时为 HBase 提供高容错的支持。
2.0HbaseAPI的使用
2.1创建连接
HBase 的客户端连接由 ConnectionFactory 类来创建,用户使用完成之后需要手动关闭连接。同时连接是一个重量级的,推荐一个进程使用一个连接,对 HBase的命令通过连接中的两个属性 Admin 和 Table 来实现。使用类单例模式,确保使用一个连接,可以同时用于多个线程。
packagecom.fang.hbase;importorg.apache.hadoop.conf.Configuration;importorg.apache.hadoop.hbase.HBaseConfiguration;importorg.apache.hadoop.hbase.client.Connection;importorg.apache.hadoop.hbase.client.ConnectionFactory;importjava.io.IOException;publicclassHbaseConnection{publicstaticConnection connection=null;//声明一个静态属性static{//1.创建连接//默认使用同步连接try{//使用读取本地文件的方式添加参数
connection=ConnectionFactory.createConnection();}catch(IOException e){
e.printStackTrace();}}publicstaticvoidcloseConnection()throwsIOException{//判断连接是否为nullif(connection!=null){
connection.close();}}publicstaticvoidmain(String[] args)throwsIOException{//直接使用创建好的连接,不要在main线程里面单独创建System.out.println(HbaseConnection.connection);//在main线程的最后记得关闭连接HbaseConnection.closeConnection();}}
还记得静态代码块的特点吗?随着类的加载而执行,而且只执行一次
静态代码块:执行优先级高于非静态的初始化块,它会在类初始化的时候执行一次,执行完成便销毁,它仅能初始化类变量
2.2创建命名空间
在同一个包下创建HbaseDDL类,执行创建命名空间的功能,使用建造者模式
packagecom.fang.hbase;importorg.apache.hadoop.hbase.NamespaceDescriptor;importorg.apache.hadoop.hbase.client.Admin;importorg.apache.hadoop.hbase.client.Connection;importjava.io.IOException;publicclassHBaseDDL{//声明一个静态属性,获取连接publicstaticConnection connection =HbaseConnection.connection;/**
* 创建命名空间,命名空间名称
* @param namespase
* admin的连接是轻量级的,不是线程安全的,不推荐池化或者缓存连接
*/publicstaticvoidcreateNamespace(String namespace)throwsIOException{//1.获取adminAdmin admin = connection.getAdmin();//2.调用方法创建命名空间,给一个描述//代码相对shell更加底层,shell实现的功能,代码一定能实现//2.1创建命名空间描述建造者=》设计师NamespaceDescriptor.Builder builder =NamespaceDescriptor.create(namespace);//2.2给命名空间添加需求
builder.addConfiguration("user","fang");//2.3使用builder构造出对饮的创建一个命名空间描述
admin.createNamespace(builder.build());//3.关闭admin
admin.close();}publicstaticvoidmain(String[] args)throwsIOException{//测试创建命名空间createNamespace("fang");System.out.println("创建成功");//关闭Hbase连接HbaseConnection.closeConnection();}}
执行情况:
在命令行中查看,创建过程,表示创建成功!!!
看这里,前面的代码你会发现,如果你再次执行代码就会发现会出现问题,原因是,创建的命名空间已经存在理论来说这个问题应该自己解决,并不是将异常直接抛出,可参考如下代码
packagecom.fang.hbase;importorg.apache.hadoop.hbase.NamespaceDescriptor;importorg.apache.hadoop.hbase.client.Admin;importorg.apache.hadoop.hbase.client.Connection;importjava.io.IOException;publicclassHBaseDDL{//声明一个静态属性,获取连接publicstaticConnection connection =HbaseConnection.connection;/**
* 创建命名空间,命名空间名称
* @param namespase
* admin的连接是轻量级的,不是线程安全的,不推荐池化或者缓存连接
*/publicstaticvoidcreateNamespace(String namespace)throwsIOException{//1.获取adminAdmin admin = connection.getAdmin();//2.调用方法创建命名空间,给一个描述//代码相对shell更加底层,shell实现的功能,代码一定能实现//2.1创建命名空间描述建造者=》设计师NamespaceDescriptor.Builder builder =NamespaceDescriptor.create(namespace);//2.2给命名空间添加需求
builder.addConfiguration("user","fang");//2.3使用builder构造出对饮的创建一个命名空间描述//创建命名空间出现的问题,都属于try{
admin.createNamespace(builder.build());}catch(IOException e){System.out.println("命名空间已经存在");
e.printStackTrace();}//3.关闭admin
admin.close();}publicstaticvoidmain(String[] args)throwsIOException{//测试创建命名空间createNamespace("fang");System.out.println("执行完成");//关闭Hbase连接HbaseConnection.closeConnection();}}packagecom.fang.hbase;importorg.apache.hadoop.hbase.NamespaceDescriptor;importorg.apache.hadoop.hbase.client.Admin;importorg.apache.hadoop.hbase.client.Connection;importjava.io.IOException;publicclassHBaseDDL{//声明一个静态属性,获取连接publicstaticConnection connection =HbaseConnection.connection;/**
* 创建命名空间,命名空间名称
* @param namespase
* admin的连接是轻量级的,不是线程安全的,不推荐池化或者缓存连接
*/publicstaticvoidcreateNamespace(String namespace)throwsIOException{//1.获取adminAdmin admin = connection.getAdmin();//2.调用方法创建命名空间,给一个描述//代码相对shell更加底层,shell实现的功能,代码一定能实现//2.1创建命名空间描述建造者=》设计师NamespaceDescriptor.Builder builder =NamespaceDescriptor.create(namespace);//2.2给命名空间添加需求
builder.addConfiguration("user","fang");//2.3使用builder构造出对饮的创建一个命名空间描述//创建命名空间出现的问题,都属于try{
admin.createNamespace(builder.build());}catch(IOException e){System.out.println("命名空间已经存在");
e.printStackTrace();}//3.关闭admin
admin.close();}publicstaticvoidmain(String[] args)throwsIOException{//测试创建命名空间createNamespace("fang");System.out.println("执行完成");//关闭Hbase连接HbaseConnection.closeConnection();}}
2.3判断表格是否存在
自行将本代码块,放入上方代码中进行测试即可
/**
* 创建表格是否存在
* @param namespace
* @return
* @throws IOException
* trur表示存在 false表示不存在
*/
public static boolean isTableExists(String namespace,String tableName) throws IOException {
//1.获取admin
Admin admin = connection.getAdmin();
//2.使用方法判断表格是否存在
boolean b = false;
try {
b = admin.tableExists(TableName.valueOf(namespace,tableName));
} catch (IOException e) {
e.printStackTrace();
}
admin.close();
//3.返回结果
return b;
}
执行结果:
2.5创建表格(使用HBase1.3.1版本和2.4版本有所区别)
/**
* @param tableName 表格名称
* @param families 列族名称,可以有多个
*/publicstaticvoidcreateTable(String tableName,String... families)throwsIOException{//1.获取adminAdmin admin = connection.getAdmin();//2.调用方法创建表格//2.1创建表格描述的建造者TableName tableName1 =TableName.valueOf(tableName);HTableDescriptor tableDescriptor=newHTableDescriptor(tableName);//表格描述器if(families==null||families.length==0){//如果没有填写列族,给一个info
families=newString[1];
families[0]="info";}for(String family : families){HColumnDescriptor columnDescriptor=newHColumnDescriptor(family);//列族描述器
tableDescriptor.addFamily(columnDescriptor);}try{
admin.createTable(tableDescriptor);}catch(IOException e){System.out.println("表格已存在");
e.printStackTrace();}//3.关闭admin
admin.close();}
2.6插入数据
packagecom.fang.hbase;importorg.apache.hadoop.hbase.HBaseConfiguration;importorg.apache.hadoop.hbase.TableName;importorg.apache.hadoop.hbase.client.Connection;importorg.apache.hadoop.hbase.client.Put;importorg.apache.hadoop.hbase.client.Table;importorg.apache.hadoop.hbase.util.Bytes;importjava.io.IOException;publicclassHBaseDML{publicstaticConnection connection=HbaseConnection.connection;//声明一个静态属性/**
* @param tableName 表名
* @param rowKey 主键
* @param family 列族名
* @param columnName 列名
* @param value 值
*/publicstaticvoidputCell(String tableName,String rowKey,String family,String columnName,String value)throwsIOException{//1.获取tableTable table = connection.getTable(TableName.valueOf(tableName));//2.调用相关方法添加数据Put put =newPut(Bytes.toBytes(rowKey));//3.给put对象添加属性
put.addColumn(Bytes.toBytes(family),Bytes.toBytes(columnName),Bytes.toBytes(value));//4.将对象写入方法
table.put(put);//5.关闭tabletry{
table.close();}catch(IOException e){System.out.println("表格是否存在");
e.printStackTrace();}}publicstaticvoidmain(String[] args)throwsIOException{//测试添加数据putCell("shuju:huahua","1000","age","agga","43");System.out.println("其他代码");//关闭连接HbaseConnection.closeConnection();}}
测试成功!
版权归原作者 程序员小憨 所有, 如有侵权,请联系我们删除。