Hbase
1、Hbase简介
(1)基础介绍
HBase的原型是Google的BigTable论文,受到了该论文思想的启发,目前作为Hadoop的子项目来开发维护,用于支持结构化的数据存储。
HBase是Google Bigtable的开源实现,但是也有很多不同之处。比如:Google
Bigtable利用GFS作为其文件存储系统,HBase利用Hadoop
HDFS作为其文件存储系统;Google运行MAPREDUCE来处理Bigtable中的海量数据,HBase同样利用Hadoop
MapReduce来处理HBase中的海量数据;Google
Bigtable利用Chubby作为协同服务,HBase利用Zookeeper作为对应。
(2)Hbase特点
海量存储
- Hbase适合存储PB级别的海量数据,在PB级别的数据以及采用廉价PC存储的情况下,能在几十到百毫秒内返回数据。这与Hbase的极易扩展性息息相关。正式因为Hbase良好的扩展性,才为海量数据的存储提供了便利。
- 传统关系型数据库,单表不会超过五百万,超过要做分表分库,不会超过30列。
- Hbase单表可以有百亿行、百万列,数据矩阵横向和纵向两个维度所支持的数据量级都非常具有弹性
列式存储
- 这里的列式存储其实说的是列族存储,Hbase是根据列族来存储数据的。列族下面可以有非常多的列,列族在创建表的时候就必须指定。
- 面向列的存储和权限控制,并支持独立检索,可以动态增加列,即,可单独对列进行各方面的操作。
- 列式存储,其数据在表中是按照某列存储的,这样在查询只需要少数几个字段的时候,能大大减少读取的数量
极易扩展
- Hbase的扩展性主要体现在两个方面,一个是基于上层处理能力(RegionServer)的扩展,一个是基于存储的扩展(HDFS)。
- 通过横向添加RegionSever的机器,进行水平扩展,提升Hbase上层的处理能力,提升Hbsae服务更多Region的能力。
- 备注:RegionServer的作用是管理region、承接业务的访问,这个后面会详细的介绍通过横向添加Datanode的机器,进行存储层扩容,提升Hbase的数据存储能力和提升后端存储的读写能力。
高并发
- 由于目前大部分使用Hbase的架构,都是采用的廉价PC,因此单个IO的延迟其实并不小,一般在几十到上百ms之间。这里说的高并发,主要是在并发的情况下,Hbase的单个IO延迟下降并不多。能获得高并发、低延迟的服务。
稀疏
- 稀疏主要是针对Hbase列的灵活性,在列族中,你可以指定任意多的列,在列数据为空的情况下,是不会占用存储空间的。
- 为空的列并不占用存储空间,表可以设计的非常稀疏。不必像关系型数据库那样需要预先知道所有列名然后再进行null填充
总结
- 面向列,容量大,写入比mysql快但是读取没有,超过五百万条数据的话建议读写用Hbase
2、Hbase体系结构
HBase的服务器体系结构遵从简单的主从服务器架构,它由HRegion Server群和HBase Master服务器构成。
HBase Master负责管理所有的HRegion Server,而HBase中的所有RegionServer都是通过ZooKeeper来协调,并处理HBase服务器运行期间可能遇到的错误。
HBase Master Server本身并不存储HBase中的任何数据,HBase逻辑上的表可能会被划分成多个Region,然后存储到HRegion Server群中。HBase Master Server中存储的是从数据到HRegion Server的映射。因此HBase体系结构如下图
(1) Client
- HBase Client 使用HBase的RPC机制与HMaster和HRegionServer进行通信:对于管理类操作,Client与HMaster进行RPC;对于数据读写类操作,Client与HRegionServer进行RPC;
(2)Master
- HBase Master 用于协调多个 Region Server,侦测各个 Region Server 之间的状态,并平衡 Region Server 之间的负载。HBase Master 还有一个职责就是负责分配 Region 给 Region Server。HBase 允许多个 Master 节点共存,但是这需要 Zookeeper 的帮助。不过当多个 Master 节点共存时,只有一个 Master 是提供服务的,其他的 Master 节点处于待命的状态。当正在工作的 Master 节点宕机时,其他的 Master 则会接管 HBase 的集群。
(3)HRegionServer
-
0.94之后的HRegionServer:图片来自Map-R网站
-
0.94之前的HRegionServer
-
对于一个 Region Server 而言,其包括了多个 Region。Region Server 的作用只是管理表格,以及实现读写操作。Client 直接连接 Region Server,并通信获取 HBase 中的数据。对于 Region 而言,则是真实存放 HBase 数据的地方,也就说 Region 是 HBase 可用性和分布式的基本单位。如果当一个表格很大,并由多个 CF 组成时,那么表的数据将存放在多个 Region 之间,并且在每个 Region 中会关联多个存储的单元(Store)。
-
HRegionServer内部管理了一系列HRegion对象,每个HRegion对应了Table中的一个Region,HRegion中由多个HStore组成。每个HStore对应了Table中的一个Column Family的存储,可以看出每个Column Family其实就是一个集中的存储单元,因此最好将具备共同IO特性的column放在一个Column Family中,这样最高效。
-
HStore存储是HBase存储的核心了,其中由两部分组成,一部分是MemStore,一部分是StoreFiles。MemStore是Sorted Memory Buffer,用户写入的数据首先会放入MemStore,当MemStore满了以后会Flush成一个StoreFile(底层实现是HFile),当StoreFile文件数量增长到一定阈值,会触发Compact合并操作,将多个StoreFiles合并成一个StoreFile,合并过程中会进行版本合并和数据删除,因此可以看出HBase其实只有增加数据,所有的更新和删除操作都是在后续的compact过程中进行的,这使得用户的写操作只要进入内存中就可以立即返回,保证了HBase I/O的高性能。当StoreFiles Compact后,会逐步形成越来越大的StoreFile,当单个StoreFile大小超过一定阈值后,会触发Split操作,同时把当前Region Split成2个Region,父Region会下线,新Split出的2个孩子Region会被HMaster分配到相应的HRegionServer上,使得原先1个Region的压力得以分流到2个Region上。下图描述了Compaction和Split的过程
-
在理解了上述HStore的基本原理后,还必须了解一下HLog的功能,因为上述的HStore在系统正常工作的前提下是没有问题的,但是在分布式系统环境中,无法避免系统出错或者宕机,因此一旦HRegionServer意外退出,MemStore中的内存数据将会丢失,这就需要引入HLog了。每个HRegionServer中都有一个HLog对象,HLog是一个实现Write Ahead Log的类,在每次用户操作写入MemStore的同时,也会写一份数据到HLog文件中(HLog文件格式见后续),HLog文件定期会滚动出新的,并删除旧的文件(已持久化到StoreFile中的数据)。当HRegionServer意外终止后,HMaster会通过Zookeeper感知到,HMaster首先会处理遗留的 HLog文件,将其中不同Region的Log数据进行拆分,分别放到相应region的目录下,然后再将失效的region重新分配,领取 到这些region的HRegionServer在Load Region的过程中,会发现有历史HLog需要处理,因此会Replay HLog中的数据到MemStore中,然后flush到StoreFiles,完成数据恢复。
(4)Zookeeper
- 对于 HBase 而言,Zookeeper 的作用是至关重要的。首先 Zookeeper 是作为 HBase Master 的 HA 解决方案。也就是说,是 Zookeeper 保证了至少有一个 HBase Master 处于运行状态。并且 Zookeeper 负责 Region 和 Region Server 的注册。其实 Zookeeper 发展到目前为止,已经成为了分布式大数据框架中容错性的标准框架。不光是 HBase,几乎所有的分布式大数据相关的开源框架,都依赖于 Zookeeper 实现 HA。
(6 )HBase存储格式
HBase中的所有数据文件都存储在Hadoop HDFS文件系统上,主要包括上述提出的两种文件类型:
1.HFile, HBase中KeyValue数据的存储格式,HFile是Hadoop的二进制格式文件,实际上StoreFile就是对HFile做了轻量级包装,即StoreFile底层就是HFile
2.HLog File,HBase中WAL(Write Ahead Log) 的存储格式,物理上是Hadoop的Sequence File
在分布式系统环境中,无法避免系统出错或者宕机,因此一旦HRegionServer意外退出,MemStore中的内存数据将会丢失,这就需要引入HLog了。每个HRegionServer中都有一个HLog对象,HLog是一个实现Write Ahead Log的类,在每次用户操作写入MemStore的同时,也会写一份数据到HLog文件中(HLog文件格式见后续),HLog文件定期会滚动出新的,并删除旧的文件(已持久化到StoreFile中的数据)。当HRegionServer意外终止后,HMaster会通过Zookeeper感知到,HMaster首先会处理遗留的 HLog文件,将其中不同Region的Log数据进行拆分,分别放到相应region的目录下,然后再将失效的region重新分配,领取 到这些region的HRegionServer在Load Region的过程中,会发现有历史HLog需要处理,因此会Replay HLog中的数据到MemStore中,然后flush到StoreFiles,完成数据恢复。
HFile
下图是HFile的存储格式:
首先HFile文件是不定长的,长度固定的只有其中的两块:Trailer和FileInfo。正如图中所示的,Trailer中有指针指向其他数据块的起始点。File Info中记录了文件的一些Meta信息,例如:AVG_KEY_LEN, AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY等。Data Index和Meta Index块记录了每个Data块和Meta块的起始点。
Data Block是HBase I/O的基本单元,为了提高效率,HRegionServer中有基于LRU的Block Cache机制。每个Data块的大小可以在创建一个Table的时候通过参数指定,大号的Block有利于顺序Scan,小号Block利于随机查询。每个Data块除了开头的Magic以外就是一个个KeyValue对拼接而成, Magic内容就是一些随机数字,目的是防止数据损坏。后面会详细介绍每个KeyValue对的内部构造。
HFile
HFile里面的每个KeyValue对就是一个简单的byte数组。但是这个byte数组里面包含了很多项,并且有固定的结构。我们来看看里面的具体结构:
开始是两个固定长度的数值,分别表示Key的长度和Value的长度。紧接着是Key,开始是固定长度的数值,表示RowKey的长度,紧接着是RowKey,然后是固定长度的数值,表示Family的长度,然后是Family,接着是Qualifier,然后是两个固定长度的数值,表示Time Stamp和Key Type(Put/Delete)。Value部分没有这么复杂的结构,就是纯粹的二进制数据了。
HLogFile
上图中示意了HLog文件的结构,其实HLog文件就是一个普通的Hadoop Sequence File,Sequence File 的Key是HLogKey对象,HLogKey中记录了写入数据的归属信息,除了table和region名字外,同时还包括 sequence number和timestamp,timestamp是“写入时间”,sequence number的起始值为0,或者是最近一次存入文件系统中sequence number。HLog Sequece File的Value是HBase的KeyValue对象,即对应HFile中的KeyValue,可参见上文描述。
3、Hbase和其他数据库的区别
常用数据库 | HBase、MongoDB、Redis | Oracle、DB2、MySQL |
---|---|---|
存储格式 | 文档、键值对、图结构 | 表格式,行和列 |
存储规范 | 鼓励冗余 | 规范性,避免重复 |
存储扩展 | 横向扩展,分布式 | 纵向扩展(横向扩展有限) |
查询方式 | 结构化查询语言SQL | 非结构化查询 |
事务 | 不支持事务一致性 | 支持事务 |
性能 | 读写性能高 | 读写性能差 |
成本 | 简单易部署,开源,成本低 | 成本高 |
4、Hbase生态圈的技术
Lily – 基于HBase的CRM
OpenTSDB – HBase面向时间序列数据管理
Kylin – HBase上的OLAP
Phoenix – SQL操作HBase工具
Splice Machine – 基于HBase的OLTP
Apache Tephra – HBase事务支持
TiDB – 分布式SQL DB
Apache Omid - 优化事务管理
Yarn application timeline server v.2 迁移到HBase
Hive metadata存储可以迁移到HBase
Ambari Metrics Server将使用HBase做数据存储
5、Hbase 逻辑架构
RowKey : 主键(最大64kb,实际使用10~100bytes)
-
数据根据RowKey排序
-
HRegion大小达到一定值时,裂变
-
HBase Table中的行的三种方式:
1.通过单个 RowKey 访问 get 'TAB_NAME','COL_FAMILY_NAME' 2.通过 RowKey 的 range(正则) 3.全表扫描 scan 'TAB_NAME'
ColumnFamily
- 列族在在物理存储上对应于 HDFS 上的一个目录。
- HBase 表中的每个列,都归属于某个列族。
- 列族是表的 schema 的一部分(而列不是),必须在使用表之前定义。
- 列名都以列族作为前缀。例如 courses:history,courses:math 都属于 courses 这个列族。
- 每一个列族对应一个 Store,也对应 HDFS 一个目录,类似于 Hive 分区操作一样,HBase相当于按列族进行了分区
Cell
- 由{RowKey, ColumnFamily, Version} 唯一确定的单元
- 类似于excel的一个单元格,数据以字节存储,没有类型
Time Stamp
- rowkey -> ColumnFamily:Column 确定cell
- 每个Cell中保存着一份数据的多个版本:以由精确到毫秒的64位整数存储,可以由HBase写入是自动生成或用户指定
- 若用户指定为避免版本冲突,一定要用单Cell中不重复的时间戳
- 单元格中的数据以时间戳倒序排序
- 为避免Cell数据过大,HBase提供两种机制:保留最新的N条数据,或保留截止当下多长时间的数据
6、Hbase 的基础命令
命令类别 | 命令 |
General | version,status,whoami,help |
DDL | alter,create, describe, disable,drop, enable, exists, is_disabled, is_enabled, list |
DML | count,delete,deleteall,get,get_counter, incr,put,scan,truncate |
Tools | assign,balance_switch,balancer,close_region,compact,flush,major_compact,move,split,unassign,zk_dump |
Replication | add_peer,disable_peer,enable_peer,remove_peer,start_replication,stop_replication |
(1)命名空间NAMESPACE
- list_namespace
- create_namespace ‘NS_NAME’
- describe_namespace ‘NS_NAME’
- 两个特殊命名空间
- 1、hbase => 存hbase内部表
- 2、default => 没有指定命令空间的表,默认存在该default下
(2)表 TABLE
- list
- ist_namespace_tables ‘NS’
- create
- 完整方式:create ‘NS:表名’,{NAME=>‘列族1名’,VERSION=‘版本号’,TTL=‘超时时间’,BLOCKCACHE=‘是否缓存’},{…}…
- VERSION: 版本号:默认最小版本号:0
- TTL: 超时设定:默认值FOREVER
- BLOCKCACHE: 设定列族是否缓存:默认为true
- 简易方式:create ‘[NS:]表名’,‘列族1名’,‘列族2名’…
- 完整方式:create ‘NS:表名’,{NAME=>‘列族1名’,VERSION=‘版本号’,TTL=‘超时时间’,BLOCKCACHE=‘是否缓存’},{…}…
- hp.enable
- hp.disable
- hp.drop 禁用后才可以删除
(3)简单命令
create 'kb08:handphone',{NAME=>'base',VERSION=>'0'},{NAME=>'price'}
desc 'kb08:handphone'
exists 'kb08:handphone'
is_disabled 'kb08:handphone'
put 'kb08:handphone','huawei','base:seriesNo','nova4'
put 'kb08:handphone','huawei','base:cpu','4c8t'
put 'kb08:handphone','huawei','base:resolution','1024*768'
### SELECT ####
hp = get_table 'kb08:handphone'
hp.scan
hp.get 'huawei'[,'base:cpu']
### UPDATE ####
hp.put 'huawei','base:cpu','8c16t'
#### DELETE ####
hp.delete 'iphone','price:retailPrice'
hp.deleteall 'iphone'
truncate 'kb08:handphone'
参考
https://www.cnblogs.com/ggjucheng/p/3380169.html
https://my.oschina.net/u/189445/blog/596325
https://developer.ibm.com/zh/technologies/analytics/articles/ba-cn-bigdata-hbase/