共计 7426 个字符,预计需要花费 19 分钟才能阅读完成。
HBase 定义
HBase 是一个高可靠、高性能、面向列、可伸缩的分布式存储系统,利用 Hbase 技术可在廉价 PC Server 上搭建 大规模结构化存储集群。
HBase 是 Google Bigtable 的开源实现,与 Google Bigtable 利用 GFS 作为其文件存储系统类似,HBase 利用 Hadoop HDFS 作为其文件存储系统;Google 运行 MapReduce 来处理 Bigtable 中的海量数据,HBase 同样利用 Hadoop MapReduce 来处理 HBase 中的海量数据;Google Bigtable 利用 Chubby 作为协同服务,HBase 利用 Zookeeper 作为对应。
HBase 的特点
HBase 中的表一般有以下特点。
1)大:一个表可以有上亿行,上百万列。
2)面向列:面向列表(簇)的存储和权限控制,列(簇)独立检索。
3)稀疏:对于为空(NULL)的列,并不占用存储空间,因此,表可以设计的非常稀疏。
HBase 访问接口
HBase 支持很多种访问,访问 HBase 的常见接口如下。
1、Native Java API,最常规和高效的访问方式,适合 Hadoop MapReduce Job 并行批处理 HBase 表数据。
2、HBase Shell,HBase 的命令行工具,最简单的接口,适合 HBase 管理使用。
3、Thrift Gateway,利用 Thrift 序列化技术,支持 C ++,PHP,Python 等多种语言,适合其他异构系统在线访问 HBase 表数据。
4、REST Gateway,支持 REST 风格的 Http API 访问 HBase, 解除了语言限制。
5、Pig,可以使用 Pig Latin 流式编程语言来操作 HBase 中的数据,和 Hive 类似,本质最终也是编译成 MapReduce Job 来处理 HBase 表数据,适合做数据统计。
6、Hive,当前 Hive 的 Release 版本尚没有加入对 HBase 的支持,但在下一个版本 Hive 0.7.0 中将会支持 HBase,可以使用类似 SQL 语言来访问 HBase。
HBase 存储结构
从 HBase 的架构图上可以看出,HBase 中的存储包括 HMaster、HRegionServer、HRegion、Store、MemStore、StoreFile、HFile、HLog 等,本课程统一介绍他们的作用即存储结构。以下是 HBase 存储架构图:
HBase 中的每张表都通过行键按照一定的范围被分割成多个子表(HRegion),默认一个 HRegion 超过 256M 就要被分割成两个,这个过程由 HRegionServer 管理,而 HRegion 的分配由 HMaster 管理。
HMaster
1、为 Region server 分配 region。
2、负责 Region server 的负载均衡。
3、发现失效的 Region server 并重新分配其上的 region。
4、HDFS 上的垃圾文件回收。
5、处理 schema 更新请求。
HRegionServer
1、维护 master 分配给他的 region,处理对这些 region 的 io 请求。
2、负责切分正在运行过程中变的过大的 region。
可以看到,client 访问 hbase 上的数据并不需要 master 参与(寻址访问 zookeeper 和 region server,数据读写访问 region server),master 仅仅维护 table 和 region 的元数据信息(table 的元数据信息保存在 zookeeper 上),负载很低。HRegionServer 存取一个子表时,会创建一个 HRegion 对象,然后对表的每个列族创建一个 Store 实例,每个 Store 都会有一个 MemStore 和 0 个或多个 StoreFile 与之对应,每个 StoreFile 都会对应一个 HFile,HFile 就是实际的存储文件。因此,一个 HRegion 有多少个列族就有多少个 Store。 一个 HRegionServer 会有多个 HRegion 和一个 HLog。
HRegion
table 在行的方向上分隔为多个 Region。Region 是 HBase 中分布式存储和负载均衡的最小单元,即不同的 region 可以分别在不同的 Region Server 上,但同一个 Region 是不会拆分到多个 server 上。
Region 按大小分隔,每个表一般是只有一个 region。随着数据不断插入表,region 不断增大,当 region 的某个列族达到一个阈值(默认 256M)时就会分成两个新的 region。
每个 region 由以下信息标识:
1、< 表名,startRowkey, 创建时间 >
2、由目录表 (-ROOT- 和.META.) 记录该 region 的 endRowkey
HRegion 定位:Region 被分配给哪个 Region Server 是完全动态的,所以需要机制来定位 Region 具体在哪个 region server。
HBase 使用三层结构来定位 region:
1、通过 zk 里的文件 /hbase/rs 得到 -ROOT- 表的位置。-ROOT- 表只有一个 region。
2、通过 -ROOT- 表查找.META. 表的第一个表中相应的 region 的位置。其实 -ROOT- 表是.META. 表的第一个 region;.META. 表中的每一个 region 在 -ROOT- 表中都是一行记录。
3、通过.META. 表找到所要的用户表 region 的位置。用户表中的每个 region 在.META. 表中都是一行记录。
-ROOT- 表永远不会被分隔为多个 region,保证了最多需要三次跳转,就能定位到任意的 region。client 会将查询的位置信息保存缓存起来,缓存不会主动失效,因此如果 client 上的缓存全部失效,则需要进行 6 次网络来回,才能定位到正确的 region,其中三次用来发现缓存失效,另外三次用来获取位置信息。
Store
每一个 region 由一个或多个 store 组成,至少是一个 store,hbase 会把一起访问的数据放在一个 store 里面 ,即为每个 ColumnFamily 建一个 store,如果有几个 ColumnFamily,也就有几个 Store。 一个 Store 由一个 memStore 和 0 或者多个 StoreFile 组成。HBase 以 store 的大小来判断是否需要切分 region。
MemStore
memStore 是放在内存里的。保存修改的数据即 keyValues。当 memStore 的大小达到一个阀值(默认 64MB)时,memStore 会被 flush 到文件,即生成一个快照。目前 hbase 会有一个线程来负责 memStore 的 flush 操作。
StoreFile
memStore 内存中的数据写到文件后就是 StoreFile,StoreFile 底层是以 HFile 的格式保存。
HFile
HBase 中 KeyValue 数据的存储格式,是 hadoop 的二进制格式文件。首先 HFile 文件是不定长的,长度固定的只有其中的两块:Trailer 和 FileInfo。Trailer 中有指针指向其他数据块的起始点,FileInfo 记录了文件的一些 meta 信息。Data Block 是 hbase io 的基本单元,为了提高效率,HRegionServer 中有基于 LRU 的 block cache 机制。每个 Data 块的大小可以在创建一个 Table 的时候通过参数指定(默认块大小 64KB),大号的 Block 有利于顺序 Scan,小号的 Block 利于随机查询。每个 Data 块除了开头的 Magic 以外就是一个个 KeyValue 对拼接而成,Magic 内容就是一些随机数字,目的是防止数据损坏,结构如下。
HFile 结构图如下:
Data Block 段用来保存表中的数据,这部分可以被压缩。Meta Block 段(可选的)用来保存用户自定义的 kv 段,可以被压缩。FileInfo 段用来保存 HFile 的元信息,不能被压缩,用户也可以在这一部分添加自己的元信息。Data Block Index 段(可选的)用来保存 Meta Blcok 的索引。Trailer 这一段是定长的。保存了每一段的偏移量,读取一个 HFile 时,会首先读取 Trailer,Trailer 保存了每个段的起始位置(段的 Magic Number 用来做安全 check),然后,DataBlock Index 会被读取到内存中,这样,当检索某个 key 时,不需要扫描整个 HFile,而只需从内存中找到 key 所在的 block,通过一次磁盘 io 将整个 block 读取到内存中,再找到需要的 key。DataBlock Index 采用 LRU 机制淘汰。HFile 的 Data Block,Meta Block 通常采用压缩方式存储,压缩之后可以大大减少网络 IO 和磁盘 IO,随之而来的开销当然是需要花费 cpu 进行压缩和解压缩。目标 HFile 的压缩支持两种方式:gzip、lzo。
另外,针对目前针对现有 HFile 的两个主要缺陷:
a) 占用过多内存
b) 启动加载时间缓慢
基于此缺陷,提出了 HFile Version2 设计。
HLog
其实 HLog 文件就是一个普通的 Hadoop Sequence File,Sequence File 的 value 是 key 时 HLogKey 对象,其中记录了写入数据的归属信息,除了 table 和 region 名字外,还同时包括 sequence number 和 timestamp,timestamp 是写入时间,sequence number 的起始值为 0,或者是最近一次存入文件系统中的 sequence number。Sequence File 的 value 是 HBase 的 KeyValue 对象,即对应 HFile 中的 KeyValue。
HLog(WAL log):WAL 意为 write ahead log,用来做灾难恢复使用,HLog 记录数据的所有变更,一旦 region server 宕机,就可以从 log 中进行恢复。
LogFlusher
前面提到,数据以 KeyValue 形式到达 HRegionServer,将写入 WAL 之后,写入一个 SequenceFile。看过去没问题,但是因为数据流在写入文件系统时,经常会缓存以提高性能。这样,有些本以为在日志文件中的数据实际在内存中。这里,我们提供了一个 LogFlusher 的类。它调用 HLog.optionalSync(), 后者根据 hbase.regionserver.optionallogflushinterval (默认是 10 秒),定期调用 Hlog.sync()。另外,HLog.doWrite()也会根据 hbase.regionserver.flushlogentries (默认 100 秒)定期调用 Hlog.sync()。Sync() 本身调用 HLog.Writer.sync(),它由 SequenceFileLogWriter 实现。
LogRoller
Log 的大小通过 $HBASE_HOME/conf/hbase-site.xml 的 hbase.regionserver.logroll.period 限制,默认是一个小时。所以每 60 分钟,会打开一个新的 log 文件。久而久之,会有一大堆的文件需要维护。首先,LogRoller 调用 HLog.rollWriter(),定时滚动日志,之后,利用 HLog.cleanOldLogs()可以清除旧的日志。它首先取得存储文件中的最大的 sequence number,之后检查是否存在一个 log 所有的条目的“sequence number”均低于这个值,如果存在,将删除这个 log。每个 region server 维护一个 HLog,而不是每一个 region 一个,这样不同 region(来自不同的 table)的日志会混在一起,这样做的目的是不断追加单个文件相对于同时写多个文件而言,可以减少磁盘寻址次数,因此可以提高 table 的写性能。带来麻烦的时,如果一个 region server 下线,为了恢复其上的 region,需要将 region server 上的 log 进行拆分,然后分发到其他 region server 上进行恢复。
HBase 设计
HBase 中的每一张表就是所谓的 BigTable。BigTable 会存储一系列的行记录,行记录有三个基本类型的定义:Row Key、Time Stamp、Column。
1、Row Key 是行在 BigTable 中的唯一标识。
2、Time Stamp 是每次数据操作对应关联的时间戳,可以看做 SVN 的版本。
3、Column 定义为 < family>:< label>,通过这两部分可以指定唯一的数据的存储列,family 的定义和修改需要 对 HBase 进行类似于 DB 的 DDL 操作,而 label,不需要定义直接可以使用,这也为动态定制列提供了一种手段。family 另一个作用体现在物理存储优化读写操作上,同 family 的数据物理上保存的会比较临近,因此在业务设计的过程中可以利用这个特性。
数据模型
HBase 以表的形式存储数据。表由行和列组成。列划分为若干个列族(row family),如下图所示。
1、Row Key
与 NoSQL 数据库一样,Row Key 是用来检索记录的主键。访问 HBase table 中的行,只有三种方式:
1)通过单个 Row Key 访问。
2)通过 Row Key 的 range 全表扫描。
3)Row Key 可以使任意字符串(最大长度是 64KB,实际应用中长度一般为 10 ~ 100bytes),在 HBase 内部,Row Key 保存为字节数组。
在存储时,数据按照 Row Key 的字典序(byte order)排序存储。设计 Key 时,要充分排序存储这个特性,将经常一起读取的行存储到一起(位置相关性)。
行的一次读写是原子操作(不论一次读写多少列)。这个设计决策能够使用户很容易理解程序在对同一个行进行并发更新操作时的行为。
2、列族
HBase 表中的每个列都归属于某个列族。列族是表的 Schema 的一部分(而列不是),必须在使用表之前定义。列名都以列族作为前缀,例如 courses:history、courses:math 都属于 courses 这个列族。
访问控制、磁盘和内存的使用统计都是在列族层面进行的。在实际应用中,列族上的控制权限能帮助我们管理不同类型的应用,例如,允许一些应用可以添加新的基本数据、一些应用可以读取基本数据并创建继承的列族、一些应用则只允许浏览数据(甚至可能因为隐私的原因不能浏览所有数据)。
3、时间戳
HBase 中通过 Row 和 Columns 确定的一个存储单元称为 Cell。每个 Cell 都保存着同一份数据的多个版本。版本通过时间戳来索引,时间戳的类型是 64 位整型。时间戳可以由 HBase(在数据写入时自动)赋值,此时时间戳是精确到毫秒的当前系统时间。时间戳也 可以由客户显示赋值。如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳。每个 Cell 中,不同版本的数据按照时间倒序排序,即最新的数据排在最前面。
为了避免数据存在过多版本造成的管理(包括存储和索引)负担,HBase 提供了两种数据版本回收方式。一是保存数据的最后 n 个版本,二是保存最近一段时间内的版本(比如最近七天)。用户可以针对每个列族进行设置。
4、Cell
Cell 是由 {row key,column(=< family> + < label>),version} 唯一确定的单元。Cell 中的数据是没有类型的,全部是字节码形式存储。
物理存储
Table 在行的方向上分割为多个 HRegion,每个 HRegion 分散在不同的 RegionServer 中。
每个 HRegion 由多个 Store 构成,每个 Store 由一个 memStore 和 0 或多个 StoreFile 组成,每个 Store 保存一个 Columns Family
StoreFile 以 HFile 格式存储在 HDFS 中。
Hadoop+HBase 搭建云存储总结 PDF http://www.linuxidc.com/Linux/2013-05/83844.htm
Ubuntu Server 14.04 下 Hbase 数据库安装 http://www.linuxidc.com/Linux/2016-05/131499.htm
HBase 结点之间时间不一致造成 regionserver 启动失败 http://www.linuxidc.com/Linux/2013-06/86655.htm
Hadoop+ZooKeeper+HBase 集群配置 http://www.linuxidc.com/Linux/2013-06/86347.htm
Hadoop 集群安装 &HBase 实验环境搭建 http://www.linuxidc.com/Linux/2013-04/83560.htm
基于 Hadoop 集群的 HBase 集群的配置 http://www.linuxidc.com/Linux/2013-03/80815.htm‘
Hadoop 安装部署笔记之 -HBase 完全分布模式安装 http://www.linuxidc.com/Linux/2012-12/76947.htm
单机版搭建 HBase 环境图文教程详解 http://www.linuxidc.com/Linux/2012-10/72959.htm
HBase 的详细介绍:请点这里
HBase 的下载地址:请点这里
本文永久更新链接地址:http://www.linuxidc.com/Linux/2017-01/139173.htm
![post-qrcode](https://www.xgss.net/wp-content/uploads/2023/07/二维码-微信公众号256x256.jpg)