HBase工作原理

1 HBase概述

(1)HBase的定义
      HBase:Hadoop Database,是一个高可靠、高性能、面向列、可伸缩、实时读写的分布式数据库。利用HBase技术可在廉价的PC Server上搭建大规模结构化存储集群。
      ① 高可靠:数据高可靠性:HBase利用Hadoop HDFS作为其文件存储系统;服务高可靠性:HBase利用Zookeeper作为协同服务。
      ② 高性能:传统关系型数据库在上亿条数据中查询时,速度极其慢。相比之下,HBase在上亿行、上百万列、上万个版本的数据上做查询时,速度要远高于传统关系型数据库。
      ③ 面向列:与传统数据库按行存储数据的方式不同,HBase是按列存储数据。
      ④ 可伸缩:HBase的集群节点数量可多可少。
      ⑤ 实时读写:HBase的读写时间是毫秒级的。
(2)HBase与BigTable的对比
      ① HBase是Google BigTable的开源实现,与Google BigTable利用GFS作为其文件存储系统类似,HBase利用Hadoop HDFS作为其文件存储系统;
      ② Google运行MapReduce来处理BigTable中的海量数据,HBase同样利用Hadoop MapReduce来处理HBase中的海量数据;
      ③ Google BigTable利用Chubby作为协同服务,HBase利用Zookeeper作为协同服务。
(3)HBase存储什么格式的数据
      HBase主要用来存储非结构化和半结构化的松散数据(列存NoSQL数据库)。
(4)HBase与HDFS的对比
HBase工作原理
1)相同点:两者都具有良好的容错性和扩展性,都可以扩展到成百上千个节点。
2)HDFS适合的场景:
      ① 不支持数据随机查找;
      ② 不适合增量数据(新增的数据)处理;
      ③ 不支持数据更新。
3)HBase表的特点
      ① 大:一个表可以有数十亿行,上百万列;
      ② 无模式:每行都有一个可排序的主键和任意多的列,列可以根据需要动态的增加,同一张表中不同的行可以有截然不同的列;
      ③ 面向列:面向列(族)的存储和权限控制,列(族)独立检索;
      ④ 稀疏:对于空(null)的列,并不占用存储空间,表可以设计的非常稀疏;
      ⑤ 数据多版本:每个单元中的数据可以有多个版本,默认情况下版本号自动分配,是单元格插入时的时间戳;
      ⑥ 数据类型单一:HBase中数据都是字符串,没有类型。
(5)列存储与行存储
1)传统行式数据库
      ① 数据是按行存储的;
      ② 没有索引的查询使用大量I/O;
      ③ 建立索引和物化视图需要花费大量时间和资源;
      ④ 面向查询的需求,数据库必须被大量膨胀才能满足性能要求,即当查询某些列的时候,需要将所有的行加载,数据库会被大量膨胀,才能满足查询要求。
2)列式数据库
      ① 数据时按列存储,每一列单独存放在一块;
      ② 数据即是索引,换句话说某一列的内容都存在一块,找到这个块就可以;
      ③ 不用全行扫描,只需访问查询涉及的列,可以大量降低系统I/O;
      ④ 每一列由一个线程来处理,有利实现多线程并发处理;
      ⑤ 数据类型一致,数据特征相似,可以进行高效的压缩。
(6)关系型数据库与HBase比较
HBase工作原理
      HBase非常容易地建立“二级缓存”,执行复杂的内连接和外连接,执行计数(使用HTable 的incrementColumnValue()方法以后,计数器每秒可以实现数千次更新)求和、排序、分组等操作,或对表、行和列中的数据进行分页存放。

2 HBase数据模型HBase工作原理

(1)Row Key
      ① 字节数组(byte array),只能存储64k的字节数据;
      ② 表中每条记录的主键;
      ③ 方便快速查找。
(2)column family(列族)和column(列)
      ① HBase表中的每个列都归属于某个列族,列族必须作为表模式(schema)定义的一部分预先给出。如:create ‘test’.’course’;
      ② 列名以列族作为前缀,每个列族都可以有多个列成员(column);如course:math,course:english,新的列族成员(列)可以随后按需、动态加入;
      ③ 权限控制、存储以及调优都是在列族层面进行的(column本身就是),更准确地说HBase是面向列族存储的;
      ④ HBase把同一列族里面的数据存储在同一目录下,由几个文件保存;
      ⑤ Hbase官方文档中写明,目前列族数量最优不超过3个。
(3)TimeStamp时间戳
      ① 在HBase每个cell(单元格)存储单元对同一份数据有多个版本,根据唯一的时间戳来区分每个版本之间的差异,不同版本的数据按照时间倒序排序,最新的数据版本排在最前面;
      ② 时间戳的类型时64位整型;
      ③ 时间戳可以由HBase(在数据写入时自动)赋值,此时时间戳是精确到毫秒的当前系统时间;
      ④ 时间戳也可以由客户显示赋值,如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳。
      ⑤ 用户可以指定每个值所能保存的最大版本数量,也可以添加条件,如:保存一周内的值。
(4)cell单元格
      ① 由行和列的坐标交叉决定;
      ② 单元格是有版本的;
      ③ 单元格的内容时未解析的字节数组:
      ④ 由{row key,column(=+),version}唯一确定的单元。Cell中的数据是没有类型的,全部是字节码形式存储。

3 HBase基本架构 HBase工作原理

(1)Client
      包含访问HBase的接口,并维护cache来加快对HBase的访问。
(2)Zookeeper
      ① 保证任何时候,集群中只有一个Master;
      ② 存储所有Region的寻址入口;
      ③ 实时监控Region server的上线和下线信息,并实时通知Master;
      ④ 存储HBase的schema和table元数据。
(3)Master
      ① 为Region server分配region;
      ② 负责Region server的负载均衡;
      ③ 发现失效的Region server并重新分配其上的region;
      ④ 管理用户对table的增删改操作;
      ⑤ HDFS上的垃圾文件回收。
(4)Region server
      ① Region server维护region,处理对这些region的IO请求;
      ② Region server负责切分在运行过程中变得过大的region。
(5)Region
      ① HBase自动把表水平划分成多个区域(region),每个region会保存一个表里面某段连续的数据;每个表一开始只有一个region,随着数据不断插入表,region不断增大,当增大到一个阈值(默认256M)的时候,region就会被Region server等分成两个新的region(裂变),而region的分配由Master管理; HBase工作原理
      ② 当table中的行不断增多,就会有越来越多的region。这样一张完整的表被保存在多个Region server上;
      ③ region虽然是HBase中分布式存储和负载均衡的最小单元,但不是存储的最小单元,region有一个或者多个store组成。
HBase工作原理
(6)Store
      ① 每个store保存一个列族,如果有几个列族就有几个store;
      ② 每个store由一个MemStore和0至多个storefile组成;
      ③ HBase以store的大小来判断是否需要切分region。
(7)MemStore
      MemStore是放在内存里的,保存修改的数据即key-values。当MemStore的大小达到一个阈值(默认64M)时, Region server回启动flash cache进程将MemStore中的数据写入storefile,每次写入形成单独的一个storefile。
(8)StoreFile
      ① MemStore内存中的数据写到文件后就是StoreFile,StoreFile底层是以HFile的格式保存;
      ② 当storefile文件的数量增长到一定阈值后,系统会进行合并,在合并过程中会进行版本合并和删除工作,形成更大的storefile。
(9)HFile
      HBase中KeyValue数据的存储格式,是Hadoop的二进制格式文件。所以Hadoop不知道HBase存储的是什么,只知道是二进制文件(HFile是存储在HDFS上的)。
      HFile文件是不定长的,长度固定的只有其中的两块:Trailer和FileInfo。
      Trailer中有指针指向其他数据块的起始点;
      FileInfo记录了文件的一些元数据信息;
      Index块记录Data和Meta块的偏移量;
      Data块是HBase IO的基本单元为了提高效率,Region server中有基于LRU(Least Recently Used,最近最少使用)的Block Cache机制。每个Data块的大小可以在创建一个Table的时候通过参数指定(默认块大小64KB),大号的Block有利于顺序扫描,消耗的Block利于随机查询。每个Data除了开头的Magic以外就是一个个keyvalue对拼接而成,Magic内容是一些随机数字,目的是防止数据损坏。
HBase工作原理

HFile结构图

HBase工作原理

KeyValue格式图

      Data块段用来保存表中的数据,这部分可以被压缩;
      Meta块段(可选的)用来保存用户自定义的keyvalue段,可以被压缩;
      FileInfo段用来保存HFile的元信息,不能被压缩,用户也可以在这一部分添加自己的元信息;
      Data Index段(可选的)用来保存Meta块的索引;
      Trailer这一段是定长的,保存了每一段的偏移量;
      读取一个HFile时,会首先读取Trailer,Trailer保存了每个段的起始位置(段的Magic Number用来做安全check),然后,Data Index会被读取到内存中,这样,当检索某个key时,不需要扫描整个HFile,而只需从内存中找到key所在的块,通过一次磁盘IO将整个块读取到内存中,再找到需要的key;
      HFile的Data Block,Meta Block通常采用压缩方式存储,压缩之后可以大大减少网络IO和磁盘IO,随之而来的开销当然是需要花费CPU进行压缩和解压缩。(备注: DataBlock Index的缺陷。 a) 占用过多内存 b) 启动加载时间缓慢)
(10)HLog
       有多少个region就有多少个HLog。
(11)LogFlusher
      定期的将缓存中信息写入到日志文件中。
(12)LogRoller
      对日志文件进行管理维护。

4 Region定位

HBase工作原理
(1)ROOT
      记录了META表的region信息,ROOT只有一个region,因此永远不会被分割。
(2)META
      ① 记录了用户创建的表的region信息,META可以有多个regoin;
      ② 为了加快访问速度,META表的所有Region全部保存在内存中。
(3)ZooKeeper
      ZooKeeper中记录了ROOT表的location。
(4)Client访问region的顺序
      1) 正常访问:Client访问用户数据之前需要首先访问ZooKeeper,然后访问ROOT表,接着访问META表,最后才能找到用户数据的位置去访问。
      2) 异常访问:客户端会将查询过的位置信息缓存起来,且缓存不会主动失效。如果客户端根据缓存信息还访问不到数据,则询问相关META表的RegionServer,试图获取数据的位置,如果还是失败,则询问ROOT表相关的META表在哪里。最后,如果前面的信息全部失效,则通过ZooKeeper重新定位Region的信息。所以如果客户端上的缓存全部是失效,则需要进行6次网络来回,才能定位到正确的Region。
(5)在新的版本中,ROOT表已经被移除了,将Meta表存储在ZooKeeper中。

5 HBase读写流程

5.1 写操作流程

(1)Client通过ZooKeeper的调度,向RegionServer发出写数据请求,在Region中写数据;
(2)数据被写入Region的MemStore,直到MemStore达到预设阈值;
(3)MemStore中的数据被Flush成一个StoreFile;
(4)随着StoreFile文件的不断增多,当其数量增长到一定阈值后,触发Compact合并操作,将多个StoreFile合并成一个StoreFile,同时进行版本合并和数据删除;
(5)StoreFiles通过不断地Compact合并操作,逐步形成越来越大的StoreFile;
(6)单个StoreFile大小超过一定阈值后,触发Split操作,把当前Region Split成2个新的Region。父Region会下线,新Split出的2个子Region会被HMaster分配到相应的RegionServer上,使得原先1个Region的压力得以分流到2个Region上。
      可以看出HBase只有增添数据,所有的更新和删除操作都是在后续的Compact合并历程中进行的,使得用户的写操作只要进入内存就可以立刻返回,实现了HBase I/O的高机能。

5.2 读操作流程

(1)Client访问ZooKeeper,查找ROOT表,获取META表信息;
(2)从META表查找,获取存放目标数据的Region信息,从而找到对应的RegionServer;
(3)通过RegionServer获取需要查找的数据;
(4)Regionserver的内存分为MemStore和BlockCache两部分,MemStore主要用于写数据,BlockCache主要用于读数据。读请求先到MemStore中查数据,查不到就到BlockCache中查,再查不到就会到StoreFile上读,并把读的结果放入BlockCache。
      寻址过程:Client–>ZooKeeper–>(ROOT表)–>META表–>RegionServer–>Region–>Client

6 HBase容错性

(1)WAL保证数据高可用
      WAL(Write-Ahead-Log)用来做灾难恢复使用,HLog记录数据的所有变更,一旦region server 宕机,就可以从log中进行恢复
(2)Master容错:Zookeeper重新选择一个新的Master
      ① 无Master过程中,数据读取仍照常进行;
      ② 无master过程中,region切分、负载均衡等无法进行。
(3)RegionServer容错:定时向Zookeeper汇报心跳,如果一旦时间内未出现心跳
      ① Master将该RegionServer上的Region重新分配到其他RegionServer上;
      ② Master将该RegionServer上的Region重新分配到其他RegionServer上。
(4)ZooKeeper容错:ZooKeeper是一个可靠地服务
      ① 默认情况下,HBase管理ZooKeeper实例(例如:启动或者停止ZooKeeper);
      ② Master与RegionServer启动时会向ZooKeeper注册;
      ③ Zookeeper的引入使得Master不再是单点故障;
      ④ 一般配置3或5个Zookeeper实例。

参考文章:
[1]《Hadoop权威指南》
[2]《HBase权威指南》
[3] Apache HBase ™ Reference Guide
[4] https://www.cnblogs.com/steven-note/p/7209398.html
[5] https://blog.bcmeng.com/post/hbase-hdfs.html