HBase数据库

2021/7/11 19:11:12

本文主要是介绍HBase数据库,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

文章目录

  • HBase
    • RDBMS(关系型数据库--MySQL|Oracle)问题
    • 简介
    • 什么情况下需要HBase以及为什么需要HBase
      • HBase特点
      • HBase和RDBMS对比
      • HBase表逻辑结构
      • 数据相关概念
      • HBase架构体系(物理结构)
      • 架构相关概念
        • HRagionServer
        • HMaster
        • Zookeeper
        • HRegion
        • Store
    • HBase单机版安装
      • 下载
      • 准备
      • 安装
    • HBase 命令
      • 1. 客户端进出命令
      • 2. namespace的管理命令(相当于数据库中DataBase)
      • 3. 表的操作(table)
      • 4.表数据操作(增删改查)
      • 5. 多版本问题
    • HBase API
      • API介绍
      • 环境准备
      • 常用API
        • 1. 创建namespace和表
        • 2. 表操作
        • 3. 添加
        • 4. 修改
        • 5. 删除
        • 6. 查询
    • HBase架构原理
      • HBase的Region分区的意义
      • 读写数据操作原理
        • 读数据
        • 写数据
    • HBase底层原理
      • Region split 分区
      • Region切片预分区
      • RowKey设计
      • MemStore Flush刷写
      • Store File Compact合并
      • HBase为何能做到海量数据的实时读写(简单说明秒级原因)
    • HBase之Mapreduce
      • Mapreduce思想
      • 环境搭建
      • 编码实现
        • 需求:
        • Mapper
        • Reducer
        • Job
    • HBase架构完整版

HBase

RDBMS(关系型数据库–MySQL|Oracle)问题

1.建表限定列数量,无法动态随意扩展。
2.MySQL单表数据库500w左右,数量小。(单表上限)
3.MySQL单表数据量过大,横向切分。(手动开发、复杂、稳定性低、效率低)
4.MySQL中单表的列过多,影响表的CRUD效率。(MySQL单表列最好不要超过30列)
5.MySQL单表的列过多,纵向切分。(手动开发、复杂、稳定性)
6.MySQL数据库允许空值,空值的空间是占用了的(海量数据面前造成空间浪费)
7.MySQL数据库中每个单元格,只能保存一个值(一个版本)

  总结:(mysql存在问题)
    a.海量数据存储问题
    b.实时检索问题    
Hbase  数据库(海量存储、实时检索)

简介

HBase的原型是Google的BigTable论文,受到了该论文思想的启发,目前作为Hadoop的子项目来开发维护,用于支持结构化的数据存储。

官方网站:http://hbase.apache.org

  • 2006年Google发表BigTable白皮书
  • 2006年开始开发HBase
  • 2008年北京成功开奥运会,程序员默默地将HBase弄成了Hadoop的子项目
  • 2010年HBase成为Apache顶级项目
  • 现在很多公司基于HBase开发出了定制版,比如阿里云HBase

总结:

HBase是构建在HDFS之上的分布式、面向列的存储系统,在需要实时读写、随机访问的超大规模数据集的时候,可以使用HBase。

在这里插入图片描述

什么情况下需要HBase以及为什么需要HBase

1.一个表数据量会超过500w,未来数据量会达到百亿条。
2.实时查询。(秒级  毫秒级读写)
原因:
# 海量数据存储
	一个表百亿行 百万列;(MySQL实战最大值500万行,30列)
# 实时查询
	1秒内查询得到结果。

HBase特点

# 1. 容量大
	HBase单表百亿行,百万列。
# 2. 面向列
	HBase存储是面向列,可以再数据存在以后动态增加新列和数据,并支持列数据的独立操作。
# 3. 多版本
	HBase每个数据,可以同时保存多个版本,按照时间去标记。
# 4. 稀疏性
	HBase每条数据的增删,并不是要操作所有的列,列可以动态增加,可以存在大量空白单元格,不会占用磁盘空间,这对于海量数据来讲,非常重要。
# 5. 扩展性
	底层使用HDFS,存储能力可以横向扩展。
# 6. 高可靠性
	底层使用HDFS,拥有replication的数据高可靠性。
# 7. 高性能
	表数据达到一定规模,"自动分区",具备主键索引,缓存机制,使得HBase海量数据查询能达到毫秒级。

HBase和RDBMS对比

HBase关系型数据库
数据库以**region**的形式存在数据库以Table的形式存在
使用**行键**(row key)支持主键PK
使用行表示一条数据一条数据用row代表
使用列 column、列族 column familycolumn代表列数据的含义
使用HBase shell命令操作数据使用SQL操作数据
数据文件可以基于HDFS,是分布式文件系统,
可以任意扩展,数据总量取决于服务器数量
数据总量依赖于单体服务器的配置
不支持事务、不支持ACID支持事务和ACID
不支持表连接支持join表连接

HBase表逻辑结构

在这里插入图片描述

数据相关概念

# namespace 命名空间
	管理多个表,相当于Database。
	hbase管理表的结构,在HDFS中对应一个文件夹。
# table 表
	存储管理数据,相当于table。
	hbase管理数据的结构,在HDFS中对应一个文件。
# column
	列,每个列对应一个单元格。
# column family 列族
	包含多个列,一组拥有相关业务含义列组成1个列族。
	表中数据的列,要属于某个列族,所有的列的访问格式(列族:列名)
# rowkey 主键
	类似于id,用来唯一标识一条数据。
	用来标记和检索数据的主键key。
# cell 单元格
	由`row key+column family+column+version` 唯一确定的一条数据。
	每个单元格可以保存值多个版本,按照时间排序,最新值在最前面。
# timestamp 时间戳
	时间戳,每个单元格可以保存多个值,每个值有对应的时间戳,每个cell中,不同版本的数据倒叙排序,排在最前面的是最新数据。

HBase架构体系(物理结构)

1.主从架构
Zookeeper
	1.保存HMaster管理表的元数据。
	2.HMaster解决单点故障(两个HMaster--Zookeeper自动处理)
	3.保存RegionServer从机状态信息。
HMaster(主)
    1. 管理RegionServer及其状态。
	2. 管理表的元数据。
	3.接受DDL语句,建表、删除表、alter。
	4.对HRegionServer做数据分布负载均衡。
HRegionServer(从)
	1. 定时向HMaster报告自身节点状态信息。
	2.保存表的数据部分。
	3.接受并执行DML语句。
		(添加-put、删除-delete、查询-get、scan)
		 没有修改,使用put覆盖代替修改;
		 delete删除,不会立刻操作数据,打标记。
	4.维护横向切分后的数据。
HRegion
	一段表的数据(横向拆分)。即start key~end key之间的数据一个Region(拆分后的小表数据)。
store
	横向拆分后的子表的纵向拆分。
	一个Region内部,每个列族数据,单独存放叫做store。
	
namespace--table--region--store(1对多)

在这里插入图片描述

架构相关概念

HRagionServer

HRegionServer(和DataNode同一节点)
1. 存储表数据部分
2. put delete get scan等针对数据的操作
3. 定时向Master报告自身节点的状态
4. 管理表的数据的Table的数据

HMaster

HMaster
1. Region Server状态的管理
2. 表的管理:create drop alter
3. 实现HRegionServer的数据负载均衡,平衡HRegion的分布

Zookeeper

Zookeeper
1. 解决HMaster的单点故障问题
2. 存放HMaster管理的HRegionServer的状态信息,并通知HMaster
3. 存放HMaster管理的表的元数据信息
   表名、列名、key区间等。

在这里插入图片描述

HRegion

HRegion
   表的横向切片的物理表现,大表的子表,有(startkey endkey),多行数据。
   为了减小单表操作的大小,提高读写效率。

Store

Store
1. 表的纵向切分的物理表现,按照列族作为切分。
2. 按照列族查询,仅需要检索一定范围内的数据,减少全表扫描。

HBase单机版安装

下载

地址:https://mirrors.tuna.tsinghua.edu.cn/apache/hbase/

准备

  1. 安装并配置hadoop
[root@hbase40 installs]# jps
3440 Jps
3329 SecondaryNameNode
3030 NameNode
3134 DataNode
  1. 安装并配置单机zookeeper
[root@hbase40 installs]# jps
3329 SecondaryNameNode
3509 QuorumPeerMain
3030 NameNode
3595 Jps
3134 DataNode
[root@hbase40 installs]# zkServer.sh status
ZooKeeper JMX enabled by default
Using config: /opt/installs/zookeeper3.4.14/bin/../conf/zoo.cfg
Mode: standalone
  1. 设置好日期同步
# 确保HBase主机的时间和网络时间一致
# 查看linux系统时间
[root@hbase40 installs]# date
# 重启chronyd服务,同步系统时间。
[root@hbase40 installs]# systemctl restart chronyd
[root@hbase40 installs]# date
2020年 04月 12日 星期日 22:51:31 CST

安装

# 1. 安装hbase
1. 解压HBase
	[root@hbase40 modules]# tar zxvf hbase-1.5.0-bin.tar.gz -C /opt/install/
2. 配置环境变量
	#JAVA
    export JAVA_HOME=/opt/install/jdk1.8
    export PATH=$PATH:$JAVA_HOME/bin
    # HADOOP
    export HADOOP_HOME=/opt/install/hadoop2.9.2/
    export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
    # zookeeper
    export PATH=$PATH:/opt/install/zookeeper3.4.14/bin/
    # HBase
    export HBASE_HOME=/opt/install/hbase1.5
    export PATH=$PATH:$HBASE_HOME/bin
3. 加载profile配置
	source /etc/profile
# 2. 初始化配置文件
	hbase-env.sh
	hbase-site.xml
	regioniservers
# 1 -------------------hbase-env.sh--------------------

# 配置Java_home
export JAVA_HOME=/opt/installs/jdk1.8

# 注释掉如下2行。
# export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m -XX:ReservedCodeCacheSize=256m"
# export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m -XX:ReservedCodeCacheSize=256m"

# 禁用内置zookeeper
export HBASE_MANAGES_ZK=false
# 2. -------------------hbase-site.xml-------------------------
<configuration>
    <!-- hbase的访问hdfs入口,ns HaHadoop的虚拟命名空间 -->
    <property>
        <name>hbase.rootdir</name>
        <value>hdfs://hbase40:9000/hbase</value>
    </property>
    <!-- 使用分布式模式 -->
    <property>
        <name>hbase.cluster.distributed</name>
        <value>true</value>
    </property>
    <!-- zookeeper集群地址,端口默认2181不需要指定 -->
    <property>
        <name>hbase.zookeeper.quorum</name>
        <value>hbase40</value>
    </property>
    <!--zookeeper的默认工作目录,就是data目录,要和zookeeper的一样-->
    <property>
        <name>hbase.zookeeper.property.dataDir</name>
        <value>/opt/install/zookeeper3.4/data/</value>
    </property>
    <!--配置hdfs的hdfs的flush方式:否则该版本启动会报错-->
    <property>
        <name>hbase.unsafe.stream.capability.enforce</name>
        <value>false</value>
    </property>
</configuration>
#  -------------------配置regionservers(regionserver所在节点的ip) -------------------
hadoop30
# 3. 启动hbase
# 启动顺序
zookeepr->hdfs->hbase
# 1. 启动HMaster
[root@hbase40 install]# hbase-daemon.sh start master
# 关闭
[root@hbase40 install]# hbase-daemon.sh stop master
# 2. 启动HRegionServer
[root@hbase40 install]# hbase-daemon.sh start regionserver
# 关闭
[root@hbase40 install]# hbase-daemon.sh stop master
# 3.全部启动
[root@hbase40 install]# start-hbase.sh
# 4. 验证访问
1. java进程查看
[root@hadoop30 installs]# jps
4688 NameNode
5618 HMaster
5730 HRegionServer
4819 DataNode
3509 QuorumPeerMain
6150 Jps
4984 SecondaryNameNode
2. HMaster WebUI查看
http://ip:16010
3. 进入客户端
hbase shell
hbase(main):001:0>

HBase 命令

注意:命令行中,删除字符用ctrl+backspace

​ HBase shell 命令结尾没有“分号”

1. 客户端进出命令

# 进入客户端:
	./hbase shell
# 退出客户端命令:
	quit/exit
# 帮助
	help

2. namespace的管理命令(相当于数据库中DataBase)

默认存在一个default的namespace
#1. 查看namespace
  list_namespace

#2. 创建namespace
  create_namespace "命名空间名字"`

#3. 删除namespace
  drop_namespace "命令空间名字"

3. 表的操作(table)

# 1. 查看所有表
hbase(main):008:0> list    (目前没有表)
TABLE
0 row(s) in 0.0320 seconds
=> []
hbase(main):009:0>

# 2. 查看某个namespace下的所有表
hbase(main):001:0> list_namespace_tables "test"
TABLE
user
1 row(s) in 0.2980 seconds

# 3. 创建表 (如果不指定namespace,则放在默认default下)
语法:create "test:user","info","edu"
hbase(main):004:0> create "test:user","info","edu"
0 row(s) in 2.5580 seconds
=> Hbase::Table - test:user

# 4. 查看表结构(表名、列族相关信息)
语法:desc "namespace:表名字"
hbase(main):002:0> desc "test:user"
Table test:user is ENABLED
test:user
COLUMN FAMILIES DESCRIPTION
{NAME => 'edu', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE',
DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => '
true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
{NAME => 'info', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE',
 DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE =>
'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
2 row(s) in 30.3330 seconds
hbase(main):003:0>

# 5. 删除表和禁用表(HBase对表进行了加锁,若想删除必须先进行禁用)
语法:disable "namespace:表名字"
hbase(main):010:0> disable "cyf:user"
0 row(s) in 2.2970 seconds
hbase(main):011:0>

语法:drop "namespace:表名"
hbase(main):011:0> drop "cyf:user"
0 row(s) in 1.3540 seconds
hbase(main):012:0>

4.表数据操作(增删改查)

1.HBase添加数据,会按照rowkey进行排序(默认字典排序)。

2.HBase查询数据,查询结果按照rowkey排序展示。

# 1. 添加数据(每次只能添加一个列,一个put代表一个数据)
	# 表 rowkey 列族:列名 值
	语法:put "namespace:表","rowkey","列族1:列名1","值"
	put "test:user","1001","info:name","cyf"
	put "test:user","1001","info:age","66"
	put "test:user","1001","info:mobile","110000"
	
# 2. 根据rowkey查找数据(get)
	语法:get "namespace:表名","rowkey"
	get "test:user","1001"
	
    hbase(main):006:0> get "test:user","1001"
    COLUMN                       CELL
     info:age                    timestamp=1624148527287, value=66
     info:mobile                 timestamp=1624148627742, value=110000
     info:name                   timestamp=1624148314733, value=lihao
    1 row(s) in 0.0130 seconds
    hbase(main):007:0>
    
# 3. 根据rowkey和列族查找部分列
	语法:get "namespace:表名","rowkey","列族:列"
	get "test:user","1001","info:name"
	
    hbase(main):001:0> get "test:user","1001","info:name"
    COLUMN                       CELL
     info:name                   timestamp=1624148314733, value=lihao
    1 row(s) in 30.3270 seconds
    hbase(main):002:0>
    
# 4. scan 查询表中所有数据(scan 多行查询)
	语法:scan "namespace:表名"
	scan "test:user"
hbase(main):006:0> scan "test:user"
ROW                          COLUMN+CELL
 1001                        column=info:age, timestamp=1624148527287, value=66
 1001                        column=info:mobile, timestamp=1624148627742, value=110000
 1001                        column=info:name, timestamp=1624148314733, value=lihao
 1002                        column=info:age, timestamp=1624149095675, value=26
 1002                        column=info:name, timestamp=1624149028019, value=cyf
 1003                        column=info:age, timestamp=1624149122537, value=15
 1003                        column=info:name, timestamp=1624149045376, value=fjl
3 row(s) in 0.0640 seconds
hbase(main):007:0>

# 5.查询表中前2条数据(scan)
	语法:scan "namespace:表名",{LIMIT=>2}
	scan "test:user",{LIMIT=>2}
# LIMIT注意事项:
	LIMIT必须大写
	等号:=>

hbase(main):007:0> scan "test:user",{LIMIT=>2}
ROW                          COLUMN+CELL
 1001                        column=info:age, timestamp=1624148527287, value=66
 1001                        column=info:mobile, timestamp=1624148627742, value=110000
 1001                        column=info:name, timestamp=1624148314733, value=lihao
 1002                        column=info:age, timestamp=1624149095675, value=26
 1002                        column=info:name, timestamp=1624149028019, value=cyf
2 row(s) in 0.0350 seconds
hbase(main):008:0>

# 6. 使用start row 和 end row 范围查找(1002~1003前闭后开)
	语法:scan "namespace:表名",{STARTROW=>"",ENDROW=""}
	scan "test:user",{STARTROW=>"1002",ENDROW=>"1004"}
	
hbase(main):013:0> scan "test:user",{STARTROW=>"1002",ENDROW=>"1004"}
ROW                          COLUMN+CELL
 1002                        column=info:age, timestamp=1624149095675, value=26
 1002                        column=info:name, timestamp=1624149028019, value=cyf
 1003                        column=info:age, timestamp=1624149122537, value=15
 1003                        column=info:name, timestamp=1624149045376, value=fjl
2 row(s) in 0.0270 seconds
hbase(main):014:0>

# 7. 查询rowkey=“1001”并且向后查询三条,使用start row和limit查找
	语法:scan "namespace:表",{START=>"10001",LIMIT=>3}
	scan "test:user",{STARTROW=>"10001",LIMIT=>2}

hbase(main):014:0> scan "test:user",{STARTROW=>"10001",LIMIT=>2}
ROW                          COLUMN+CELL
 1001                        column=info:age, timestamp=1624148527287, value=66
 1001                        column=info:mobile, timestamp=1624148627742, value=110000
 1001                        column=info:name, timestamp=1624148314733, value=lihao
 1002                        column=info:age, timestamp=1624149095675, value=26
 1002                        column=info:name, timestamp=1624149028019, value=cyf
2 row(s) in 0.0280 seconds
hbase(main):015:0>
     
# 8. 修改数据(本质上是覆盖--put)
	语法:put "namespace:表","rowkey","列族:列名","值"
	put "test:user","1001","info:name","yf"

hbase(main):005:0> put "test:user","1002","info:name","yf"
0 row(s) in 0.0110 seconds

hbase(main):006:0> scan "test:user"
ROW                          COLUMN+CELL
 1001                        column=info:age, timestamp=1624148527287, value=66
 1001                        column=info:mobile, timestamp=1624148627742, value=110000
 1001                        column=info:name, timestamp=1624157416165, value=lihao
 1002                        column=info:age, timestamp=1624149095675, value=26
 1002                        column=info:name, timestamp=1624157430474, value=yf
 1003                        column=info:age, timestamp=1624149122537, value=15
 1003                        column=info:name, timestamp=1624149045376, value=fjl
3 row(s) in 0.0170 seconds
hbase(main):007:0>

# 9. 删除数据(删除某个cell)
	语法:delete "namespace:表","rowkey","列族:列名"
	delete "test:user","1001","info:mobile"

hbase(main):007:0> delete "test:user","1001","info:mobile"
0 row(s) in 0.0370 seconds

hbase(main):008:0> scan "test:user"
ROW                          COLUMN+CELL
 1001                        column=info:age, timestamp=1624148527287, value=66
 1001                        column=info:name, timestamp=1624157416165, value=lihao
 1002                        column=info:age, timestamp=1624149095675, value=26
 1002                        column=info:name, timestamp=1624157430474, value=yf
 1003                        column=info:age, timestamp=1624149122537, value=15
 1003                        column=info:name, timestamp=1624149045376, value=fjl
3 row(s) in 0.0250 seconds
hbase(main):009:0>

# 10. 删除某个rowkey对应的整行数据(deleteall)
	语法:deleteall "namespace:表","rowkey"
	deleteall "test:user","1001"
hbase(main):009:0> deleteall "test:user","1001"
0 row(s) in 0.0170 seconds

hbase(main):010:0> scan "test:user"
ROW                          COLUMN+CELL
 1002                        column=info:age, timestamp=1624149095675, value=26
 1002                        column=info:name, timestamp=1624157430474, value=yf
 1003                        column=info:age, timestamp=1624149122537, value=15
 1003                        column=info:name, timestamp=1624149045376, value=fjl
2 row(s) in 0.0110 seconds
hbase(main):011:0>

# 11. 统计表中所有数据
# HBase没有外键,也没有表连接
	语法:count "namespace:表"
	count "test:user"

hbase(main):011:0> count "test:user"
2 row(s) in 0.0360 seconds
=> 2
hbase(main):012:0>

5. 多版本问题

# 修改表的指定列族中数据版本数量。
# alter "namespace:表",{NAME=>"info",VERSIONS=>2}
# alter "test:user",{NAME=>"info",VERSIONS=>2}

hbase(main):012:0> alter "test:user",{NAME=>"info",VERSIONS=>2}
Updating all regions with the new schema...
0/1 regions updated.
1/1 regions updated.
Done.
0 row(s) in 3.6380 seconds

hbase(main):013:0> desc "test:user"
Table test:user is ENABLED
test:user
COLUMN FAMILIES DESCRIPTION
{NAME => 'edu', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE',
DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => '
true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
{NAME => 'info', BLOOMFILTER => 'ROW', VERSIONS => '2', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE',
 DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE =>
'true', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
2 row(s) in 0.0410 seconds

hbase(main):014:0>

# 同一个cell添加2次数据。
hbase(main):014:0> put "test:user","1002","info:name","aaa"
0 row(s) in 0.2620 seconds

hbase(main):015:0>put "test:user","1002","info:name","bbb"
0 row(s) in 0.0290 seconds
# 查看多版本
hbase(main):016:0> get "test:user","1002",{COLUMN=>'info:name',VERSIONS=>2}
COLUMN                       CELL
 info:name                   timestamp=1624158383906, value=bbb
 info:name                   timestamp=1624158364824, value=aaa
1 row(s) in 0.0360 seconds

hbase(main):017:0>
# 表的列族的VERSIONS=>2表示的该列族的数据,要保存2个版本。如果put3次,则保留最新的版本。
# 使用get和scan查询,默认查询到的只有最新版本数据
# 查询多个版本 get "namespace:表","rowkey",{COLUMN=>"列族:列",VERSIONS=>数字}

HBase API

API介绍

HBase Java API
1.Configuration:访问HBase配置信息。
2.Configuration:hbase数据库连接,操作表的数据。
3.Admin:HBase客户端连接,操作表结构 namespace
HBase 表示数据(数据查询 Delete 表 namespace)模型的API
1.NamespaceDescriptor 表示namespace命名空间。
API含义创建
Configuration配置文件HBaseConfiguration.create();
Connection连接,用来操作数据ConnectionFactory.createConnection(conf);
Admin客户端,用来操作元数据
(namespace和table结构)
conn.getAdmin();
NamespaceDescriptor命名空间相当于databaseNamespaceDescriptor.create(“btrc”).build();
TableName表名TableName.valueOf(“btrc:user”);
HTableDescriptornew HTableDescriptor(tablename);
HColumnDescriptor列族new HColumnDescriptor(“info”);
Put添加数据new Put(Bytes.toBytes(“1001”));
Deleterowkey的删除条件new Delete(Bytes.toBytes(“1001”));
Getscan单行查询器new Get(Bytes.toBytes(“1019”));
Scanscan多行查询器new Scan();
Result查询结果集(单条结果)table.get(get);
ResultScanner查询结果集(N条结果)table.getScanner(scan);

环境准备

  • 依赖

    <properties>
       <!--定义版本号-->
       <hbase.version>1.5.0</hbase.version>
       <java.version>1.8</java.version>
       <maven.compiler.source>8</maven.compiler.source>
       <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependency>
        <groupId>org.apache.hbase</groupId>
        <artifactId>hbase-client</artifactId>
        <version>${hbase.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hbase</groupId>
        <artifactId>hbase-common</artifactId>
        <version>${hbase.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hbase</groupId>
        <artifactId>hbase-protocol</artifactId>
        <version>${hbase.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.hbase</groupId>
        <artifactId>hbase-server</artifactId>
        <version>${hbase.version}</version>
    </dependency>
    
  • HBase客户端连接编码步骤

//将hbase中的conf中的 **hbase-site.xml**放到resource配置文件目录中。
    public void test2() throws Exception{
        //1.初始化配置
        Configuration conf = HBaseConfiguration.create();
        conf.set("hbase.zookeeper.quorum","192.168.153.40");
        //2.创建Hbase连接
        Connection conn = ConnectionFactory.createConnection(conf);
        //3.获得操作表和namespace结构的admin
        Admin admin = conn.getAdmin();
        //4.java中创建namespace对象
        NamespaceDescriptor btrc = NamespaceDescriptor.create("btrc").build();
        //5.执行创建namespace操作
        admin.createNamespace(btrc);
        //释放资源
        admin.close();
    }

常用API

表相关的API
	creat "namespace:表",”列族“
	表名字:TableName
	TableName.valueOf("namespace:”表名")
	
表:HTableDesscriptor
	new HTableDesscriptor(”table“);
列族:HColumnDescriptor
	new HColumnDescriptor("列族名字");

创建表:
	①获得表名字
	②创建Table
	③创建列族
	④将列族,装配在table中
	⑤创建表:admin

1. 创建namespace和表

# 创建namespace
//1. 构建namespace信息。
NamespaceDescriptor btrc = NamespaceDescriptor.create("btrc").build();
//2. 创建namespace
admin.createNamespace(btrc);
# 创建表 
public void test3() throws Exception{
   //1.初始化配置文件
   Configuration conf = HBaseConfiguration.create();
   conf.set("hbase.zookeeper.quorum","192.168.153.40");
   //启动显示日志
   BasicConfigurator.configure();
   //2.获得hbase连接
   Connection conn = ConnectionFactory.createConnection(conf);
   //3.获得admin
   Admin admin = conn.getAdmin();
   //1.创建表名
   TableName tableName = TableName.valueOf("btrc:persons");
   //2.构造表
   HTableDescriptor table = new HTableDescriptor(tableName);
   //3.构造列族
   HColumnDescriptor info = new HColumnDescriptor("info");
   HColumnDescriptor edu = new HColumnDescriptor("edu");
   //4.将列族装配在table中
   table.addFamily(info);
   table.addFamily(edu);
   //5.admin创建表
   admin.createTable(table);
   admin.close();
}

2. 表操作

  • 判断表是否存在

    # 操作表,使用admin
    //1. 创建表名
    TableName tableName = TableName.valueOf("btrc:persons");
    //2. 判断表是否存在
    boolean b = admin.tableExists(tableName);
    System.out.println(b?"存在":"不存在");
    

3. 添加

# 操作数据使用conn
**Bytes是HBase提供的进行字节和java数据类型转化的工具类

public void test2() throws Exception{
   //0.获得连接
   Connection conn = HBaseUtil.getConnection();
   //1.获得table表
   TableName tableName = TableName.valueOf("btrc:persons");
   Table table = conn.getTable(tableName);
   //2.创建一个put
   Put put = new Put(Bytes.toBytes("1001"));
   //3.向put中绑定添加的数据(列族:列,“值”)
   put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("name"),Bytes.toBytes("liqinghua"));
   put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("age"),Bytes.toBytes("24"));
   //4.使用table,添加put的数据---将put放入table中
   table.put(put);
   table.close();
}

4. 修改

public void test5() throws Exception{
  //0.获得连接
  Connection conn = HBaseUtil.getConnection();
  //1.获得table表
  TableName tableName = TableName.valueOf("btrc:persons");
  Table table = conn.getTable(tableName);
  //2.创建一个put
  Put put = new Put(Bytes.toBytes("1001"));
  //3.向put中绑定添加的数据(列族:列,“值”)修改实质即为重新添加
  put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("name"),Bytes.toBytes("wangyuxi"));
  //4.使用table,添加put的数据---即修改数据
  table.put(put);
  table.close();
}

5. 删除

public void test3() throws Exception{
  //0.获得连接
  Connection conn = HBaseUtil.getConnection();
  //1.先获得table
  Table table = conn.getTable(TableName.valueOf("btrc:persons"));
  //3.创建删除Delete
  Delete delete = new Delete(Bytes.toBytes("10012"));
  //4.调用table.delete(delete)----执行删除
  table.delete(delete);
}

6. 查询

  • 根据rowkey单条查询(get)。

    public void test6() throws Exception{
      //1.获得连接
      Connection conn = HBaseUtil.getConnection();
      //2.获得表table
      TableName tableName = TableName.valueOf("btrc:persons");
      Table table = conn.getTable(tableName);
      //3.封装查询操作Get(rowkey)
      Get get = new Get(Bytes.toBytes("1008"));
      //4.执行查询,获得查询结果Result
      Result result = table.get(get);
      //5.处理结果Result  info-name,info-age
      byte[] names = result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name"));
      byte[] ages = result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age"));
      //将字节name转换String name
      //将字节name转换Int age
      String name = Bytes.toString(names);
      int age = Bytes.toInt(ages);
      System.out.println("name"+name);
      System.out.println("age"+age);
    }
    
  • 多条查询(scan-rowkey=1001,查询4条)

    scan "btrc:persons",{STARTROW=>"1001",LIMIT=>4}
    public void test7() throws Exception{
       //1.获得连接
       Connection conn = HBaseUtil.getConnection();
       //2.获得表table
       TableName tableName = TableName.valueOf("btrc:persons");
       Table table = conn.getTable(tableName);
       //3.创建Scan多行查询扫描器
       Scan scan = new Scan();
       //4.设置Scan扫描器(列族,起始rowkey,limit)
       scan.addFamily(Bytes.toBytes("info"));
       scan.withStartRow(Bytes.toBytes("1001"));
       scan.setLimit(4);
       //5.执行扫描--table.getScanner(scan)得到ResultScanner
       ResultScanner scanner = table.getScanner(scan);
       //6.处理结果,遍历ResultScanner得到数据
         for (Result result : scanner) {
            byte[] namebyt = result.getValue(Bytes.toBytes("info"), Bytes.toBytes("name"));
            byte[] agebyt = result.getValue(Bytes.toBytes("info"), Bytes.toBytes("age"));
            String name = Bytes.toString(namebyt);
            int age = Bytes.toInt(agebyt);
            System.out.println(name+age);
         }
        table.close();
    }
    

HBase架构原理

HBase的Region分区的意义

# HBase的Region分区的意义
HRegion:
	1.HBase中数据存在RegionServer管理的Region中。
	2.一旦Region数据量达标到一定规模,拆分。()
	3.每个region(startkey---endkey)
Meta表(元数据表)
	1.表  rowkey区间范围,每条信息范围对应一个Region,对应一个Region所在RegionServer机器。
		方便客户端(添加 查询)快速定位到Region。

在这里插入图片描述

读写数据操作原理

读数据

# 客户端查询数据执行原理
1.客户端访问zookeeper:(目的:获得meta表的位置)
	HMaster地址
    HRegionServer地址
    hbase:meta表数据所在regionServer地址
2.查询meta所在机器,确定rowkey和user对应的Region在哪个RegionServer
3.请求Region所在RegionServer,数据检索
4.获得查询结果。 

在这里插入图片描述

写数据

# 客户端写入数据执行原理
1.请求zookeeper
	获得meta表位置。
2.请求meta所在RegionServer节点确定表,rowkey并返回对应region所在的RegionServer服务节点。
3.请求RegionServer向里面写入数据。
**注意
	①将写操作记录在日志(HLog、WAL:write ahead log)
	②regionserver接受数据写入内存中。写入数据的内存:Memstore。

在这里插入图片描述

HBase底层原理

Region split 分区

# Region split的原因
1.随着put操作,Region空间不断增加,导致put delete get需要定位rowkey的时间逐渐增加。(效率降低)
# Region split 分区
2.HBase,当Region达到一定条件的时候,会对Region进行切分,并且将切分后的Region交给不同的RegionServer管理。
	a.根据rowkey在region定位数据,速度变快
	b.Region数据在RegionServer分布管理负载均衡。(合理利用硬件资源)
# Region split 分区时机
3.Region Split的时机
	hbase.hregion.memstore.flush.size=128M
	分区时机:
		Region数量(平方)*hbase.hregion.memstore.flush.size=Region分区时的大小
		Region分区时机:
			128M ---  512M ---  1152M---....10GB---10GB---10GB
# 默认Region split 方案的缺点
	由于HBase的默认分区没有考虑实际业务场景中rowkey规律:
	a.拆分后的Region的后续增长极其不均衡,导致数据倾斜。
	b.访问Region中的数据,访问的概率也不同,访问负载不均衡,数据热点问题。

Region Split 分区

  • 原因(为啥)

    提高Region的负载和读写效率。

在这里插入图片描述

  • 说明

    Region一拆为二(平均)

  • 默认分区机制

    Region中数据超过128M、512M、1152M… *Region数量2hbase.hregion.memstore.flush.size … 10G、10G

    查看参数

    hbase.hregion.memstore.flush.size=128M
    hbase.hregion.max.filesize=10G
    
  • 问题

    默认分区容易导致数据倾斜,硬件资源无法充分利用。

Region切片预分区

​ 预分区即创建表的时候,决定分区,Region的个数,每个Region维护的rowkey区间。

​ 目的:防止数据热点,防止数据倾斜。(均衡分布数据到不同Regionc)

​ rowkey设计核心操作。

  • 为什么

    • 增加读写效率。(多个region分布在不同的RegionServer中,可以提高并发效率)
    • 尽量保证每个Region中的数据量相当,防止数据倾斜。(合理利用计算资源)
  • 分区的效果

    每个Region维护一对StartKey和EndKey,限定维护输入rowkey范围。

    添加数据时,讲rowkey放入匹配的region中。

  • 创建表时分区,手动指定(分区方案)

    命令:

    create "namespace:表","列族",SPLITS=>["100000","200000","300000","400000"]

    总结:按照splits中指定的分区key,分成4个区。

    效果:
    在这里插入图片描述

    从文件中手动指定。

    • 创建分区文件,输入分区key信息。

    ​ 分区键的文件:(splits.txt)

    ​ 10000

    ​ 20000

    ​ 30000

    • 使用文件创建分区

    create “btcr:t_users1”,“info”,SPLITS_FILE => “/opt/install/hbase1.5/splits.txt”

    java代码分区:

    admin.createTable(htable,splitkeys);
    在这里插入图片描述

RowKey设计

  • RowKey作用

    1. 读写数据时通过 RowKey 找到对应的 Region;
    2. Region、Store、Store File中的数据,会按照rowkey的字典顺序排序。
    3. 通过 get 方式,指定 RowKey 获取唯一一条记录
    4. 通过 scan 方式,设置 startRowstopRow 参数进行范围匹配
  • 设计原则

    1. 唯一,不能重复
    2. Region负载均衡,散列,后添加的数据,总是能均匀的散部在不同的Region中。
    3. 避免热点数据,避免访问量频繁的数据,分布在同一个或者两个Region中。
    4. 满足业务查询需求。
  • 技巧

    1. 进行查询的时候,根据RowKey从前向后匹配
    2. 结合业务场景特点,选择合适的字段来做为RowKey,并且按照查询频次来放置字段顺序
    3. 宏观散列,局部排序。
  • 案例

    1. 查询某用户在某应用中的操作记录
    hash(userid) + appid + timestamp
    
    2. 查询某用户在某应用中的操作记录(优先展现最近的数据)
    hash(userid) + appid + (Long.Max_Value - timestamp)
    
    3. 查询某用户在某段时间内所有应用的操作记录
    hash(userid) + timestamp + appid
    
    4. 查询某用户的基本信息
    hash(userid)
    

MemStore Flush刷写

1.client不断向RegionServer维护的Region中添加数据。
	Region维护的数据存在于内存中。
	client向HBase写入数据,Memstore。
	说明:Region维护在内存中,目的:写入数据和删除块。
2.问题:
	Region数据量过大,RegionServer内存不足。
3.解决问题:
	HBase监控,当Region中数据达到条件值,将Region中Store,分别向HDFS进行刷写flush,将数据写入到HDFS文件中。
	列族数量==store数量:每个store对应hdfs中的一个文件夹。
	结论:每次达到刷写条件,就将store数据flush到hdfs文件中,随着数据增长,会不断刷写文件。(有很多小的store file)
4.flush时机
	a.Region Server整个服务总内存占用达到40%,执行全局刷写:(全局flush:影响客户端操作,该flush会暂停客户端读写操作)
		hbase.regionserver.global.memstore.size
	b.当MemStore持续写入1h,触发局部刷写:
		hbase.regionserver.optionalcacheflushinterval
	c.当单个Region中的数据文件大小超过128M(局部刷写):
		hbase.hregion.memstore.flush.size
	b和c只要达到一个条件就进行刷写。
	d.手动flush
		flush "namespace:表名"
		
HBase刷写到hdfs的存储位置:http://192.168.153.40:50070/explorer.html#/hbase/data/btrc/persons/19a0c4f38481013611b4102c32a1c761/info
  • 说明

    简言:持久化,保护数据不丢失。

    将RegionServer中内存中的数据Memstore,写入到硬盘中。


  • 在这里插入图片描述

  • 时机

    1. Region Server整个服务总内存占用达到40%该flush会暂停客户端读写操作

    对应参数:hbase.regionserver.global.memstore.size

    1. MemStore持续写入1h。

    对应参数:hbase.regionserver.optionalcacheflushinterval

    1. 单个Region中的数据文件大小超过128M。

    对应参数:hbase.hregion.memstore.flush.size

  • 手动flush

    命令:flush "namespace:表名"

Store File Compact合并

1.问题:
	随着HBase运行,HBase基于HDFS中,会不断的刷写成小的store file文件(几十MB)
总结:大量刷写次数,产生大量的小的刷写文件store file,查询storefile中的数据,需要将region所管理所有storefile遍历才能查到?
	问题:大量的小storefile在内存中,遍历所有storefile查询效率。
		a.小文件多
		b.小文件整体没有顺序。
		c.HDFS不适合管理小文件,文件管理效率也会降低。
2.解决方案:
	store File compaction 合并
  • 原因

    storefile小文件过多,查询时,需要遍历所有文件,效率低。

    storefile中遍布过期数据,占用空间,且查询效率低。

  • 说明

    简言:为提高检索效率,合并store


  • 在这里插入图片描述

  • 分类和时机

    • (局部合并) minor compact

    将部分相邻的store合并中等文件。

    特点:少量相邻文件的合并。
      发生频率较高,不影响性能。
    

    手动命令:compact "namespace:表名"

    • (全局合并) majorcompact

    将某个表:region:列族:所有storefile进行全局合并,产生一个文件。

    特点:
    1. 全局的所有store file文件的合并(数据量大)。
    2. 去除删除被覆盖的文件。(删除过期版本的数据、delete命令删除过的数据起始还存在着,只不过打了标记)
       **删除过期数据(Region内存中 小Storefile中数据不会真正删除)
    3. 特别消耗RegionServer的性能资源。(重点)
    时机:每7天执行一次:参数:hbase.hregion.majorcompaction
    

    一般手动触发。

    手动触发命令:major_compact "namespace:表名"

HBase为何能做到海量数据的实时读写(简单说明秒级原因)

# 1.Mestore
Region内存中
	特点:
	(内存)
	(数据最新的)
	(有序)
# 2.BlockCache(LRU)
	HBase缓存中。
	缓存策略:LRU(数据淘汰机制):保留最近最新使用多的数据。
# 3.磁盘storeFile(每个小file中rowkey是有序的)
	磁盘的检索速度慢是因为寻道。
# 4.磁盘合并大storeFile(减少file数量,可以提高磁盘的检索效率)
	1.磁盘storeFile文件数量少,减少遍历。
	2.文件内以及文件在磁盘中,rowkey有序,代码检索还是磁盘寻道大大节省了时间

HBase之Mapreduce

Mapreduce思想

在这里插入图片描述

环境搭建

<!--hadoop依赖-->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-common</artifactId>
    <version>${hadoop.version}</version>
</dependency>
<!--hdfs依赖-->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-hdfs</artifactId>
    <version>${hadoop.version}</version>
</dependency>
<!--mapreduce依赖-->
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-mapreduce-client-core</artifactId>
    <version>${hadoop.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-mapreduce-client-common</artifactId>
    <version>${hadoop.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.hadoop</groupId>
    <artifactId>hadoop-mapreduce-client-jobclient</artifactId>
    <version>${hadoop.version}</version>
</dependency>
<!-- hbase依赖 -->
<dependency>
    <groupId>org.apache.hbase</groupId>
    <artifactId>hbase-client</artifactId>
    <version>${hbase.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.hbase</groupId>
    <artifactId>hbase-common</artifactId>
    <version>${hbase.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.hbase</groupId>
    <artifactId>hbase-protocol</artifactId>
    <version>${hbase.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.hbase</groupId>
    <artifactId>hbase-server</artifactId>
    <version>${hbase.version}</version>
</dependency>

编码实现

需求:

统计 btrc:persons 表中所有人的平均年龄?

package demo3;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.junit.Test;
import util.HBaseUtil;

import java.io.IOException;

public class AgeUserJob {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        //job组装和启动代码
        //初始化hdfs入口换成为hbase入口
        Configuration conf = HBaseConfiguration.create();
        conf.addResource("/hbase-site.xml");
        //创建job
        Job job = Job.getInstance(conf);
        job.setJarByClass(AgeUserJob.class);
        //配置map端
            //TableInputformat
        job.setInputFormatClass(TableInputFormat.class);
        TableMapReduceUtil.initTableMapperJob("btrc:persons",new Scan(),UserMapper.class,Text.class,IntWritable.class,job);
        //配置reduce端
            //TableOutputFormat
        job.setOutputFormatClass(TableOutputFormat.class);
        //hbase的表必须创建
        TableMapReduceUtil.initTableReducerJob("btrc:pavgage",UserReducer.class,job);
        //启动job
        boolean b = job.waitForCompletion(true);
        System.out.println(b);
    }

    //map的类
    public static class UserMapper extends TableMapper<Text, IntWritable>{
        @Override
        protected void map(ImmutableBytesWritable key, Result value, Context context) throws IOException, InterruptedException {
            //key -rowkey
            //行数据 resulit
            byte[] value1 = value.getValue(Bytes.toBytes("info"), Bytes.toBytes("age"));
            //得到age属性数据
            int age = Bytes.toInt(value1);
            //将age作为value输出
            //将"age"作为key 输出,
            context.write(new Text("age"),new IntWritable(age));
        }
    }

    //reducer的类
    public static class UserReducer extends TableReducer<Text,IntWritable, NullWritable>{
        @Override
        protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
            //key:"age"
            //values:[15,18,57]
            int sum = 0;
            int count = 0;
            for (IntWritable value : values) {
                sum+=value.get();
                count++;
            }
            //sum总年龄  count 条数
            int ave = sum/count;
            //输出到HBase表
            //封装成put
            String rowkey = "23点07分_ave";
            Put put = new Put(Bytes.toBytes(rowkey));
            put.addColumn(Bytes.toBytes("info"),Bytes.toBytes("avgage"),Bytes.toBytes(ave));
            /**
             *   context.write(xxx,put); put是一条数据,会被添加在HBase中
             */
            context.write(NullWritable.get(),put);
        }
    }
}

Mapper

/**
 * 泛型1:Map输出的key
 * 泛型2:Map输出的value
 */
public class PersonMapper extends TableMapper<Text, LongWritable> {
    /**
     *
     * @param key  输入的数据的rowkey
     * @param value rowkey对应的一条结果
     * @param context map的输出
     */
    @Override
    protected void map(ImmutableBytesWritable key, Result value, Context context) throws IOException, InterruptedException {
        //1. 获得value中的age
        byte[] agebyte = value.getValue(Bytes.toBytes("info"), Bytes.toBytes("age"));
        if (agebyte != null) {
            //2. 将age的数字输出
            // 注意 输出的key,必须一样,这样shuffle才能分组成一组数据,方便reduce进行汇总。
            context.write(new Text("age"), new LongWritable(Bytes.toInt(agebyte)));
        }
    }
}

Reducer

/**
 * 输出的结果要进入HBase,所以输出的value必须是Put
 */
public class PersonReducer extends TableReducer<Text, LongWritable, NullWritable> {
    /**
     *
     * @param key map输出的key输入到reduce
     * @param values map输出的value输入到reduce
     * @param context 写入到hbase表中的context
     */
    @Override
    protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
        // 1. 获得map输出的value,进行遍历,计算平均值。
        int count = 0;
        double sum = 0.0;
        for (LongWritable p:values){
            count++;
            sum+=p.get();
        }
        double avgAge = sum/count;
        //2. 创建
        Put put = new Put(Bytes.toBytes("ageAge"));
        //3. 将统计数据封装到Put中。
        put.addColumn(Bytes.toBytes("info"), Bytes.toBytes("avg_age"), Bytes.toBytes(avgAge));
        //4. 以null为key,put为value输出到HBase中。
        context.write(NullWritable.get(),put);
    }
}

Job

//1. 初始化配置文件,方便job操作HBase中的数据。(输入输出)
Configuration conf = HBaseConfiguration.create();
conf.addResource("/hbase-site.xml");
//2. 创建job任务
Job job = Job.getInstance(conf);
//3. 设置输入输出工具,HBase提供了从操作数据的InputFormat和OutputFormat
job.setInputFormatClass(TableInputFormat.class);
job.setOutputFormatClass(TableOutputFormat.class);
//4. 绑定Map相关信息:读入表,Scan,使用的Mapper,输出key类型,输出Value类型,job任务。
TableMapReduceUtil.initTableMapperJob("baizhins:person", new Scan(), PersonMapper.class, Text.class, LongWritable.class, job);
//5. 绑定reduce信息:输出信息表,reduce类型,job任务。
TableMapReduceUtil.initTableReducerJob("baizhins:person_avgAge", PersonReducer.class, job);
//6. 启动任务
job.waitForCompletion(true);

HBase架构完整版

在这里插入图片描述

集群规划
192.168.153.30: HMaster
192.168.153.31: HRegionServer
192.168.153.32: HRegionServer
192.168.153.33: HRegionServer
# 0 确保HDFS HA已经搭建完毕
[root@hadoop130 ~]# jps
1259 JournalNode
1965 NameNode
1758 DFSZKFailoverController
2110 Jps
1215 QuorumPeerMain
# 1. 安装HBase
1. 解压HBase
	[root@hadoop30 modules]# tar zxvf hbase-1.5.0-bin.tar.gz -C /opt/install/
2. 配置环境变量
	#JAVA
    export JAVA_HOME=/opt/installs/jdk1.8
    export PATH=$PATH:$JAVA_HOME/bin
    # HADOOP
    export HADOOP_HOME=/opt/installs/hadoop2.9.2/
    export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
    # zookeeper
    export PATH=$PATH:/opt/installs/zookeeper3.4.14/bin/
    # HBase
    export HBASE_HOME=/opt/install/hbase1.5
    export PATH=$PATH:$HBASE_HOME/bin
3. 加载profile配置
	source /etc/profile
# 2. 初始化HBase 配置文件
# 1 -------------------hbase-env.sh--------------------

# 配置Java_home
export JAVA_HOME=/opt/install/jdk1.8

# 注释掉如下2行。
# export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m -XX:ReservedCodeCacheSize=256m"
# export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS -XX:PermSize=128m -XX:MaxPermSize=128m -XX:ReservedCodeCacheSize=256m"

# 禁用内置zookeeper
export HBASE_MANAGES_ZK=false
# 2. -------------------hbase-site.xml-------------------------
<configuration>
    <!-- hbase的入口,ns HaHadoop的虚拟命名空间 -->
    <property>
        <name>hbase.rootdir</name>
        <value>hdfs://ns/hbase</value>
    </property>
    <!-- 使用分布式模式 -->
    <property>
        <name>hbase.cluster.distributed</name>
        <value>true</value>
    </property>
    <!-- zookeeper集群地址,端口默认2181不需要指定 -->
    <property>
        <name>hbase.zookeeper.quorum</name>
        <value>hadoop30,hadoop31,hadoop32</value>
    </property>
    <!--zookeeper的默认工作目录,就是data目录,要和zookeeper的一样-->
    <property>
        <name>hbase.zookeeper.property.dataDir</name>
        <value>/opt/install/zookeeper3.4.14/data</value>
    </property>
    <!--配置hdfs的hflush:否则该版本启动会报错-->
    <property>
        <name>hbase.unsafe.stream.capability.enforce</name>
        <value>false</value>
    </property>
</configuration>
# 3. -------------------regionservers--------------------
hadoop31
hadoop32
hadoop33
# 3. 远程拷贝
1. hbase加入hadoop配置文件
[root@hadoop30 install]# ln -s /opt/install/hadoop2.9.2/etc/hadoop/core-site.xml /opt/install/hbase1.5/conf/core-site.xml
[root@hadoop30 install]# ln -s /opt/install/hadoop2.9.2/etc/hadoop/hdfs-site.xml /opt/install/hbase1.5/conf/hdfs-site.xml
2. 拷贝profile文件
[root@hadoop30 install]# scp /etc/profile root@hadoop31:/etc/
[root@hadoop30 install]# scp /etc/profile root@hadoop32:/etc/
[root@hadoop30 install]# scp /etc/profile root@hadoop33:/etc/
3. 拷贝hbase安装软件和配置文件
[root@hadoop30 install]# scp -r hbase1.5/ root@hadoop31:/opt/install/
[root@hadoop30 install]# scp -r hbase1.5/ root@hadoop32:/opt/install/
[root@hadoop30 install]# scp -r hbase1.5/ root@hadoop33:/opt/install/
4. 重新加载profile
[root@hadoop31 ~]# source /etc/profile
[root@hadoop32 ~]# source /etc/profile
[root@hadoop33 ~]# source /etc/profile
# 4. 启动HBase
# 启动HMaster
root@hadoop30 install]# hbase-daemon.sh start master

# 启动HRegionServer
[root@hadoop31 ~]# hbase-daemon.sh start regionserver
[root@hadoop32 ~]# hbase-daemon.sh start regionserver
[root@hadoop33 ~]# hbase-daemon.sh start regionserver

# 启动后需要等待20s左右,HMaster需要初始化工作。

在这里插入图片描述



这篇关于HBase数据库的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程