0


大数据组件之HBase

文章目录

前言

HBase作为一个列式存储的数据存储框架,其广泛应用于OLAP。前面介绍了大数据组件之HIve,其访问量很高,因此本文主要介绍HBase的shell命令和java操作,希望对于学习大数据或者从事大数据的你有些帮助。

一、HBase

HBase是一个分布式的面向列的开源数据库,该技术来源于 Fay Chang 所撰写的Google论文“Bigtable:一个结构化数据的分布式存储系统”。就像Bigtable利用了Google文件系统(File System)所提供的分布式数据存储一样,HBase在Hadoop之上提供了类似于Bigtable的能力。HBase是Apache的Hadoop项目的子项目。HBase不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库。另一个不同的是HBase基于列的而不是基于行的模式

HBase只有新增操作,通过操作类型和时间戳建立版本管理,按照时间的先后顺序0,1,2,…

可以通过切换版本追踪历史数据

可以设置最大的保留实例记录数

  • 基于列式存储模型,对于数据实现了高度压缩,节省存储成本
  • 采用 LSM 机制而不是B(+)树,这使得HBase非常适合海量数据实时写入的场景
  • 高可靠,一个数据会包含多个副本(默认是3副本),这得益于HDFS的复制能力,由RegionServer提供自动故障转移的功能
  • 高扩展,支持分片扩展能力(基于Region),可实现自动、数据均衡
  • 强一致性读写,数据的读写都针对主Region上进行,属于CP型的系统
  • 易操作,HBase提供了Java API、RestAPI/Thrift API等接口
  • 查询优化,采用Block Cache 和 布隆过滤器来支持海量数据的快速查找

1、Region

Region就是一段数据的集合。HBase中的表一般拥有一个到多个Region。Region具有以下特性:

1. Region不能跨服务器,一个RegionServer上有一个或者多个 Region。

2. 数据量小的时候,一个Region足以存储所有数据;但是,当数据 量大的时候,HBase会拆分Region。
3. 当HBase在进行负载均衡的时候,也有可能会从一台 RegionServer上把Region移动到另一台RegionServer上。
4. Region是基于HDFS的,它的所有数据存取操作都是调用了HDFS的 客户端接口来实现的。

2、RegionServer

RegionServer就是存放Region的容器,直观上说就是服务器上的一 个服务。当客户端从ZooKeeper获取RegionServer的地址后,它会直接从 RegionServer获取数据。

3、Master

Master只负责各种协调工作,比如建表、删表、 移动Region、合并等操作。

4、Zookeeper

Zookeeper 对于 HBase的作用是至关重要的。

  1. Zookeeper 提供了 HBase Master 的高可用实现,并保证同一时刻有且仅有一个主 Master 可用。
  2. Zookeeper 保存了 Region 和 Region Server 的关联信息(提供寻址入口),并保存了集群的元数据(Schema/Table)。
  3. Zookeeper 实时监控Region server的上线和下线信息,并实时通知Master。

二、HBases的Standalone安装

1、解压配置环境变量

1.下载

HBase的下载地址

#利用wget进行HBase安装包下载wget https://hbase.apache.org/downloads.html

2.解压

#tar解压tar -zxvf hbase-2.1.4-bin.tar.gz -C /opt/software

3.配置环境变量

#编辑环境变量
vim /etc/profile.d/my.sh
#-------------------------------------export HBASE_HOME=/opt/software-2.1.4
export PATH=$HBASE_HOME/bin:$PATH#-------------------------------------# 生效环境变量source /etc/profile

2、修改配置文件信息

1.hbase-env.sh

#打开文件
vim /opt/software-2.1.4/conf/hbase-env.sh
#-----------------------------------------export JAVA_HOME=/opt/software/jdk1.8.0_201
#-----------------------------------------

2.hbase-site.xml

#打开编辑文件,新增以下内容
vim /opt/software-2.1.4/conf/hbase-site.xml

新增以下内容:

<configuration><property><name>hbase.rootdir</name><value>file:///home/hbase/rootdir</value></property><property><name>hbase.zookeeper.property.dataDir</name><value>/home/zookeeper/dataDir</value></property><property><name>hbase.unsafe.stream.capability.enforce</name><value>false</value></property></configuration>

配置信息介绍:

  1. hbase.rootdir: 配置 hbase 数据的存储路径;
  2. hbase.zookeeper.property.dataDir: 配置 zookeeper 数据的存储路径;
  3. hbase.unsafe.stream.capability.enforce: 使用本地文件系统存储,不使用 HDFS 的情况下需要禁用此配置,设置为 false。

3.启动HBase

由于已经将 HBase 的 bin 目录配置到环境变量,直接使用以下命令启动:

#启动HBase
start-hbase.sh

4.验证启动是否成功

验证方式一 :使用

jps

命令查看 HMaster 进程是否启动。

[root@hadoop001 hbase-2.1.4]# jps
16336 Jps
15500 HMaster

验证方式二 :访问 HBaseWeb UI 页面,默认端口为

16010

三、HBase完全分布式搭建

#默认无,必须手动创建
vim conf/backup-masters 
#---------#backup状态
master02
#--------
start-hbase.sh HMaster

溢写64MB

#DDL
list
list_namespace
create_namespace 'kb16nb'
list_namespace_tables 'kb16nb'#
create 'kb16nb:student','base','score'
describe 'kb16nb:student'#----------------------------------------------------------------------------------------
Table kb16nb:student is ENABLED                                                         
kb16nb:student                                                                          
COLUMN FAMILIES DESCRIPTION                                                             
{NAME =>'base', BLOOMFILTER =>'ROW', IN_MEMORY =>'false', VERSIONS =>'1', KEEP_DELET
ED_CELLS =>'FALSE', DATA_BLOCK_ENCODING =>'NONE', COMPRESSION =>'NONE', TTL =>'FOREV
ER', MIN_VERSIONS =>'0', BLOCKCACHE =>'true', BLOCKSIZE =>'65536', REPLICATION_SCOPE 
=>'0'}{NAME =>'score', BLOOMFILTER =>'ROW', IN_MEMORY =>'false', VERSIONS =>'1', KEEP_DELE
TED_CELLS =>'FALSE', DATA_BLOCK_ENCODING =>'NONE', COMPRESSION =>'NONE', TTL =>'FORE
VER', MIN_VERSIONS =>'0', BLOCKCACHE =>'true', BLOCKSIZE =>'65536', REPLICATION_SCOPE
 =>'0'}#----------------------------------------------------------------------------------------#DML
is_enabled 'kb16nb:student'#查看表是否可用
is_disabled 'kb16nb:student'#查看表示是否禁用
drop 'kb16nb:student'#删除表,删除前需要禁用enable'kb16nb:student'#启用表
disable 'kb16nb:student'#禁用表
truncate 'kb16nb:student'#删除数据
delete 'kb16nb:student','rowkey','columnfamily:colname'#删除某行某列(最新的版本)
deleteall 'kb16nb:student','rowkey'#删除某行(删除所有版本)
put 'kb16nb:student','1','base:name','zhangsan'#插入数据
scan 'kb16nb:student'#查看全表#----------------------------------------------------------------------------------------
hbase(main):014:0> scan 'kb16nb:student'
ROW                     COLUMN+CELL                                                     
 1                      column=base:name, timestamp=2022-01-28T10:23:06.333, value=zhang
                        san
#----------------------------------------------------------------------------------------
get 'kb16nb:student','2','base:name'
scan 'kb16nb:student',{COLUMN=>'base'}#查询列簇
scan 'kb16nb:student',{COLUMN=>'base:name'}#查询指定列
scan 'kb16nb:student',{COLUMN=>'base:name',LIMIT=>2}
scan 'kb16nb:student',{COLUMN=>'base:name',LIMIT=>2,STARTKEY=>'2'}#开始下标(包含)
scan 'kb16nb:student',{COLUMN=>'base:name',LIMIT=>2,STARTKEY=>'2',STARTROW=>'2'}#Row下标不包含#BLOCKCACHE的页面置换算法是最近最少使用LRU
create 'kb16nb:'#shell执行HBase命令echo"shell指令"|hbase shell -n
echo"list_namespace_tables 'kb16nb'"|hbase shell -n
#布隆过滤器出现误码后怎么处理#预分区
create_namespace 'kb16'
create 'kb16:pre_split_n1','cf',SPLITS=>['10','20','30']
hbase org.apache.hadoop.hbase.util.RegionSplitter kb16:pre_split_hsp1 HexStringSplit -c 3 -f base,scores
create 'kb16:pre_split_pdp','base',{NUMREGIONS=>4,SPLITALGO=>'DecimalStringSplit'}

四、HBase常见shell指令

HBase为什么这么快

1、基本指令

1.打开HBase shell

#进入HBase的命令
hbase shell

2. 获取帮助

# 获取帮助help# 获取命令的详细信息help'status'

3. 查看服务器状态

#查看服务器状态
status

4.查看版本信息

#查看HBase版本信息
version

5.创建命名空间

#创建命名空间
create_namespace '命名空间'
create_namespace 'ns1'

6.描述命名空间

#描述命名空间
describe_namespace '命名空间'
describe_namespace 'ns1'

7.删除namespace

#删除namespace
drop_namespace 'ns1'

2、表操作

1. 查看所有表

#查看HBase的所有表
list

2.创建表

命令格式: create ‘表名称’, ‘列族名称 1’,‘列族名称 2’,‘列名称 N’

# 创建一张名为Student的表,包含基本信息(baseInfo)、学校信息(schoolInfo)两个列族
create 'ns1:t1',{NAME =>'f1',VERSION => 5},{NAME =>'f2'}
create 'Student','baseInfo','schoolInfo'

3.查看表的基本信息

命令格式:desc ‘表名’

#查看表的基本信息
describe 'Student'

4.表的启用/禁用

enable 和 disable 可以启用/禁用这个表,is_enabled 和 is_disabled 来检查表是否被禁用

# 禁用表
disable 'Student'# 检查表是否被禁用
is_disabled 'Student'# 启用表enable'Student'# 检查表是否被启用
is_enabled 'Student'

5.检查表是否存在

指令格式: exits ‘表名’

#检查表是否存在
exists 'Student'

6.删除表

删除表前需要先禁用表

# 删除表前需要先禁用表
disable 'Student'# 删除表
drop 'Student'

3、增删改

1.添加列族

命令格式: alter ‘表名’, ‘列族名’

alter 'Student', 'teacherInfo'

2.删除列族

命令格式:alter ‘表名’, {NAME => ‘列族名’, METHOD => ‘delete’}

alter 'Student', {NAME =>'teacherInfo', METHOD =>'delete'}

3.更改列族存储版本的限制

默认情况下,列族只存储一个版本的数据,如果需要存储多个版本的数据,则需要修改列族的属性。修改后可通过

desc

命令查看。

alter 'Student',{NAME=>'baseInfo',VERSIONS=>3}

4.插入数据

命令格式:put ‘表名’, ‘行键’,‘列族:列’,‘值’

注意:如果新增数据的行键值、列族名、列名与原有数据完全相同,则相当于更新操作

put 'Student', 'rowkey1','baseInfo:name','tom'
put 'Student', 'rowkey1','baseInfo:birthday','1990-01-09'
put 'Student', 'rowkey1','baseInfo:age','29'
put 'Student', 'rowkey1','schoolInfo:name','Havard'
put 'Student', 'rowkey1','schoolInfo:localtion','Boston'

put 'Student', 'rowkey2','baseInfo:name','jack'
put 'Student', 'rowkey2','baseInfo:birthday','1998-08-22'
put 'Student', 'rowkey2','baseInfo:age','21'
put 'Student', 'rowkey2','schoolInfo:name','yale'
put 'Student', 'rowkey2','schoolInfo:localtion','New Haven'

put 'Student', 'rowkey3','baseInfo:name','maike'
put 'Student', 'rowkey3','baseInfo:birthday','1995-01-22'
put 'Student', 'rowkey3','baseInfo:age','24'
put 'Student', 'rowkey3','schoolInfo:name','yale'
put 'Student', 'rowkey3','schoolInfo:localtion','New Haven'

put 'Student', 'wrowkey4','baseInfo:name','maike-jack'

5.获取指定行、指定行中的列族、列的信息

# 获取指定行中所有列的数据信息
get 'Student','rowkey3'# 获取指定行中指定列族下所有列的数据信息
get 'Student','rowkey3','baseInfo'# 获取指定行中指定列的数据信息
get 'Student','rowkey3','baseInfo:name'

6.删除指定行、指定行中的列

# 删除指定行
delete 'Student','rowkey3'# 删除指定行中指定列的数据
delete 'Student','rowkey3','baseInfo:name'

4、查询

hbase 中访问数据有两种基本的方式:

  • 按指定 rowkey 获取数据:get 方法;
  • 按指定条件获取数据:scan 方法。
scan

可以设置 begin 和 end 参数来访问一个范围内所有的数据。get 本质上就是 begin 和 end 相等的一种特殊的 scan。

1.Get查询

# 获取指定行中所有列的数据信息
get 'Student','rowkey3'# 获取指定行中指定列族下所有列的数据信息
get 'Student','rowkey3','baseInfo'# 获取指定行中指定列的数据信息
get 'Student','rowkey3','baseInfo:name'

2.查询整表数据

指令格式: scan ‘表名’

#查询整表数据
scan 'Student'

3.查询指定列簇的数据

#查看指定列簇数据
scan 'Student', {COLUMN=>'baseInfo'}

4.条件查询

# 查询指定列的数据
scan 'Student', {COLUMNS=>'baseInfo:birthday'}

除了列

(COLUMNS)

修饰词外,HBase 还支持

Limit

(限制查询结果行数),

STARTROW

ROWKEY

起始行,会先根据这个

key

定位到

region

,再向后扫描)、

STOPROW

(结束行)、

TIMERANGE

(限定时间戳范围)、

VERSIONS

(版本数)、和

FILTER

(按条件过滤行)等。

如下代表从

rowkey2

这个

rowkey

开始,查找下两个行的最新 3 个版本的 name 列的数据:

scan 'Student', {COLUMNS=>'baseInfo:name',STARTROW =>'rowkey2',STOPROW =>'wrowkey4',LIMIT=>2, VERSIONS=>3}

5. 条件过滤

Filter 可以设定一系列条件来进行过滤。如我们要查询值等于 24 的所有数据:

scan 'Student', FILTER=>"ValueFilter(=,'binary:24')"

值包含 yale 的所有数据:

scan 'Student', FILTER=>"ValueFilter(=,'substring:yale')"

列名中的前缀为 birth 的:

scan 'Student', FILTER=>"ColumnPrefixFilter('birth')"

FILTER 中支持多个过滤条件通过括号、AND 和 OR 进行组合:

# 列名中的前缀为birth且列值中包含1998的数据
scan 'Student', FILTER=>"ColumnPrefixFilter('birth') AND ValueFilter ValueFilter(=,'substring:1998')"
PrefixFilter

用于对 Rowkey 的前缀进行判断:

scan 'Student', FILTER=>"PrefixFilter('wr')"

五、Java API

1、pom.xml

<!--依赖导入--><dependency><groupId>org.apache.hbase</groupId><artifactId>hbase-client</artifactId><version>2.0.0</version></dependency>

2、HBaseClient

import org.apache.hadoop.hbase.HBaseConfiguration;import org.apache.hadoop.hbase.client.Connection;import org.apache.hadoop.hbase.client.ConnectionFactory;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.IOException;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;publicclassHbaseClient{// config zookeeperstaticprivate org.apache.hadoop.conf.Configuration configuration = null;staticprivate Connection connection = null;privatestatic Logger logger = LoggerFactory.getLogger(HbaseClient.class);staticprivate Lock lock =newReentrantLock();static Connection getConnectionInstance(){if(null == connection){
            lock.lock();try{if(null == connection){
                    configuration = HBaseConfiguration.create();
                    configuration.set("hbase.zookeeper.quorum","zk1:2182,zk2:2182,zk3:2182");
                    configuration.set("hbase.client.keyvalue.maxsize","100000000");
                    connection = ConnectionFactory.createConnection(configuration);}}catch(IOException e){
                logger.error("create hbase error ", e);}finally{
                lock.unlock();}}return connection;}}

3、创建表

/**
* 创建表
*
* @param tableName
*/publicstaticvoidcreateTable(String tableStr, String[] familyNames){
    System.out.println("start create table ......");try{
        Admin admin = connection.getAdmin();
        TableName tableName = TableName.valueOf(tableStr);if(admin.tableExists(tableName)){// 如果存在要创建的表,那么先删除,再创建
        admin.disableTable(tableName);
        admin.deleteTable(tableName);
        System.out.println(tableName +" is exist,detele....");}
        HTableDescriptor tableDescriptor =newHTableDescriptor(tableName);// 添加表列信息if(familyNames != null && familyNames.length >0){for(String familyName : familyNames){
                tableDescriptor.addFamily(newHColumnDescriptor(familyName));}}
          admin.createTable(tableDescriptor);}catch(MasterNotRunningException e){
        e.printStackTrace();}catch(ZooKeeperConnectionException e){
          e.printStackTrace();}catch(IOException e){
        e.printStackTrace();}
    System.out.println("end create table ......");}

4、添加行列数据数据

/**
* 添加行列数据数据
*
* @param tableName
* @throws Exception
*/publicstaticvoidinsertData(String tableName, String rowId, String familyName,String qualifier, String value)throws Exception {
    System.out.println("start insert data ......");
    Table table = connection.getTable(TableName.valueOf(tableName));
    Put put =newPut(rowId.getBytes());// 一个PUT代表一行数据,再NEW一个PUT表示第二行数据,每行一个唯一的ROWKEY,此处rowkey为put构造方法中传入的值
    put.addColumn(familyName.getBytes(), qualifier.getBytes(), value.getBytes());// 本行数据的第一列try{
        table.put(put);}catch(IOException e){
        e.printStackTrace();}
    System.out.println("end insert data ......");}

5、添加行列数据数据

/**
* 添加行列数据数据
*
* @param tableName
* @throws Exception
*/publicstaticvoidbatchInsertData(String tableName, String rowId, List<String> familyNames,String qualifier, List<String> values)throws Exception {if(null == qualifier) qualifier ="tmp";
    Table table = connection.getTable(TableName.valueOf(tableName));
    Put put =newPut(rowId.getBytes());// 一个PUT代表一行数据,再NEW一个PUT表示第二行数据,每行一个唯一的ROWKEY,此处rowkey为put构造方法中传入的值for(int i =0; i < familyNames.size();++i){
        put.addColumn(familyNames.get(i).getBytes(),
            qualifier.getBytes(), values.get(i).getBytes());// 本行数据的第一列}try{
        table.put(put);}catch(IOException e){
        e.printStackTrace();}}

6、删除行

/**
* 删除行
*
* @param tablename
* @param rowkey
*/publicstaticvoiddeleteRow(String tablename, String rowkey){try{
        Table table = connection.getTable(TableName.valueOf(tablename));
        Delete d1 =newDelete(rowkey.getBytes());
        table.delete(d1);//d1.addColumn(family, qualifier);d1.addFamily(family);
        System.out.println("删除行成功!");}catch(IOException e){
        e.printStackTrace();}}

7、查询所有数据

/**
* 查询所有数据
*
* @param tableName
* @throws Exception
*/publicstaticvoidqueryAll(String tableName)throws Exception {
    Table table = connection.getTable(TableName.valueOf(tableName));try{
        ResultScanner rs = table.getScanner(newScan());for(Result r : rs){
            System.out.println("获得到rowkey:"+newString(r.getRow()));for(Cell keyValue : r.rawCells()){
            System.out.println("列:"+newString(CellUtil.cloneFamily(keyValue))+":"+newString(CellUtil.cloneQualifier(keyValue))+"====值:"+newString(CellUtil.cloneValue(keyValue)));}}
        rs.close();}catch(IOException e){
        e.printStackTrace();}}

8、根据rowId查询

/**
* 根据rowId查询
*
* @param tableName
* @throws Exception
*/publicstaticvoidqueryByRowId(String tableName, String rowId)throws Exception {
    Table table = connection.getTable(TableName.valueOf(tableName));try{
        Get scan =newGet(rowId.getBytes());// 根据rowkey查询
        Result r = table.get(scan);
        System.out.println("获得到rowkey:"+newString(r.getRow()));for(Cell keyValue : r.rawCells()){
        System.out.println("列:"+newString(CellUtil.cloneFamily(keyValue))+":"+newString(CellUtil.cloneQualifier(keyValue))+"====值:"+newString(CellUtil.cloneValue(keyValue)));}}catch(IOException e){
        e.printStackTrace();}}

9、根据列条件查询

/**
* 根据列条件查询
*
* @param tableName
*/publicstaticvoidqueryByCondition(String tableName, String familyName,String qualifier,String value){try{
        Table table = connection.getTable(TableName.valueOf(tableName));
        Filter filter =newSingleColumnValueFilter(Bytes.toBytes(familyName),
        Bytes.toBytes(qualifier), CompareOp.EQUAL, Bytes.toBytes(value));// 当列familyName的值为value时进行查询
        Scan s =newScan();
        s.setFilter(filter);
        ResultScanner rs = table.getScanner(s);for(Result r : rs){
            System.out.println("获得到rowkey:"+newString(r.getRow()));for(Cell keyValue : r.rawCells()){
                System.out.println("列:"+newString(CellUtil.cloneFamily(keyValue))+":"+newString(CellUtil.cloneQualifier(keyValue))+"====值:"+newString(CellUtil.cloneValue(keyValue)));}}
        rs.close();}catch(Exception e){
        e.printStackTrace();}}

10、多条件查询

/**
* 多条件查询
*
* @param tableName
*/publicstaticvoidqueryByConditions(String tableName, String[] familyNames, String[] qualifiers,String[] values){try{
        Table table = connection.getTable(TableName.valueOf(tableName));
        List<Filter> filters =newArrayList<Filter>();if(familyNames != null && familyNames.length >0){int i =0;for(String familyName : familyNames){
                Filter filter =newSingleColumnValueFilter(Bytes.toBytes(familyName),
Bytes.toBytes(qualifiers[i]), CompareOp.EQUAL,Bytes.toBytes(values[i]));
                filters.add(filter);
                i++;}}
        FilterList filterList =newFilterList(filters);
        Scan scan =newScan();
        scan.setFilter(filterList);
        ResultScanner rs = table.getScanner(scan);for(Result r : rs){
            System.out.println("获得到rowkey:"+newString(r.getRow()));for(Cell keyValue : r.rawCells()){
                System.out.println("列:"+newString(CellUtil.cloneFamily(keyValue))+":"+newString(CellUtil.cloneQualifier(keyValue))+"====值:"+newString(CellUtil.cloneValue(keyValue)));}}
                rs.close();}catch(Exception e){
        e.printStackTrace();}}

11、删除表

// 懒加载单例模式staticprivate Connection connection = HbaseClient.getConnectionInstance();/**
* 删除表
*
* @param tableName
*/publicstaticvoiddropTable(String tableStr){try{
        Admin admin = connection.getAdmin();
        TableName tableName = TableName.valueOf(tableStr);
        admin.disableTable(tableName);
        admin.deleteTable(tableName);
        admin.close();}catch(MasterNotRunningException e){
        e.printStackTrace();}catch(ZooKeeperConnectionException e){
        e.printStackTrace();}catch(IOException e){
        e.printStackTrace();}}

本文转载自: https://blog.csdn.net/m0_43405302/article/details/123629207
版权归原作者 绝域时空 所有, 如有侵权,请联系我们删除。

“大数据组件之HBase”的评论:

还没有评论