HBase位于Hadoop生态系统的结构化存储层,建立在HDFS之上的分布式、面向列的数据库,并且使用Zookeeper作为协调服务。
- HDFS****为HBase提供了高可靠的底层存储支持,
- MapReduce****为HBase提供了高性能的计算能力,
- Zookeeper****则为HBase提供了稳定的服务和失效恢复机制。
虽然Hadoop是一个高容错、高延时的分布式文件系统和高并发的批处理系统,但是它不适用于提供实时计算;HBase是可以提供实时计算的分布式数据库,数据被保存在HDFS分布式文件系统上,由HDFS保证期高容错性,但是再生产环境中,HBase是如何基于hadoop提供实时性呢?
HBase上的数据是以StoreFile(HFile)二进制流的形式存储在HDFS上block块儿中;但是HDFS并不知道的HBase用于存储什么,它只把存储文件认为是二进制文件,也就是说,HBase的存储数据对于HDFS文件系统是透明的。
III、HBase与HDFS在下面的表格中,我们对HDFS与HBase进行比较:
HDFS | HBase |
---|---|
HDFS适于存储大容量文件的分布式文件系统。 | HBase是建立在HDFS之上的数据库。 |
HDFS不支持快速单独记录查找。 | HBase提供在较大的表快速查找 |
HDFS提供了高延迟批量处理;没有批处理概念。 | HBase提供了数十亿条记录低延迟访问单个行记录(随机存取)。 |
HDFS提供的数据只能顺序访问。 | HBase内部使用哈希表和提供随机接入,并且其存储索引,可将在HDFS文件中的数据进行快速查找。 |
rowkey | column family(userInfo) | column family(addressInfo) | timestamp | ||||||
---|---|---|---|---|---|---|---|---|---|
name | age | sex | password | country | province | city | |||
1 | zhengshuang | 29 | 0 | 123456 | PRC | 辽宁 | 沈阳 | 11@1.com | 154590701 |
2 | lixiaolu | 28 | 0 | 123456 | PRC | 上海 | 上海 | 22@2.com | 154590702 |
3 | luozhixiang | 31 | 1 | 123456 | PRC | 台湾 | 台北 | 33@3.com | 154590703 |
表(Table)
在HBase,数据存储在表中,表名是一个字符串,表由行和列组成。与关系型数据库不同,HBase是多维映射的。
行(Row)
HBase的行由行键或一个多个列组成。行键没有数据类型,总是视为字节数组byte[]。行键类似于关系型数据库中的主键索引,在整个HBase表中是唯一的,但是RDBMS不同的是,行键按照字母顺序排序。例如,表中已经有三条行键为1000001,1000002,1000004的数据,当插入一条行键为1000003的数据时,该条数据不会排在最后,而是排在行键1000002,1000004的中间。因此,行键的设计非常重要,我们可以利用行键的特性将相关的数据排列在一起。例如,将网站的域名作为行键的前缀,则应该将域名进行反转存储(org.apache.www,org.apache.mail,org.apache.jira),这样将所有的Apache域名将在表中的排列在一起,而不是分散排列。
列族(Column Family)
HBase列族由多个列组成,相当于将列进行分组。列的数量没有限制,一个列族里可以有数百万格列。表中的每一个行都有同样的列族。**列族必须在表创建的时候指定,不能轻易修改,且数量不超过三个。**列族名的类型是字符串。
列限定符(Qualifier)
列限定符用于代表HBase表中的列的名称,定位列族里的数据。格式如**family:qualifier 。**代表family 列族中的 qualifier 列。
单元格(Cell)
单元格通过行键、列族和限定符一起来定位。单元格包含值和时间戳。值没有数据类型,总是视为 byte[];时间戳代表值得版本,类型为long。
II、HBase 数据模型
由于HBase表示多维映射的,因此行列的排列与传统的RDBMS不同。传统的RDBMS数据库对于不存在的值,必须存储NULL,而在HBase中,不存在的值可以省略,且不占存储空间。此外HBase在建表时指定表名和列族,不需要指定列,所有的列在后续添加数据的时候动态添加,而RDBMS指定好列以后,不可以修改或动态添加。
三、集群搭建[daniel@hadoop103 software]$ tar -zxvf hbase-1.2.1-bin.tar.gz -C /opt/moudle/
[daniel@hadoop103 hbase-1.2.1]$ vim conf/hbase-env.sh export JAVA_HOME=/usr/java/jdk1.8.0_211-amd64 #指定使用外部的zk集群 export HBASE_MANAGES_ZK=FALSE
[daniel@hadoop103 hbase-1.2.1]$ vim conf/hbase-site.xml <configuration> <!-- 指定hbase在HDFS上存储的路径 --> <property> <name>hbase.rootdir</name> <value>hdfs://hadoop101:9000/hbase</value> </property> <!-- 指定hbase是分布式的 --> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> <!-- 指定zk的地址,多个用“,”分割 --> <property> <name>hbase.zookeeper.quorum</name> <value>hadoop101:2181,hadoop102:2181,hadoop103:2181</value> </property> <property> <name>hbase.master.info.port</name> <value>16010</value> </property> <!--指定true为分布式集群部署--> <property> <name>hbase.cluster.distributed</name> <value>true</value> </property> </configuration>
[daniel@hadoop103 hbase-1.2.1]$ vim conf/regionservers hadoop104 hadoop105 [daniel@hadoop101 hbase-1.2.1]$ vim conf/backup-masters hadoop105
[daniel@hadoop103 hbase-1.2.1]$ scp -r /opt/moudle/hbase-1.2.1/ daniel@hadoop104:/opt/moudle/ [daniel@hadoop103 hbase-1.2.1]$ scp -r /opt/moudle/hbase-1.2.1/ daniel@hadoop105:/opt/moudle/
Master:http://hadoop103:16010/
Backup Master:http://hadoop105:16010/
四、常用shell操作进入客户端操作界面
[daniel@hadoop103 hbase-1.2.1]$ bin/hbase shell
创建user表, 包含base_info、extra_info两个列族
hbase(main):001:0> create 'user', 'base_info', 'extra_info' 0 row(s) in 1.7180 seconds => Hbase::Table - user ## 另一种写法 hbase(main):002:0> create 'user2', {NAME => 'base_info', VERSIONS => '3'},{NAME => 'extra_info'} 0 row(s) in 1.2440 seconds => Hbase::Table - user2
添加数据操作
hbase(main):001:0> put 'user', 'rk0001', 'base_info:name', 'zhangsan' 0 row(s) in 0.2610 seconds hbase(main):002:0> put 'user', 'rk0001', 'base_info:gender', 'female' 0 row(s) in 0.0280 seconds hbase(main):003:0> put 'user', 'rk0001', 'base_info:age', 20 0 row(s) in 0.0180 seconds hbase(main):004:0> put 'user', 'rk0001', 'extra_info:address', 'beijing' 0 row(s) in 0.0410 seconds
数据查询
hbase(main):005:0> get 'user', 'rk0001' COLUMN CELL base_info:age timestamp=1612262295591, value=20 base_info:gender timestamp=1612262285794, value=female base_info:name timestamp=1612262272928, value=zhangsan extra_info:address timestamp=1612262304269, value=beijing 4 row(s) in 0.0840 seconds hbase(main):006:0> get 'user', 'rk0001', 'base_info' COLUMN CELL base_info:age timestamp=1612262295591, value=20 base_info:gender timestamp=1612262285794, value=female base_info:name timestamp=1612262272928, value=zhangsan 3 row(s) in 0.0240 seconds
查看rowkey下面的某个列族的信息
hbase(main):006:0> get 'user', 'rk0001', 'base_info' COLUMN CELL base_info:age timestamp=1612262295591, value=20 base_info:gender timestamp=1612262285794, value=female base_info:name timestamp=1612262272928, value=zhangsan 3 row(s) in 0.0240 seconds
获取user表中row key为rk0001,base_info列族的name、age列标示符的信息
hbase(main):007:0> get 'user', 'rk0001', 'base_info:name', 'base_info:age' COLUMN CELL base_info:age timestamp=1612262295591, value=20 base_info:name timestamp=1612262272928, value=zhangsan 2 row(s) in 0.0200 seconds
获取user表中row key为rk0001,base_info、extra_info列族的信息
hbase(main):008:0> get 'user', 'rk0001', 'base_info', 'extra_info' COLUMN CELL base_info:age timestamp=1612262295591, value=20 base_info:gender timestamp=1612262285794, value=female base_info:name timestamp=1612262272928, value=zhangsan extra_info:address timestamp=1612262304269, value=beijing 4 row(s) in 0.0180 seconds hbase(main):009:0> get 'user', 'rk0001', {COLUMN => ['base_info', 'extra_info']} COLUMN CELL base_info:age timestamp=1612262295591, value=20 base_info:gender timestamp=1612262285794, value=female base_info:name timestamp=1612262272928, value=zhangsan extra_info:address timestamp=1612262304269, value=beijing 4 row(s) in 0.0210 seconds hbase(main):010:0> get 'user', 'rk0001', {COLUMN => ['base_info:name', 'extra_info:address']} COLUMN CELL base_info:name timestamp=1612262272928, value=zhangsan extra_info:address timestamp=1612262304269, value=beijing 2 row(s) in 0.0200 seconds
指定rowkey与列值查询
hbase(main):011:0> get 'user', 'rk0001', {FILTER => "ValueFilter(=, 'binary:zhangsan')"} COLUMN CELL base_info:name timestamp=1612262272928, value=zhangsan 1 row(s) in 0.0750 seconds
获取user表中row key为rk0001,列标示符中含有a的信息
hbase(main):002:0> get 'user', 'rk0001', {FILTER => "(QualifierFilter(=,'substring:a'))"} COLUMN CELL base_info:age timestamp=1612262295591, value=20 base_info:name timestamp=1612262272928, value=zhangsan extra_info:address timestamp=1612262304269, value=beijing
继续插入一批数据
hbase(main):003:0> put 'user', 'rk0002', 'base_info:name', 'fanbingbing' 0 row(s) in 0.1320 seconds hbase(main):004:0> put 'user', 'rk0002', 'base_info:gender', 'female' 0 row(s) in 0.0270 seconds hbase(main):005:0> put 'user', 'rk0002', 'base_info:birthday', '2000-06-06' 0 row(s) in 0.0160 seconds hbase(main):006:0> put 'user', 'rk0002', 'extra_info:address', 'shanghai' 0 row(s) in 0.0150 seconds
查询user表中的所有信息
hbase(main):007:0> scan 'user'
列族查询
## Scan时可以设置是否开启Raw模式,开启Raw模式会返回包括已添加删除标记但是未实际删除的数据 ## VERSIONS指定查询的最大版本数
hbase(main):008:0> scan 'user', {COLUMNS => 'base_info'}
hbase(main):009:0> scan 'user', {COLUMNS => 'base_info', RAW => true, VERSIONS => 5}
多列族查询
hbase(main):023:0> scan 'user', {COLUMNS => ['base_info', 'extra_info']}
hbase(main):024:0> scan 'user', {COLUMNS => ['base_info:name', 'extra_info:address']}
指定列族与某个列名查询
五、集群架构HBase架构采用主从(master/slaver)方式,由三种类型的节点组成——**HMaster节点,HRegionServer节点 和 Zookeeper集群。**HMaster节点作为主节点,HRegionServer节点作为从节点,主从方式类似于HDFS的NameNode,和DataNode。
HBase客户端通过 RPC方式 与 HMaste节点 和 HRegionServer节点 通信,HMaster节点连接Zookeeper获得HRegionServer节点的状态并对其进行管理。HBase的系统架构。
由于 HBase 将底层数据存储于HDFS中,因此也设计 NameNode节点 和 DataNode节点等,HRegionServer经常与HDFS的DataNode在同一个节点,有利于数据的本地访问,节省网络传输时间。
I、HMasterHMaster 并非只有一个,用户可以启动多个 HMaster 节点,并通过Zookeeper选举保证只有一个HMaster节点保持活跃,其余的处于备用。
HBase客户端通过 RPC方式 与 HMaste节点 和 HRegionServer节点 通信,HMaster节点连接Zookeeper获得HRegionServer节点的状态并对其进行管理。HBase的系统架构。
由于 HBase 将底层数据存储于HDFS中,因此也设计 NameNode节点 和 DataNode节点等,HRegionServer 经常与 HDFS 的 DataNode 在同一个节点,有利于数据的本地访问,节省网络传输时间。
HMaster 主要作用:
- HMaster不用于存储HBase的任何数据,而是管理HRegionServer节点,指定HRegionServer 节点可以管理哪些 HRegion,实现负载均衡。
- 当HRegionServer宕机时,HMaster 会将其中的 HRegion 迁移到其他地方HRegionServer上。
- 管理用户表的增删改查等操作。
- 管理表的元数据(元数据主要保存HRegion的唯一标识符和HRegionServer的映射关系)
- 权限控制
HBase**使用 rowkey 自动把表水平切分为多个叫 HRegion区域 ,每个 HRegion 由表中的多行数据组成。**最初一个表只有一个 HRegion ,随着数据的增多便会在某行的边界上将表分割成两个大小基本相同的 HRegion。后由HMaster节点将HRegion分配到不同的HRegionServer节点中,由HRegionServer对其进行管理以及响应客户端的读写请求。分布在集群中的所有HRegion 按照序列排列就成了一张表。
每一个HRegion 都记录了rowkey 的 起始行键(startkey) 和 结束行键(endkey),**第一个HRegion的 startkey 和 最后一个 Hregion 的 endkey 为空。**客户端可以通过 HMaster 节点快速定位到每一个rowkey 所在的 HRegion。
III、Store**一个Store 存储 HBase 表中的一个列族的数据。**由于一个表被水平分割为多个 HRegion,那么一个HRegion 中包含一个或多个 Store。一个Store包含一个 MemStore 和 多个 HFile。
MemStore 相当于一个内存缓冲区,数据存入磁盘之前会先存入 MemStore。
当 MemStore 达到某一大小,会生成一个 HFile 文件,MemStore 的数据的数据会移到 HFile 中,StoreFile 是对 HFile 文件的封装,HFile 是 HBase 底层的数据存储格式,最终数据以 HFile 的格式存储在HDFS中。
需要注意的是,一个HFile文件只存放某个时刻 MemStore 中的所有数据,一个完整的行数据可能存放于多个 HFile 里。
IV、HLogHLog 是 HBase 的日志文件,记录数据的更新操作。与 RDBMS 数据库类似,为了保证 数据的一致性和实现回滚的操作,HBase 在写数据时候会先进行 WAL(预写日志)操作。即将更新操作写入 HLog 中后,才会将数据写入到 Store 的 MenStore 中,两个地方都写入成功,才会认为数据写入成功。
由于MenStore是写入内存,数据达到一定量的时候才会写入到HDFS,如果在写入到HDFS 之前服务器宕机,MemStore 中的数据丢失,还可以通过 HLog 来恢复数据。
**HLog在HDFS中,**所以服务器崩溃,HLog仍可用。
V、Zookeeper每一个 HRegionServer 节点会在 Zookeeper 中注册一个自己的临时节点,HMaster 通过这些临时节点发现可用的 HRegionServer 节点,跟踪 HRegionServer 的节点故障。
HBase 利用 Zookeeper 来确保只有一个活动的 HMaster 在运行。
HRegion 应该分配到哪个 HRegionServer 节点上,也是通过 Zookeeper 得知的。