HBase的安装、命令操作和基础编程
JunLeon——go big or go home
目录
前言:
学习HBase这个组件,可能很多人都有这个这个疑惑:HDFS和MySQL等都可做数据的持久化存储,那为什么还要学习这个HBase呢?而HBase的最终数据还是存储在HDFS中,那为什么还要使用HBase呢?HBase和HDFS又有什么关系呢?
HBase作为Hadoop的分布式数据库,基于Google发行的三篇论文之一——《BigData》研发的Hadoop生态组件之一。那我们为啥要用HBase呢?HBase在HDFS之上提供了高并发的随机写和支持实时查询,这是HDFS不具备的。
HDFS是分布式文件存储系统,HBase是分布式数据库,两者其实没有什么可比性。可能很多人对MySQL比较熟悉,MySQL的数据持久化就是将数据落地磁盘存储。简单理解就是可以把HBase当做是MySQL,把HDFS当做是硬盘。HBase只是一个NoSQL数据库,把数据存在HDFS上。
一、HBase的概述
1.什么是HBase?
HBase是高可靠性、高性能、面向列、可伸缩的分布式存储系统,是基于HDFS的分布式数据库,也是一种非关系型数据库。分布式数据库HBase是Hadoop生态系统的组件之一。HBase的运行依赖于Hadoop HDFS文件系统提供数据的持久化,依赖于Zookeeper提供集群的的同步与协调。HBase使用Zookeeper服务来进行节点管理以及表数据的定位。
2.HBase的特点
(1)大:一个表可以有上亿行,上百万列。
(2)面向列:面向列表(簇)的存储和权限控制,列(簇)独立检索。
(3)稀疏:对于为空(NULL)的列,并不占用存储空间,因此,表可以设计的非常稀疏。
(4)无模式:每一行都有一个可以排序的主键和任意多的列,列可以根据需要动态增加,同一张表中不同的行可以有截然不同的列。
(5)数据多版本:每个单元中的数据可以有多个版本,默认情况下,版本号自动分配,版本号就是单元格插入时的时间戳。
(6)数据类型单一:HBase中的数据都是字符串,没有类型。
3.HBase组成部分及数据模型
(1)HBase架构的组件及其作用
HBase采用Master/slaves的主从服务器架构,由一个HMaster服务器和多个HRegionServer服务器组成。HBase采用Master/Slave架构,主要角色包括Master服务器(HMaster,管理节点)、Region服务器(HRegionServer,数据节点)、ZooKeeper服务器以及客户端。
1.HMaster HMaster
HMaster HMaster是主节点,它主要负责HRegionServer的管理以及元数据的更改,包括以下内容:新HRegionServer的注册、表的增删改查、HRegionServer的负载均衡,Region(表的分区,存储在Region服务器上)的分布调整、Region分裂以及分裂后的Region分配,HRegionServer失效后的Region迁移等。
HMaster采用主备模式部署,集群启动时,通过竞争获得主HMaster角色。主HMaster只能有一个,备HMaster进程在集群运行期间处于休眠状态,不干涉任何集群事务。当主用Master故障时,备用Master将取代主用Master对外提供服务。
2.HRegionServer
HRegionServer是HBase的从节点,它负责提供表数据读写等服务,是数据存储和计算单元。HRegionServer一般与HDFS集群的DataNode部署在一起,实现数据的存储功能。一台HRegionServer管理多个Region对象和一个HLog文件。
一个Region由一个或多个Store组成。每个Store存储该Region一个列族的数据。一个Store包含一个MemStore缓存以及若干StoreFile文件,MemStore缓存客户端向Region插入的数据,当HRegionServer中的MemStore大小达到配置的容量上限时,RegionServer会将MemStore中的数据刷新(Flush)到HDFS中。MemStore的数据刷新到HDFS后成为HFile,HFile定义了StoreFile在文件系统中的存储格式,它是当前HBase系统中StoreFile的具体实现。随着数据的插入,一个Store会产生多个StoreFile,当StoreFile的个数达到配置的最大值时,RegionServer会将多个StoreFile合并为一个大的StoreFile。
HLog日志是一种预写式日志(Write Ahead Log),用户更新数据时需要先写入HLog再写入MemStore,MemStore中的数据被刷新到StoreFile之后才会在HLog中清除对应的记录,这样的设计保证了当HRegionServer故障时,用户写入的数据不丢失,一台HRegionServer的所有Region共享同一个HLog。
3.ZooKeeper
ZooKeeper为HBase集群各进程提供分布式协作服务。各HRegionServer将自己的信息注册到ZooKeeper中,HMaster据此感知各个HRegionServer的健康状态。
HBase还通过ZooKeeper实现HMaster的高可用。ZooKeeper存储HBase的如下信息:HBase元数据、HMaster地址。当HMaster主节点出现故障时,HMaster备用节点会通过ZooKeeper获取主HMaster存储的整个HBase集群状态信息,接管HMaster主节点的工作。
4.Client
客户端通过HBase的元数据找到所需数据所在的HRegionServer进行访问(HBase的元数据存储在ZooKeeper中,因此客户端在做读取操作时不需要与HMaster进行通信,这样的设计减少了HMaster的负担),客户端会在缓存中维护访问过的Region位置信息,下次访问时就可以跳过向ZooKeeper寻址的过程。如果缓存中位置信息所指向的HRegionServer失效或Region已被迁移到其他服务器,客户端在查找不到该Region的情况下,会重新查询元数据以获取该Region的新地址。除了读取HRegionServer的信息外,客户端还可以与HMaster通信做表的修改。
(2)HBase的数据模型
HBase中,数据存储在由行和列组成的表中,HBase的表是稀疏的,多维映射的。HBase用键值对的方式存储数据。每个值都是未经解释的字符串,通过行键、列族、列限定符、时间戳等信息进行定位。
1.表(Table)
HBase采取表的形式存储数据,表由行和列组成。
2.行(Row)
HBase中的行由行键(RowKey)和若干列组成。行是通过行键按字典顺序进行排序的,因此行键的设计非常重要,好的行键设计可以将内容相关的行排列到相邻位置,方便查找和读取。以存储网页内容为例,将URL作为行键,如org.apache.www、org.apache.mail,可以将相邻子网页存储在相邻的位置。
3.列族(Column Family)
一个表在水平方向上由一个或多个列族组成。一个列族可以由任意多个列组成,列族在表创建时就需要预先设定好。
列族是Region的物理存储单元。同一个Region下面的多个列族,位于不同的Store下面。
列族信息是表级别的配置。同一个表的多个Region,都拥有相同的列族信息(例如,都有两个列族,且不同Region的同一个列族配置信息相同)。不是每一行下的列族或列中都存储了信息,因此说HBase的表是稀疏的。
4.列限定符(Column Qualifier)
列族中添加不同的列限定符可以对数据进行划分定位,列限定符以列族名作为前缀,用“:”连接后缀。例如以“content”为列族,那么列限定符则可以是“content:xxxx”。列限定符是列族下的一个标签,可以在写入数据时任意添加,支持动态扩展,无需预先定义列的数量和类型。
5.单元格(Cell)
一个单元格保存了一个值的多个版本,单元格通过行键、列族和列限定符进行定位,每个版本对应一个时间戳。
6.时间戳(TimeStamp)
HBase每个值都会带一个时间戳,时间戳标识了这个值的版本。默认情况下,在一个值发生变化(写入、更新、删除)时,所在的HRegionServer会自动为其创建一个时间戳。用户也可以在值发生变化时自定义时间戳。如果一个值有多个版本,在用户查询时默认返回最新的版本。HBase保存的版本数可以自定义,当超过设置的版本数时,新的版本会替换掉最早的版本。
(3)表和Region
一个HBase集群中维护着多张表,每张表可能包含非常多的行,在单台机器上无法全部存储,HBase会将一张数据表按行键的值范围横向划分为多个子表,实现分布式存储,如图5-1所示。这些子表,在HBase中被称作“Region”,Region是HBase分布式存储的基本单元。每一个Region都关联一个行键值的范围,即一个使用StartKey和EndKey描述的区间。事实上,每一个Region仅仅记录StartKey就可以了,因为它的EndKey就是下一个Region的StartKey。
每张表最开始值包含一个Region,随着表中数据的不断增大,Region中的行数超过一定阈值时就会分裂为两个新的Region。
Region分为元数据Region以及用户Region(User Region)两类。用户Region用于存储普通数据,元数据Region包括.META.表和-ROOT-表,用于存储Region的位置信息。.META.表记录了每一个用户Region的路由信息,用户可以通过.META.表查询到要访问的Region所在的HRegionServer,从而与其建立通信进行数据操作。.META.表的路由信息存储在-ROOT-表中,-ROOT-表不可被分割,只有一个Region。用户可以通过访问ZooKeeper服务器来获得-ROOT-表的位置。Region的划分如下图:
从HBase0.96.0开始,-ROOT-表的设置已被移除,.META.表改名为hbase:meta,hbase:meta的位置信息直接保存在ZooKeeper中。
4.HBase的读写流程
1.HBase的读流程
HBase的读流程如下: ·
客户端发起请求,与ZooKeeper服务器通信获取hbase:meta所在的HRegion Server,记为HRegionServer A;
访问HRegionServer A中的hbase:meta,hbase:meta中记载着各个User Region信息(行键范围,所在RegionServer等),通过行键查找hbase:meta获取所要读取的Region所在HRegionServer,记为HRegionServer B;
请求发送到HRegionServer B,HRegionServer B先查询MemStore,如果未查询到目标数据,则在HFile中查找; ·
查询到数据后返回到客户端。
2.HBase的写流程
HBase的写流程如下: ·
客户端发起请求,与ZooKeeper服务器通信获取hbase:meta所在HRegionServer,记为HRegionServer A;
客户端访问HRegionServer A中的hbase:meta,hbase:meta中记载着每个User Region信息(行键范围,所在RegionServer),通过行键查找hbase:meta获取本次写入操作所涉及的HRegionServer(HBase写入操作可能会涉及多个HRegionServer,在写入前HBase会对数据进行分组,分组共两步:首先将所有的记录按RegionServer划分,然后将同一RegionServer所有的记录按Region划分。每个RegionServer上的数据会一起发送,这样发送的数据中,都是已经按照Region分好组了);
客户端按RegionServer和Region将数据打包发送到对应的HRegionServer,RegionServer将数据写入对应的Region; ·客户端发送完待写数据后,会自动等待请求处理结果,如果客户端没有捕获到任何的异常,则认为所有数据写入成功。如果全部写入失败,或者部分写入失败,客户端能够获知详细的失败Key值列表。
如下图所示,HRegionServer在写入数据时,会先将数据写入HLog中,再将需要写入的数据暂时保存在对应Region的缓存MemStore中。这样一来可以减少数据直接写入磁盘带来的写入延迟,提高写入效率;另外数据先写入HLog可以避免HRegionServer故障时造成缓存数据的丢失。
达到一定预设条件时,HBase会将MemStore中的数据写入磁盘生成HFlie文件,并清空MemStore及HLog中的对应记录,这个过程称为刷盘(Flush)。
5.HBase的Compaction过程
当随着时间的增长,业务数据不断写入到HBase集群中,HFile的数目会越来越多,那么针对同样的查询,需要同时打开的文件也就可能越来越多,从而增加了查询延时,降低查询效率。
当HFile文件过多时,HBase就会启动一个Compation的操作。Compaction的主要目的,是为了减少同一个Region同一个列族下面的小文件数目,从而提升读取的性能。
如下图所示,Compaction分为Minor、Major两类。
Minor:小范围的Compaction。Minor Compation有最少和最大文件数目限制,默认最少选择3个HFile,最多10个,通常会选择一些连续时间范围的小文件进行合并。Minor Compaction选取文件时,遵循一定的算法。
Major:Major Compaction会将一个Region中的某个ColumnFamily下面所有的HFile合并成一个HFile。HBase默认一天进行一次Major Compaction。Major Compaction过程中,会清理被删除的数据。
二、基于Hadoop HA集群的HBase环境安装配置
1.下载HBase
官网下载:Index of /dist/hbase
版本:hbase-1.4.13-bin.tar.gz
hadoop版本对应的HBase版本可以参考下表,自行选择下载:
补充:我使用的是hadoop-2.7.3版本,故下载hbase-1.4.13的版本。
2.解压安装配置
说明:该HBase环境是在基于Zookeeper的Hadoop HA的基础上搭建的。
基于Zookeeper的Hadoop HA搭建请查看:(超详细)基于Zookeeper的Hadoop HA集群的搭建_JunLeon的博客-CSDN博客
(1)上传到虚拟机中指定的opt目录下
可通过XShell或者其他远程连接工具上传,上传过程略
(2)解压HBase
tar -zxvf /opt/hbase-1.4.13-bin.tar.gz -C /opt/
(3)配置环境及其相关属性
1.配置HBase的环境变量
vi /etc/profile
在该文件的最后添加HBase的安装路径
使配置文件生效:
source /etc/profile
2.配置${HBASE_HOME}/conf/hbase-env.sh文件
vi ${HBASE_HOME}/conf/hbase-env.sh
在27行,配置jdk路径:
注释46、47行,如果使用jdk1.8,则需要注释掉
128行,设置是否启动HBase自带的zookeeper
3.配置${HBASE_HOME}/conf/hbase-site.xml文件
<configuration>
<property>
<!-- hbase存放数据目录。mycluster为hdfs-site.xml中dfs.nameservices的值 -->
<name>hbase.rootdir</name>
<value>hdfs://mycluster/data/hbase_db</value>
</property>
<property>
<!-- 是否分布式部署HBase -->
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<property>
<name>dfs.support.append</name>
<value>true</value>
</property>
<property>
<name>hbase.zookeeper.quorum</name>
<value>BigData01,BigData02,BigData03</value>
</property>
<property>
<!-- Zookooper配置、日志等的存储位置 -->
<name>hbase.zookeeper.property.datadir</name>
<value>/opt/zookeeper-3.4.12</value>
</property>
<property>
<name>hbase.zookeeper.property.clientPort</name>
<value>2181</value>
</property>
</configuration>
4.配置${HBASE_HOME}/conf/regionservers文件
BigData01
BigData02
BigData03
3.启动HBase集群
在开启HBase集群之前应先将HDFS和YARN节点开启
start-all.sh # 在主节点上执行
再启动HBase集群节点
start-hbase.sh # 在主节点上执行
4.查看进程及HBase集群信息
jps # 查看开启的守护进程
Web端访问:(在主机Master上执行)
IP:16010 例如:192.168.182.10:16010
三、HBase的Shell命令
1.基本Shell命令
(1)启动shell命令(进入HBase命令环境)
[root@BigData01 ~]# hbase shell
如下图所示即进入HBase命令环境中:
(2)查看HBase状态
hbase(main):001:0> status
(3)查看版本
hbase(main):002:0> version
(4)获得帮助
hbase(main):003:0> help
(5)退出shell命令
hbase(main):004:0> exit
2.DDL操作命令
DDL即数据定义语言:
(1)创建表
create '表名','列族1','列族2'
# 例如: create ‘student’,’address’,’info’
(2)以列表的形式显示所有表
list
(3)查看表的结构
desc '表名'
# 例如: desc 'student'
(4)修改表的结构
disable '表名' # 设置表为不可用的状态
alter '表名',NAME=>'列族名' # 添加列族
alter '表名',NAME=>'cf3',METHOD=>'delete' # 删除列族
# 例如:
# disable 'student' —— 设置student为不可用状态
# alter 'student',NAME=>'cf3' —— 添加列族cf3
# alter 'student',NAME=>'cf3',METHOD=>'delete' —— 删除列族cf3
(5)查询表是否存在
exists '表名'
# 例如: exists 'student'
(6)判断表是否可用或者不可用
is_eabled '表名' # 判断表是否可用
is_disabled '表名' # 判断表是否不可用
(7)删除表
disable '表名' # 设置表为不可用的状态
drop '表名' # 删除指定表
3.DML操作命令
DML即数据操作语言:
首先, 假设student 表的列族为address { province、city}、info { height、weight、birthday、telephone}、'row key' 为姓名(也可根据需要设学号为row key)
(1)插入记录数据
格式:put '表名','row key','列族:列','列的值'
put 'student','zhangsan','address:province','guizhou'
put 'student','zhangsan','address:city','guiyang'
put 'student','zhangsan','info:height','180'
put 'student','zhangsan','info:birthday','2000-01-01'
put 'student','zhangsan','info:telephone','18888888888'
(2)获取一条数据
格式:get '表名','row key'
get 'student','zhangsan'
(3)获取一个ID(row key)的一个列族所有数据
格式:get '表名','row key','列族'
get 'student','zhangsan','info'
(4)更新一条记录
格式:get '表名','row key','列族:列'
get 'student','zhangsan','info:height'
(5)更新一条数据
格式:put '表名','row key','列族:列','列新的值'
put 'student','zhangsan','info:height','190'
(6)读出表数据
scan '表名'
scan 'student'
(7)查询表有多少行
count '表名'
count 'student'
(8)将表清空
truncate '表名'
truncate 'student'
(9)删除某ID(row key)的某列的值
格式:delete '表名','row key','列族:列'
delete 'student','zhangsan','info:height'
4.运行HBase Shell脚本
可以将操作命令写入文件中,当成HBase Shell脚本,再在Linux shell命令下执行该脚本。
比如:在Linux文件系统中创建一个脚本testHBaseData.sh,再在Linux Shell命令下执行:
vi testHBaseData.sh,在脚本文件中添加如下内容:
put 'student','lisi','address:province','guizhou'
put 'student','lisi','address:city','guiyang'
put 'student','lisi','info:height','185'
put 'student','lisi','info:birthday','1995-01-01'
put 'student','lisi','info:telephone','18899999999'
执行脚本文件:
hbase shell testHbaseData.sh
四、HBase基础编程
1.HBase API
(1)HBaseConfiguration类
该类在hbase-common-1.4.13.jar 里,包名为org.apach.hadoop.hbase,该类是客户端必须使用的。 它从hbase-default.xml和hbase-site.xml文件中获取配置信息,编程时使用如下语句进行初始化配置文件:
Configuration config = HBaseConfiguration.create();
(2)ConnectionFactory类和Connection接口
该类和接口在hbase-common-1.4.13.jar 里,包名为org.apach.hadoop.hbase.client,用来通过配置连接HBase 集群,即建立连接,提高连接接口。 编程时使用如下语句:
Connection connection = ConnectionFactory.createConnection(config)
(3)HBaseAdmin类和Admin接口
该类和接口在hbase-client-1.4.13.jar 里,包名为org.apach.hadoop.hbase.client,封装了对数据表结构的操作的接口,提供的方法有:创建表、删除表、列出表项、使表有效或者无效、添加或者删除表列族成员。
(4)HTableDescriptor类
该类在hbase-client-1.4.13.jar 里,包名为org.apach.hadoop.hbase。HTableDescriptor类封装了表的相关属性及操作接口。
(5)HColumnDescriptor类
该类在hbase-client-1.4.13.jar 里,包名为org.apach.hadoop.hbase。HColumnDescriptor类维护列族的相关信息。
(6)HTable类和Table接口
该类和接口在hbase-client-1.4.13.jar 里,包名为org.apach.hadoop.hbase.client,HTable类与HBase表直接通信,编程时不推荐使用HTable 类, 建议直接使用Table 接口, 使用如下语句获得Table 接口变量:
TableName tableName = TableName.valueOf("表名");
Table table = connection.getTable(tableName);
(7)Put类
该类在hbase-client-1.4.13.jar 里,包名为org.apach.hadoop.hbase.client,Put类用来对单行数据的添加操作。
(8)Get类
该类在hbase-client-1.4.13.jar 里,包名为org.apach.hadoop.hbase.client,Get类用于获取单行数据的相关信息。
(9)Scan类
该类在hbase-client-1.4.13.jar 里,包名为org.apach.hadoop.hbase.client,用于对表进行检索
(10)ResultScanner类
该类在hbase-client-1.4.13.jar 里,包名为org.apach.hadoop.hbase.client,该类提供了客户端获取值得接口。
(11)Result类
该类在hbase-client-1.4.13.jar 里,包名为org.apach.hadoop.hbase.client
(12)Delete类
该类在hbase-client-1.4.13.jar 里,包名为org.apach.hadoop.hbase.client
(13)TableName类
该类在hbase-common-1.4.13.jar 里,包名为org.apach.hadoop.hbase
(14)Cell类和CellUtil类
该类在hbase-common-1.4.13.jar 里,包名为org.apach.hadoop.hbase
2.HBase API编程代码演示
下面通过示例介绍使用Java 语言编程来操作HBase 中的表及数据,编程时必需的最少
jar 包为hadoop-common-2.x.x.jar、hbase-common-1.4.13.jar、hbase-client-1.4.13.jar
①打开Eclipse 编程工具,并建立Java工程MyHBaseUtil;
②新建lib 目录, 将Hbase 编程所需的jar 包拷贝到lib 目录下, 并加入buildpath;
③新建Class文件, 比如: HBASEUtil 类, 并在该类中编写针对HBase 操作的方法, 为
了测试在本类中添加入口主方法main(), 使用HBASEUtil 操作数据;
④将本工程导出生成jar 包文件(指定主类), 导出生成jar 包文件的方法:
选择Eclipse的菜单File→Export, 接着选Java 下的Jar File,点击“Next”, 勾选当前工程(比如:MyHBaseUtil), 此时默认选中当前工程下的src和lib 目录,接下来勾选“Export all output folders for checked projects”,导出所有输出文件夹, 在选项Options中勾选“Compress the contents of the of JAR file” “ add directory entries”, 在“ Select the export destination:”中输入JAR file 存储位置及文件名(比如: MyHBaseUtil.jar),最后点击“Finish”即可!⑤ 将导出的jar 文件上传到服务器BigData01中,再使用命令:
hadoop jar MyHBaseUtil.jar hadoop.hbase.HBaseUtil
运行程序(需要保证已经启动运行了HBase集群), 假设出现Zookeeper连接错误, 则将程序代码中注释下面几行:
//conf.set("hbase.zookeeper.quorum", "BigData01:2181, BigData02:2181, BigData03:2181");
//conf.set("hbase.zookeeper.quorum", "BigData01, BigData02, BigData03");
//conf.set("hbase.zookeeper.property.clientPort", "2181");
参考代码如下:
package hadoop.hbase;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.HColumnDescriptor;
import org.apache.hadoop.hbase.HTableDescriptor;
import org.apache.hadoop.hbase.KeyValue;
import org.apache.hadoop.hbase.MasterNotRunningException;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.ZooKeeperConnectionException;
import org.apache.hadoop.hbase.client.Admin;
import org.apache.hadoop.hbase.client.Append;
import org.apache.hadoop.hbase.client.Delete;
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.Increment;
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.filter.CompareFilter.CompareOp;
import org.apache.hadoop.hbase.filter.Filter;
import org.apache.hadoop.hbase.filter.SingleColumnValueFilter;
import org.apache.hadoop.hbase.util.Bytes;
public class HBaseUtil {
private static Configuration conf = null;
static {
conf = HBaseConfiguration.create();
//conf.set("hbase.zookeeper.quorum", "BigData01:2181, BigData02:2181, BigData03:2181");
//conf.set("hbase.zookeeper.quorum", "BigData01, BigData02, BigData03");
//conf.set("hbase.zookeeper.property.clientPort", "2181");
System.out.println("---Static Code Loaded. Configuration: " + conf.toString());
}
public static void main(String[] args) {
String tableName = "goods";
String[] familys = {"baseinfo", "otherinfo"};
try {
System.out.println("===Test Beginning: Creat table " + tableName);
HBaseUtil.deleteTable(tableName);
HBaseUtil.createTable(tableName, familys);
HBaseUtil.addData(tableName, "000001", familys[0], "name", "创维电视机");
HBaseUtil.getOneRow(tableName, "000001");
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 创建表
* @param tableName
* @param familys
* @throws MasterNotRunningException
* @throws ZooKeeperConnectionException
* @throws IOException
*/
public static void createTable(String tableName, String[] familys) throws MasterNotRunningException, ZooKeeperConnectionException, IOException{
HBaseAdmin admin = new HBaseAdmin(conf);
if(admin.tableExists(tableName)){
System.out.println("---CreateTable: table " + tableName + " already exists!");
}else{
HTableDescriptor tableDesc = new HTableDescriptor(tableName);
for(int i=0; i<familys.length; i++){
tableDesc.addFamily(new HColumnDescriptor(familys[i]));
}
admin.createTable(tableDesc);
System.out.println("---CreateTable: create table " + tableName + " success!");
}
}
// 删除表
public static void deleteTable(String tableName)
throws MasterNotRunningException, ZooKeeperConnectionException, IOException {
HBaseAdmin admin = new HBaseAdmin(conf);
if (admin.tableExists(tableName)) {
admin.disableTable(tableName);
admin.deleteTable(tableName);
System.out.println("---DeleteTable: delete table " + tableName + " success!");
} else {
System.out.println("---DeleteTable: " + tableName + " not exists!");
}
}
/**
* 插入数据
* @param tableName
* @param rowKey
* @param family
* @param qualifier
* @param value
*/
public static void addData(String tableName, String rowKey, String family, String qualifier, String value){
try {
HTable table = new HTable(conf, tableName);
Put put = new Put(Bytes.toBytes(rowKey));
put.add(Bytes.toBytes(family), Bytes.toBytes(qualifier), Bytes.toBytes(value));
table.put(put);
System.out.println("insert record success!");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 删除数据
* @param tableName
* @param rowKey
* @throws IOException
*/
public static void deleteRow(String tableName, String rowKey) throws IOException{
HTable table = new HTable(conf, tableName);
Delete deleteRow = new Delete(rowKey.getBytes());
table.delete(deleteRow);
System.out.println("delete row " + rowKey + " success!");
}
/**
* 删除一行中某列
* @param tableName
* @param rowKey
* @param familyName
* @param columnName
* @throws IOException
*/
public static void deleteColumn(String tableName, String rowKey, String familyName, String columnName) throws IOException{
HTable table = new HTable(conf, tableName);
Delete deleteColumn = new Delete(Bytes.toBytes(rowKey));
deleteColumn.deleteColumn(Bytes.toBytes(familyName), Bytes.toBytes(columnName));
table.delete(deleteColumn);
System.out.println("delete " + rowKey + ":" + familyName + ":" + columnName + " success!");
}
/**
* 添加数据
* @param tableName
* @param rowKey
* @param family
* @param qualifier
* @param value
* @throws IOException
*/
public static void appendData(String tableName, String rowKey, String family, String qualifier, String value) throws IOException {
HTable table = new HTable(conf, tableName);
Append append = new Append(Bytes.toBytes(rowKey));
append.add(Bytes.toBytes(family), Bytes.toBytes(qualifier), Bytes.toBytes(value));
table.append(append);
System.out.println("append data success!");
}
/**
* 增长数据
* @param tableName
* @param rowKey
* @param family
* @param qualifier
* @param amount
* @throws IOException
*/
public static void incrementData(String tableName, String rowKey, String family, String qualifier, long amount) throws IOException {
HTable table = new HTable(conf, tableName);
Increment increment = new Increment(Bytes.toBytes(rowKey));
increment.addColumn(Bytes.toBytes(family), Bytes.toBytes(qualifier), amount);
table.increment(increment);
System.out.println("increment data success!");
}
/**
* 读取数据
* @param tableName
* @param rowKey
* @throws IOException
*/
public static void getOneRow(String tableName, String rowKey) throws IOException{
HTable table = new HTable(conf, tableName);
Get get = new Get(rowKey.getBytes()); //设置rowKey
Result result = table.get(get);
//打印结果
for(KeyValue kv : result.raw()){
System.out.println("\trow: " + new String(kv.getRow()) + " ");
System.out.println("\tfamily: " + new String(kv.getFamily()) + " ");
System.out.println("\tqualifier: " + new String(kv.getQualifier()) + " ");
System.out.println("\ttimestamp: " + kv.getTimestamp() + " ");
System.out.println("\tvalue: " + new String(kv.getValue()) + " ");
}
}
/**
* 扫描数据
* @param tableName
* @param startRow
* @param stopRow
* @throws IOException
*/
public static void scanRows(String tableName, String startRow, String stopRow) throws IOException{
HTable table = new HTable(conf, tableName);
//在scan中指定startRow和stopRow
Scan scan = new Scan(startRow.getBytes(), stopRow.getBytes());
ResultScanner resultS = table.getScanner(scan);
//打印扫描结果
for(Result result : resultS){
for(KeyValue kv : result.raw()){
System.out.println("\trow: " + new String(kv.getRow()) + " ");
System.out.println("\tfamily: " + new String(kv.getFamily()) + " ");
System.out.println("\tqualifier: " + new String(kv.getQualifier()) + " ");
System.out.println("\ttimestamp: " + kv.getTimestamp() + " ");
System.out.println("\tvalue: " + new String(kv.getValue()) + " ");
}
}
}
public static void scanByFilter(String tableName, String family, String qualifier, String value) throws IOException{
HTable table = new HTable(conf, tableName);
Scan scan = new Scan();
scan.addColumn(Bytes.toBytes(family), Bytes.toBytes(qualifier));
Filter filter = new SingleColumnValueFilter(Bytes.toBytes(family), Bytes.toBytes(qualifier), CompareOp.EQUAL, Bytes.toBytes(value));
//在scan中设置filter
scan.setFilter(filter);
ResultScanner resultS = table.getScanner(scan);
//打印扫描结果
for(Result result : resultS){
System.out.println("row: " + new String(result.getRow()));
for(KeyValue kv : result.raw()){
System.out.println("\tfamily: " + new String(kv.getFamily()));
System.out.println("\tqualifier: " + new String(kv.getQualifier()));
System.out.println("\ttimestamp: " + kv.getTimestamp() + " ");
System.out.println("\tvalue: " + new String(kv.getValue()));
}
}
}
}
下一篇:数据仓库Hive的实战(超详细)
如果你喜欢、对你有帮助,点赞+收藏,跟着军哥学知识……