Hadoop-HBase

HBase 2.2.5

在这里插入图片描述
在这里插入图片描述

1. HBase介绍

BigTale:
http://blog.csdn.net/accesine960/archive/2006/02/09/595628.aspx

1.1. HBase简介

Hadoop Database,是一个高可靠性、高性能、面向列、可伸缩、实时读写的分布式数据库。利用Hadoop HDFS作为其文件存储系统,利用Zookeeper作为其分布式协同服务主要用来存储非结构化和半结构化的松散数据(列存 NoSQL 数据库)
在这里插入图片描述

1.2. HBase优点

  • 容量大:
    Hbase单表可以有百亿行、百万列,数据矩阵横向和纵向两个维度所支持的数据量级都非常具有弹性
  • 面向列:
    面向列的存储和权限控制,并支持独立检索,可以动态增加列,即,可单独对列进行各方面的操作列式存储,其数据在表中是按照某列存储的,这样在查询只需要少数几个字段的时候,能大大减少读取的数量
  • 多版本:
    Hbase的每一个列的数据存储有多个Version,比如住址列,可能有多个变更,所以该列可以有多个version
  • 稀疏性:
    为空的列并不占用存储空间,表可以设计的非常稀疏。不必像关系型数据库那样需要预先知道所有列名然后再进行null填充
  • 拓展性:
    底层依赖HDFS,当磁盘空间不足的时候,只需要动态增加datanode节点服务(机器)就可以了
  • 高可靠性:
    WAL机制,保证数据写入的时候不会因为集群异常而导致写入数据丢失Replication机制,保证了在集群出现严重的问题时候,数据不会发生丢失或者损坏Hbase底层使用HDFS,本身也有备份。
  • 高性能:
    底层的LSM数据结构和RowKey有序排列等架构上的独特设计,使得Hbase写入性能非常高。Region切分、主键索引、缓存机制使得Hbase在海量数据下具备一定的随机读取性能,该性能针对Rowkey的查询能够到达毫秒级别,LSM树,树形结构,最末端的子节点是以内存的方式进行存储的,内存中的小树会flush到磁盘中(当子节点达到一定阈值以后,会放到磁盘中,且存入的过程会进行实时merge成一个主节点,然后磁盘中的树定期会做merge操作,合并成一棵大树,以优化读性能。)
    LSM树的介绍:https://www.cnblogs.com/yanghuahui/p/3483754.html

下图显示了列簇在面向列的数据库:
在这里插入图片描述

1.3. HBase应用

Hbase是一种NoSQL数据库,这意味着它不像传统的RDBMS数据库那样支持SQL作为查询语言。Hbase是一种分布式存储的数据库,技术上来讲,它更像是分布式存储而不是分布式数据库,它缺少很多RDBMS系统的特性,比如列类型,辅助索引,触发器,和高级查询语言等待。那Hbase有什么特性呢?
如下:
什么时候用Hbase?Hbase不适合解决所有的问题:

  • 首先数据库量要足够多,如果有十亿及百亿行数据,那么Hbase是一个很好的选项,如果只有几百万行甚至不到的数据量,RDBMS是一个很好的选择。因为数据量小的话,真正能工作的机器量少,剩余的机器都处于空闲的状态
  • 其次,如果你不需要辅助索引,静态类型的列,事务等特性,一个已经用RDBMS的系统想要切换到Hbase,则需要重新设计系统。
  • 最后,保证硬件资源足够,每个HDFS集群在少于5个节点的时候,都不能表现的很好。因为HDFS默认的复制数量是3,再加上一个NameNode。
  • Hbase在单机环境也能运行,但是请在开发环境的时候使用。
    内部应用
  • 存储业务数据:车辆GPS信息,司机点位信息,用户操作信息,设备访问信息。。。
  • 存储日志数据:架构监控数据(登录日志,中间件访问日志,推送日志,短信邮件发送记录。。。),业务操作日志信息
  • 存储业务附件:UDFS系统存储图像,视频,文档等附件信息

不过在公司使用的时候,一般不使用原生的Hbase API,使用原生的API会导致访问不可监控,影响系统
稳定性,以致于版本升级的不可控。

Hbase和RDBMS

属性 Hbase RDBMS
数据类型 只有字符串 丰富的数据类型
数据操作 增删改查,不支持join 各种各样的函数与表连接
存储模式 基于列式存储 基于表结构和行式存储
数据保护 更新后仍然保留旧版本 替换
可伸缩性 轻易增加节点 需要中间层,牺牲性能

2. HBase数据模型

在这里插入图片描述

HBase 是一个稀疏的、分布式、持久、多维、排序的映射,它以行键(row key),列簇(columnFamily),列名(ColumnQualifier)和时间戳(timestamp)为索引。
在这里插入图片描述

2.1. NameSpace:

  • 命名空间是类似于关系数据库系统中的数据库的概念,他其实是表的逻辑分组。这种抽象为多租户相关功能奠定了基础。
  • 命名空间是可以管理维护的,可以创建,删除或更改命名空间。
  • HBase有两个特殊预定义的命名空间:
    • default - 没有明确指定名称空间的表将自动落入此名称空间
    • hbase - 系统命名空间,用于包含HBase内部表

2.2. Table:

  • Hbase的table由多个行组成
RowKey TimeStamp ColumnFamily1 ColumnFamily2 ColumnFamily3
111 t6 CF2:q1=val1 CF3:q3=val3
112 t3 CF1:q2=val3
t2 CF1:q8=val2

2.3. RowKey:

R- owKey 是用来检索记录的主键,是一行数据的唯一标识

  • RowKey行键 (RowKey)可以是任意字符串(最大长度是64KB,实际应用中长度一般为 10-100bytes),RowKey以字节数组保存。
  • 存储时,数据按照RowKey的字典序(byte order)排序存储。设计RowKey时,要充分排序存储这个特性,将经常一起读取的行存储放到一起。

2.4. Column Family:

  • 列簇在物理上包含了许多的列与列的值,每个列簇都有一些存储的属性可配置。
    • 例如是否使用缓存,压缩类型,存储版本数等。在表中,每一行都有相同的列簇,尽管有些列簇什么东西也没有存。
  • 将功能属性相近的列放在同一个列簇,而且同一个列簇中的列会存放在同一个Store中
  • 列簇一般需要在创建表的时候就进行声明,而且一般一个表中的列簇数不要超过3个
    • 这个和后期的优化相关
  • 列隶属于列簇,列簇隶属于表

2.5. Column Qualifier:

  • 列的限定词,理解为列的唯一标识。但是列标识是可以改变的,因此每一行可能有不同的列标识
  • 使用的时候必须 列簇:列
  • 列可以根据需求动态添加或者删除,同一个表中不同行的数据列都可以不同

2.6. Timestamp:

  • 通过rowkey和column family,column qualifier确定的一个存贮单元通过时间戳来索引。
    • 时间戳的类型是 64 位整型
    • 默认时间戳是精确到毫秒的当前系统时间。
    • 时间戳也可以由客户显式赋值,如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳。
  • 每个cell中,不同版本的数据按照时间倒序排序,即最新的数据排在最前面。
    • 查询数据的时候,如果不指定版本数,默认显示版本号最新(高)的数据
  • 为了避免数据存在过多版本中造成管理 (包括存贮和索引)负担,HBASE 提供了两种数据版本回收方式。
    • 一是保存数据的最后n个版本
    • 二是保存最近一段时间内的版本(比如最近七天)。

在这里插入图片描述

2.7. Cell:

  • Cell是由row,column family,column qualifier,version 组成的
  • cell中的数据是没有类型的,全部是字节码形式存贮。
    • 因为HDFS上的数据都是字节数组

3. HBase高可用集群搭建

前提:Hadoop集群正常运行 和ZooKeeper集群正常运行,Hive正常运行,时间同步

HMasterActive HMasterStandBy HRegionServer Zookeeper
node01 * * *
node02 * * *
node03 * *

在这里插入图片描述

3.1. 准备安装环境

[root@node01 ~]# tar -zxvf hbase-2.2.5-bin.tar.gz
[root@node01 ~]# mv hbase-2.2.5 /opt/
[root@node01 ~]# cd /opt/hbase-2.2.5/conf/

3.2. 修改集群环境

  • [root@node01 conf]# vim hbase-env.sh
export HBASE_LOG_DIR=${
   HBASE_HOME}/logs
export JAVA_HOME=/usr/java/jdk1.8.0_291-amd64
export HBASE_MANAGES_ZK=false
export HADOOP_HOME=/opt/hadoop-3.1.2/

3.3. 修改配置文件

  • [root@node01 conf]# vim hbase-site.xml
<!-- 31dd -->
<!--设置HBase表数据,也就是真正的HBase数据在hdfs上的存储根目录-->
<property>
<name>hbase.rootdir</name>
<value>hdfs://hdfs-bdp/hbase</value>
</property>
<!--是否为分布式模式部署,true表示分布式部署-->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!--zookeeper集群的URL配置,多个host中间用逗号-->
<property>
<name>hbase.zookeeper.quorum</name>
<value>node01:2181,node02:2181,node03:2181</value>
</property>
<!--HBase在zookeeper上数据的根目录znode节点-->
<property>
<name>zookeeper.znode.parent</name>
<value>/hbase</value>
</property>
<!-- 本地文件系统tmp目录,一般配置成local模式的设置一下,但是最好还是需要设置一下,因为很
多文件都会默认设置成它下面的-->
<property>
<name>hbase.tmp.dir</name>
<value>/var/bdp/hbase</value>
</property>
<!-- 使用本地文件系统设置为false,使用hdfs设置为true -->
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>
  • vim regionservers
node01
node02
node03

3.4. 备用Master节点

  • [root@node01 conf]# vim backup-masters
node02

3.5. 拷贝Hadoop配置文件

[root@node01 conf]# cp /opt/hadoop-3.1.2/etc/hadoop/core-site.xml /opt/hbase-2.2.5/conf/
[root@node01 conf]# cp /opt/hadoop-3.1.2/etc/hadoop/hdfs-site.xml /opt/hbase-2.2.5/conf/

3.6. 拷贝分发软件

[root@node02 ~]# scp -r root@node01:/opt/hbase-2.2.5 /opt/
[root@node03 ~]# scp -r root@node01:/opt/hbase-2.2.5 /opt/

3.7. 修改环境变量

[root@node01 conf]# vim /etc/profile

export HBASE_HOME=/opt/hbase-2.2.5
export PATH=$HBASE_HOME/bin:$PATH

拷贝到其他节点

[root@node01 conf]# scp /etc/profile root@node02:/etc/profile
[root@node01 conf]# scp /etc/profile root@node03:/etc/profile

让配置文件生效
【123】 source /etc/profile

3.8. 启动集群

【123】 zkServer.sh start

[root@node01 conf]# start-all.sh
[root@node01 conf]# start-hbase.sh

3.9. web界面

  • 可以看到服务器1启动和HMaster 和 HRegionServer进程,服务器2和服务器3启动和HRegionServer进程。
  • hbase集群安装和启动完成,此时可以通过Web页面查看Hbase集群情况: http://node01:16010

在这里插入图片描述

4. HBase访问方式

4.1. HBase shell

我们可以先用Hbase提供的命令行工具,位于hbase的/bin/目录下
进入退出

hbase shell
exit

查看帮助信息

help

查询服务器状态

status

查询hive版本

version
4.1.1. Shell实现DDL操作

1.创建一个表
语法:create
, {NAME => , VERSIONS => }
例如:创建表t1,有两个family name:f1,f2,且版本数均为2

hbase(main)> create 't1',{
   NAME => 'f1', VERSIONS => 2},{
   NAME => 'f2', VERSIONS
=> 2}

还有一种非标准创建的语法,创建表member,列簇是member_id,address,info,版本为1。如下:

hbase(main):011:0>create 'member','member_id','address','info'

2.获得表的描述
语法:describe

hbase(main):012:0>list
hbase(main):006:0>describe 'member'

3.删除一个列簇,alter,disable,enable
我们之前建了3个列簇,但是发现member_id这个列簇是多余的,因为他就是主键,所以我们要将其删除。

hbase(main):003:0>alter 'member',{
   NAME=>'member_id',METHOD=>'delete'}

将表enable

hbase(main):008:0> enable 'member'

4.列出所有的表

hbase(main):028:0>list

5.drop一个表

create 'temp_table','member_id','address','info'
hbase(main):029:0>disable 'temp_table'
hbase(main):030:0>drop 'temp_table'

6.查询表是否存在

hbase(main):021:0>exists 'member'

7.判断表是否enable

hbase(main):034:0>is_enabled 'member'

8.判断表是否disable

hbase(main):032:0>is_disabled 'member'

9.查看文件存储路径

hdfs dfs -ls /bdp/hbase/data/default/t1

10.truncate此命令将删除并重新创建一个表。

truncate 't1'

11.表的预分区

# create table with specific split points
hbase>create 'table1','f1',SPLITS => ['\x10\x00', '\x20\x00', '\x30\x00',
'\x40\x00']
# create table with four regions based on random bytes keys
hbase>create 'table2','f1', {
    NUMREGIONS => 8 , SPLITALGO => 'UniformSplit' }
# create table with five regions based on hex keys
hbase>create 'table3','f1', {
    NUMREGIONS => 10, SPLITALGO => 'HexStringSplit' }
4.1.2. Shell实现DML操作

插入几条记录

put'member','guojing','info:age','24'
put'member','guojing','info:birthday','1987-06-17'
put'member','guojing','info:company','alibaba'
put'member','guojing','address:contry','china'
put'member','guojing','address:province','zhejiang'
put'member','guojing','address:city','hangzhou'
put'member','yangkang','info:birthday','1987-4-17'
put'member','yangkang','info:favorite','movie'
put'member','yangkang','info:company','alibaba'
put'member','yangkang','address:contry','china'
put'member','yangkang','address:province','guangdong'
put'member','yangkang','address:city','jieyang'
put'member','yangkang','address:town','xianqiao'
注:现在表的数据都在内存中,并没有落地到磁盘。如果这时候想要落地到磁盘只能手动落地
命令:flush ‘tablename’
例如:flush ‘member’

更新一条记录 将scutshuxue的年龄改成99

hbase(main):004:0>put 'member','scutshuxue','info:age' ,'99'
hbase(main):005:0>get 'member','scutshuxue','info:age'

删除id为temp的值的‘info:age’字段

hbase(main):016:0>delete 'member','temp','info:age'

删除整行

hbase(main):001:0>deleteall 'member','xiaofeng'

查询表中有多少行:

hbase(main):019:0>count 'member'

给‘xiaofeng’这个id增加’info:age’字段,并使用counter实现递增

hbase(main):057:0>incr 'member','xiaofeng','info:age'
hbase(main):058:0>get 'member','xiaofeng','info:age'
hbase(main):059:0>incr 'member','xiaofeng','info:age'
hbase(main):060:0>get 'member','xiaofeng','info:age'

获取当前count的值

hbase(main):069:0>get_counter 'member','xiaofeng','info:age'

将整张表清空:

hbase(main):035:0>truncate 'member'

可以使用count命令计算表的行数量。

count 'member'
4.1.3. Shell实现DQL操作

获取一个id的所有数据

hbase(main):001:0>get 'member','linghuchong'

获取一个id,一个列簇的所有数据

hbase(main):002:0>get 'member','linghuchong','info'

获取一个id,一个列簇中一个列的所有数据

hbase(main):002:0>get 'member','linghuchong','info:age'

通过timestamp来获取两个版本的数据

hbase(main):010:0>get 'member','linghuchong',
{
   COLUMN=>'info:age',TIMESTAMP=>1321586238965}
hbase(main):011:0>get 'member','linghuchong',
{
   COLUMN=>'info:age',TIMESTAMP=>1321586571843}

全表扫描:

hbase(main):013:0>scan 'member'

注:全表扫描的时候一般都和过滤器一起使用

--扫描时指定列簇
scan 'member', {
   COLUMNS => 'info'}
--(3) 扫描时指定列簇,并限定显示最新的5个版本的内容
scan 'member', {
   COLUMNS => 'info', VERSIONS => 5}
--(4) 设置开启Raw模式,开启Raw模式会把那些已添加删除标记但是未实际删除的数据也显示出来
scan 'member', {
   COLUMNS => 'info', RAW => true}
--(5) 列的过滤
# 查询user表中列簇为info和data的信息
scan 'member', {
   COLUMNS => ['info', 'address']}
# 查询user表中列簇为info,列名为name、列簇为data,列名为pic的信息
scan 'member', {
   COLUMNS => ['info:name', 'address:pic']}
# 查询user表中列簇为info,列名为name的信息,并且版本最新的5个
scan 'member', {
   COLUMNS => 'info:name', VERSIONS => 5}
# 查询user表中列簇为info和data且列名含有a字符的信息
scan 'member', {
   COLUMNS => ['info', 'data'], FILTER => "
(QualifierFilter(=,'substring:a'))"}
# 查询user表中列簇为info,rk范围是[rk0001, rk0003)的数据
scan 'member', {
   COLUMNS => 'info', STARTROW => '00001', ENDROW => '00003'}
# 查询user表中row key以rk字符开头的
scan 'member',{
   FILTER=>"PrefixFilter('0')"}
# 查询user表中指定时间范围的数据
scan 'member', {
   TIMERANGE => [1392368783980, 1392380169184]}
4.1.4. Shell实现Region管理

1)移动region
语法:move ‘encodeRegionName’, ‘ServerName’
encodeRegionName指的regioName后面的编码,ServerName指的是master-status的RegionServers列表
示例:

hbase(main)>move '4343995a58be8e5bbc739af1e91cd72d','db41.xxx.xxx.org,60020,1390274516739'

2)开启/关闭region
语法:balance_switch true|false

hbase(main)> balance_switch

3)手动split
语法:split ‘regionName’, ‘splitKey’
删除之后当前Region并不会马上消失,需要等待HBase检查新Region的工作状态
4)手动触发major compaction
语法:压缩表中的所有区域:

hbase> major_compact 't1'

压缩整个区域:

hbase> major_compact 'r1'

在region中压缩单列簇:

hbase> major_compact 'r1', 'c1'

在表中压缩单列簇:

hbase> major_compact 't1', 'c1'

总结

  • 通用命令
    • status: 提供HBase的状态,例如,服务器的数量。
    • version: 提供正在使用HBase版本。
    • table_help: 表引用命令提供帮助。
    • whoami: 提供有关用户的信息。
  • 数据操纵语言
    • put: 把指定列在指定的行中单元格的值在一个特定的表。
    • get: 取行或单元格的内容。
    • delete: 删除表中的单元格值。
    • deleteall: 删除给定行的所有单元格。
    • scan: 扫描并返回表数据。
    • count: 计数并返回表中的行的数目。
    • truncate: 禁用,删除和重新创建一个指定的表。
  • 数据定义语言
    • create: 创建一个表。
    • list: 列出HBase的所有表。
    • disable: 禁用表。
      要删除表或改变其设置,首先需要使用 disable 命令关闭表。使用 enable 命令,可以重新启用它。

4.2. Java访问HBaseAPI

  • Hbase有多种不同的客户端,如REST客户端,Thift客户端,ORM框架Kundera等等。 Hbase也提供了Java的API来操作表与列簇等信息,它的shell就是对Java的API做了一层封装。
  • Hbase的Java API提供了很多高级的特性:
    • 元数据管理,列簇的数据压缩,region分隔
    • 创建,删除,更新,读取 rowkey
4.2.1. 添加依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<!-- Hadoop版本控制 -->
<hadoop.version>3.1.2</hadoop.version>
<!-- HBase版本控制 -->
<hbase.version>2.2.5</hbase.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>${
   hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>${
   hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>${
   hbase.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-auth</artifactId>
<version>${
   hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>${
   hbase.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
</dependencies>
4.2.2. 添加配置
  • 导出Hadoop和HBase的配置文件

在这里插入图片描述

4.2.3. Java实现DDL
package com.xxxx.jdbc;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.NamespaceDescriptor;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class HelloHBaseDDL {
   
//获取HBase管理员类
private Admin admin;
//获取数据库连接
private Connection connection;
/**
* 命名空间
*
* @throws IOException
*/
@Test
public void createNameSpace() throws IOException {
   
NamespaceDescriptor mkNameSpace =
NamespaceDescriptor.create("bdp").build();
this.admin.createNamespace(mkNameSpace);
System.out.println("HelloHBase.createNameSpace[表空间创建完成]");
}
/**
* 创建单列簇的表
*
* @throws IOException
*/
@Test
public 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

♪-Interpretation

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值