@R星校长
初识 HBase
hbase 介绍
概述
Welcome to Apache HBase™
Apache HBase™ is the Hadoop database, a distributed, scalable, big data store.
Use Apache HBase™ when you need random, realtime read/write access to your Big Data. This project’s goal is the hosting of very large tables – billions of rows X millions of columns – atop clusters of commodity hardware. Apache HBase is an open-source, distributed, versioned, non-relational database modeled after Google’s Bigtable: A Distributed Storage System for Structured Data by Chang et al. Just as Bigtable leverages the distributed data storage provided by the Google File System, Apache HBase provides Bigtable-like capabilities on top of Hadoop and HDFS.
Apache HBase™ 是 Hadoop 数据库,是一个分布式、可伸缩、大数据存储区。
当您需要随机、实时读/写访问大数据时,请使用 Apache HBase™。 该项目的目标是在商用硬件集群之上托管非常大的表----数十亿行X百万列。 Apache HBase 是一个开源的、分布式的、版本化的、非关系的数据库,它参考了Google 的 Bigtable。 正如 Bigtable 利用 Google 文件系统提供的分布式数据存储一样,Apache HBase 在 Hadoop 和 HDFS 之上提供了类似 Bigtable 的功能。
定义:HBase 是 Hadoop Database ,是一个高可靠性、高性能、面向列、可伸缩、实时读写的分布式 NOSQL 数据库。
作用:主要用来存储非结构化、半结构化和结构化的松散数据(列式存储的NoSQL 数据库)
注:MySQL 亿级别的数据,效率极具下降。
tb_order 达到 10 亿条数据,是不是非常慢呢?
阿里又是如何解决的呢。将订单数据横向拆分,平均放到 80 个 MySQL 中:
OrderId.hashCode()%80 来决定数据放到哪个表中。
利用 Hadoop HDFS 作为其文件存储系统,利用 Hadoop MapReduce 来处理 HBase 中的海量数据,利用 Zookeeper 作为其分布式协同服务。正常情况下,HBase 不依赖于 YARN ,用到的时候可以随时开启。从技术上讲,HBase 实际上更像是“数据存储”而不是“数据库”,因为它缺少 RDBMS中的许多功能,例如字段类型,二级索引,触发器和高级查询语言等。
HBase 数据模型
逻辑上,HBase 的数据模型同关系型数据库很类似,数据存储在一张表中,有行有列。但从底层物理存储结构(Key-Value)来看,HBase 更像一个 Map。
HBase 逻辑结构
物理存储结构
13489854921_92233704903999438078233/basic:dnum/1592979155327/Put/vlen=11/mvcc=0 V: 15973136770
数据模型
- NameSpace
命名空间,相当于关系型数据库中的 database,每个命名空间下有多个表。Hbase 默认自带的命名空间 hbase 和 default ;hbase 中存放的是 HBase 内置的表,default 是用户默认使用的命名空间。 - Region
类似关系型数据库的表,不同之处在于 HBase 定义表示只需要声明列族,不需要声明具体的列。列可以动态的按需要指定;HBase 更加适合自带经常变更的场景。开始创建表是一个表对应一个 region,当表增大到一定值是会被拆分为两个 region。 - Row
HBase 表中的每行数据被称为 Row,由一个 RowKey 和多个 Column 组成,数据是按照 RowKey 的字典顺序存储的,并且查询是只能根据 RowKey 进行检索,所以 RowKey 的设计很关键。 - Column
列是由列族(Column Family)和列限定符(Column Qualifier)进行限定,例如:base:name,base:sex
。建表示只需定义列族,而列限定符无需预先定义。 - Cell
某行中的某一列被称为 Cell(单元格),由 {rowkey,column family:column qualifier,time stamp} 确定单元。Cell 中没有具体的类型,全部是字节码的形式(字节数组)存储。 - TimeStamp
用于标识数据的不同版本(version),每条数据写入时,如果不指定时间戳,系统会自动为其加上该字段,值为写入 HBase 的时间。
非关系型数据库知识面扩展
redis,memcached
mongoDB,CouchDB
Hbase、Cassandra 横向扩展 随机读写
hbase 架构

MySQL 存储是 4KB 作为一个小的存储空间。4KB datapage 数据页。查询时会从磁盘上遍历寻址。效率较低。
HBase 引入了列族(面向列族存储,而不是列存储每个列都单独存储)的概念:
CF1 CF2
id,name,age || likes,address
查询列所在的列族即可,其他列族中内字段不查询。
目录表 hbase:meta
目录表 hbase:meta 作为 HBase 表存在,并从 hbase shell 的 list (类似 show tables)命令中过滤掉,但实际上是一个表,就像任何其他表一样。
hbase:meta 表(以前称为.META.),保有系统中所有 region 的列表。hbase:meta 位置信息存储在 zookeeper 中。hbase:meta 表是所有查询的入口
表结构如下:
key:
region的key,结构为:[table],[region start key,end key],[region id]
values:
info:regioninfo(当前region序列化的HRegionInfo实例)
info:server(包含当前region的RegionServer的server:port)
info:serverstartcode(包含当前region的RegionServer进程的开始时间)
当表正在拆分时,将创建另外两列,称为 info:splitA 和 info:splitB 。 这些列代表两个子 region。 这些列的值也是序列化的 HRegionInfo 实例。区域分割后,将删除此行。
a,,endkey
a,startkey,endkey
a,startkey,
空键用于表示表开始和表结束。具有空开始键的 region 是表中的第一个 region。如果某个 region 同时具有空开始和空结束键,则它是表中唯一的 region。
Client
hbase:meta tablea,,100,node2
hbase:meta tablea,101-200,node3
hbase:meta tablea,201-300,node5
hbase:meta tablea,301-400,node237
hbase:meta tablea,401-500,node24
hbase:meta tablea,501,,node896
Client->zookeeper(hbase:meta)->root region(tablea,node3 tableb,node4)->meta region-> regionserver(数据)
包含访问 HBase 的接口并维护 cache 来加快对 HBase 的访问。HBase 客户端查找关注的行范围所在的 regionserver。它通过查询 hbase:meta表来完成此操作。在找到所需的 region 之后,客户端与提供该 region 的 RegionServer 通信,而不是通过 Master,并发出读取或写入请求。此信息缓存在客户端中,以便后续请求无需经过查找过程。如果 Master 的负载均衡器重新平衡或者由于 regionserver 宕机,都会重新指定该 region 的 regionserver 。客户端将重新查询目录表以确定用户 region 的新位置。
通过 Admin 进行管理功能的实现。
Zookeeper
- 保证任何时候,集群中只有一个活跃 master
- 存贮所有 Region 的寻址入口。 root region 的地址 hbase:meta 表的位置
- 实时监控 Region server 的上线和下线信息。并实时通知 Master
- 存储 HBase 的 schema 和 table 元数据
Master
- 为 Region server 分配 region
- 负责 Region server 的负载均衡
- 发现失效的 Region server 并重新分配其上的 region
- 管理用户对 table 的增删改操作 不是数据的增删改(DML) DDL
概括:管理 region 的分配和管理对表的操作
RegionServer
- Region server 维护 region,处理对这些 region 的 IO 请求
- Region server 负责切分在运行过程中变得过大的 region
Region 
- HBase 自动把表水平划分成多个区域 (region),每个 region 会保存一个表里面某段连续的数据 (每条记录都有一个行键,按照行键字典序排列)
- 每个表一开始只有一个 region ,随着数据不断插入表,region 不断增大,当增大到一个阈值的时候,region 就会等分会两个新的 region(裂变)
- 当 table 中的行不断增多,就会有越来越多的 region。这样一张完整的表被保存在多个 Regionserver 上。
- 一个 region 由多个 store 组成,一个 store 对应一个 CF(列族)
- HRegion 是 HBase 中分布式存储和负载均衡的最小单元。最小单元就表示不同的 HRegion 可以分布在不同的 HRegion server 上。HRegion 由一个或者多个 Store 组成,每个 store 保存一个 columns family 。每个 Store 又由一个 memStore 和 0 至多个 StoreFile 组成。如图:StoreFile 以 HFile 格式保存在 HDFS 上。
Memstore 与 storefile
- store 包括位于内存中的 memstore 和位于磁盘的 storefile。
- 写操作先写入 memstore,当 memstore 中的数据达到某个阈值, hregionserver 会启动 flashcache 进程写入 storefile ,每次写入形成单独的一个 storefile。
- 当 storefile 文件的数量增长到一定阈值后,系统会进行合并(minor、major compaction),在合并过程中会进行版本合并和删除工作(majar),形成更大的 storefile
- 当一个 region 所有 storefile 的大小和数量超过一定阈值后,会把当前的 region 分割为两个,并由 hmaster 分配到相应的 regionserver 服务器,实现负载均衡
- 客户端检索数据,先查找 memstore,再 blockcache(查询缓存),找不到再找 storefile
hbase 搭建方式以及搭建流程
独立模式
JDK 版本要求:jdk7 最好,jdk8 也行,官方称未充分测试。
这是默认模式。独立模式是快速入门部分中描述的内容。 在独立模式下,HBase 不使用 HDFS - 它使用本地文件系统 - 它在同一个 JVM 中运行所有HBase 守护进程和本地 ZooKeeper 。 Zookeeper 绑定到端口 2181,因此客户可以与 HBase 通信。
具体操作
将 HBase 与本地文件系统一起使用并不能保证持久性。如果文件未正确关闭,HDFS 本地文件系统实现将丢失编辑。当您尝试使用新软件时,很可能会发生这种情况,经常启动和停止守护进程,而不是总是干净利落。您需要在 HDFS 上运行 HBase 以确保保留所有写入。作为评估的第一阶段,针对本地文件系统运行旨在使您熟悉常规系统的工作方式。
在conf/hbase-env.sh
中设置 JAVA_HOME
在conf/hbase-site.xml
中,仅需要指定 hbase 和 zookeeper 写数据的本地路径。默认情况下会在 /tmp 下创建新的目录。
<configuration>
<property>
<name>hbase.rootdir</name>
<value>file:///var/bjsxt/only/hbase</value>
</property>
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/var/bjsxt/only/zookeeper</value>
</property>
</configuration>
我们不需要创建任何目录,hbase 会创建。如果手动创建了,hbase 会做一个迁移,这不是我们想要的。
bin/start-hbase.sh
脚本用于启动 hbase。启动成功,hbase 会在标准输出打印成功启动的信息。使用 jps 查看进程,会只有一个 HMaster 进程。这个进程中包含了一个 HMaster、一个 HRegionServer 以及一个 zookeeper 的 daemon。它们在同一个进程中。
网页访问:http://node1:60010/
1、连接HBase:
shell> ./bin/hbase shell
2、在 hbase 的 shell 中输入 help 并回车,获取帮助:
hbase(main):001:0> help
3、创建表
使用 create 命令创建表,必须指定表名和列族的名称
hbase(main):001:0> create 'test', 'cf'
0 row(s) in 0.4170 seconds
=> Hbase::Table - test
4、列出表的信息
使用 list 命令列出信息。
hbase(main):002:0> list 'test'
TABLE
test
1 row(s) in 0.0180 seconds
=> ["test"]
5、向 table 插入数据
使用 put 命令。
hbase(main):003:0> put 'test', 'row1', 'cf:a', 'value1'
0 row(s) in 0.0850 seconds
hbase(main):004:0> put 'test', 'row2', 'cf:b', 'value2'
0 row(s) in 0.0110 seconds
hbase(main):005:0> put 'test', 'row3', 'cf:c', 'value3'
0 row(s) in 0.0100 seconds
以上,插入了三个值,每次一个。第一次在 row1 的位置,cf:a 列插入值 value1。hbase 中的列由列族前缀cf跟一个冒号,再跟一个列标识符后缀比如 a。
6、一次性扫描表中的所有数据
要查询表中的数据,可以使用 scan 命令。可以在该命令中使用限定条件,下面获取了表中的所有数据:
hbase(main):016:0> scan 'test'
ROW COLUMN+CELL
row1 column=cf:a, timestamp=1568514191889, value=value1
row2 column=cf:b, timestamp=1568514198429, value=value2
row3 column=cf:c, timestamp=1568514205341, value=value3
3 row(s) in 0.0350 seconds
7、查询一行记录
使用 get 命令一次获取一行记录
hbase(main):017:0> get