Hadoop相关知识整理系列之一:HBase基本架构及原理

1. HBase框架简单介绍

HBase是一个分布式的、面向列的开源数据库,它不一样于通常的关系数据库,是一个适合于非结构化数据存储的数据库。另外一个不一样的是HBase基于列的而不是基于行的模式。HBase使用和 BigTable很是相同的数据模型。用户存储数据行在一个表里。一个数据行拥有一个可选择的键和任意数量的列,一个或多个列组成一个ColumnFamily,一个Fmaily下的列位于一个HFile中,易于缓存数据。表是疏松的存储的,所以用户能够给行定义各类不一样的列。在HBase中数据按主键排序,同时表按主键划分为多个Region。数据库

在分布式的生产环境中,HBase 须要运行在 HDFS 之上,以 HDFS 做为其基础的存储设施。HBase 上层提供了访问的数据的 Java API 层,供应用访问存储在 HBase 的数据。在 HBase 的集群中主要由 Master 和 Region Server 组成,以及 Zookeeper,具体模块以下图所示:缓存

简单介绍一下 HBase 中相关模块的做用:服务器

  • Master
    HBase Master用于协调多个Region Server,侦测各个RegionServer之间的状态,并平衡RegionServer之间的负载。HBaseMaster还有一个职责就是负责分配Region给RegionServer。HBase容许多个Master节点共存,可是这须要Zookeeper的帮助。不过当多个Master节点共存时,只有一个Master是提供服务的,其余的Master节点处于待命的状态。当正在工做的Master节点宕机时,其余的Master则会接管HBase的集群。
  • Region Server
    对于一个RegionServer而言,其包括了多个Region。RegionServer的做用只是管理表格,以及实现读写操做。Client直接链接RegionServer,并通讯获取HBase中的数据。对于Region而言,则是真实存放HBase数据的地方,也就说Region是HBase可用性和分布式的基本单位。若是当一个表格很大,并由多个CF组成时,那么表的数据将存放在多个Region之间,而且在每一个Region中会关联多个存储的单元(Store)。
  • Zookeeper
    对于 HBase 而言,Zookeeper的做用是相当重要的。首先Zookeeper是做为HBase Master的HA解决方案。也就是说,是Zookeeper保证了至少有一个HBase Master 处于运行状态。而且Zookeeper负责Region和Region Server的注册。其实Zookeeper发展到目前为止,已经成为了分布式大数据框架中容错性的标准框架。不光是HBase,几乎全部的分布式大数据相关的开源框架,都依赖于Zookeeper实现HA。

2. Hbase数据模型

2.1 逻辑视图

基本概念:网络

  • RowKey:是Byte array,是表中每条记录的“主键”,方便快速查找,Rowkey的设计很是重要;
  • Column Family:列族,拥有一个名称(string),包含一个或者多个相关列;
  • Column:属于某一个columnfamily,familyName:columnName,每条记录可动态添加;
  • Version Number:类型为Long,默认值是系统时间戳,可由用户自定义;
  • Value(Cell):Byte array。

2.2 物理模型:

  • 每一个column family存储在HDFS上的一个单独文件中,空值不会被保存。
  • Key 和 Version number在每一个column family中均有一份;
  • HBase为每一个值维护了多级索引,即:<key, columnfamily, columnname, timestamp>;
  • 表在行的方向上分割为多个Region;
  • Region是Hbase中分布式存储和负载均衡的最小单元,不一样Region分布到不一样RegionServer上。
  • Region按大小分割的,随着数据增多,Region不断增大,当增大到一个阀值的时候,Region就会分红两个新的Region;
  • Region虽然是分布式存储的最小单元,但并非存储的最小单元。每一个Region包含着多个Store对象。每一个Store包含一个MemStore或若干StoreFile,StoreFile包含一个或多个HFile。MemStore存放在内存中,StoreFile存储在HDFS上。

疑问:每个Region都只存储一个ColumnFamily的数据,而且是该CF中的一段(按Row的区间分红多个 Region)?这个须要查证,每一个Region只包含一个ColumnFamily能够提升并行性?然而,我只知道每一个Store只包含一个ColumnFamily的数据。负载均衡

2.3 ROOT表和META表

HBase的全部Region元数据被存储在.META.表中,随着Region的增多,.META.表中的数据也会增大,并分裂成多个新的Region。为了定位.META.表中各个Region的位置,把.META.表中全部Region的元数据保存在-ROOT-表中,最后由Zookeeper记录-ROOT-表的位置信息。全部客户端访问用户数据前,须要首先访问Zookeeper得到-ROOT-的位置,而后访问-ROOT-表得到.META.表的位置,最后根据.META.表中的信息肯定用户数据存放的位置,以下图所示。
框架

-ROOT-表永远不会被分割,它只有一个Region,这样能够保证最多只须要三次跳转就能够定位任意一个Region。为了加快访问速度,.META.表的全部Region所有保存在内存中。客户端会将查询过的位置信息缓存起来,且缓存不会主动失效。若是客户端根据缓存信息还访问不到数据,则询问相关.META.表的Region服务器,试图获取数据的位置,若是仍是失败,则询问-ROOT-表相关的.META.表在哪里。最后,若是前面的信息所有失效,则经过ZooKeeper从新定位Region的信息。因此若是客户端上的缓存所有是失效,则须要进行6次网络来回,才能定位到正确的Region。分布式

一个完整分布式的HBase的组成示意图以下,后面咱们再详细谈其工做原理。
大数据

3. 高可用

3.1 Write-Ahead-Log(WAL)保障数据高可用

咱们理解下HLog的做用。HBase中的HLog机制是WAL的一种实现,而WAL(通常翻译为预写日志)是事务机制中常见的一致性的实现方式。每一个RegionServer中都会有一个HLog的实例,RegionServer会将更新操做(如 Put,Delete)先记录到 WAL(也就是HLo)中,而后将其写入到Store的MemStore,最终MemStore会将数据写入到持久化的HFile中(MemStore 到达配置的内存阀值)。这样就保证了HBase的写的可靠性。若是没有 WAL,当RegionServer宕掉的时候,MemStore 尚未写入到HFile,或者StoreFile尚未保存,数据就会丢失。或许有的读者会担忧HFile自己会不会丢失,这是由 HDFS 来保证的。在HDFS中的数据默认会有3份。所以这里并不考虑 HFile 自己的可靠性。线程

HFile由不少个数据块(Block)组成,而且有一个固定的结尾块。其中的数据块是由一个Header和多个Key-Value的键值对组成。在结尾的数据块中包含了数据相关的索引信息,系统也是经过结尾的索引信息找到HFile中的数据。翻译

3.2 组件高可用

  • Master容错:Zookeeper从新选择一个新的Master。若是无Master过程当中,数据读取仍照常进行,可是,region切分、负载均衡等没法进行;
  • RegionServer容错:定时向Zookeeper汇报心跳,若是一旦时间内未出现心跳,Master将该RegionServer上的Region从新分配到其余RegionServer上,失效服务器上“预写”日志由主服务器进行分割并派送给新的RegionServer;
  • Zookeeper容错:Zookeeper是一个可靠地服务,通常配置3或5个Zookeeper实例。

4. HBase读写流程

上图是RegionServer数据存储关系图。上文提到,HBase使用MemStore和StoreFile存储对表的更新。数据在更新时首先写入HLog和MemStore。MemStore中的数据是排序的,当MemStore累计到必定阈值时,就会建立一个新的MemStore,而且将老的MemStore添加到Flush队列,由单独的线程Flush到磁盘上,成为一个StoreFile。与此同时,系统会在Zookeeper中记录一个CheckPoint,表示这个时刻以前的数据变动已经持久化了。当系统出现意外时,可能致使MemStore中的数据丢失,此时使用HLog来恢复CheckPoint以后的数据。
StoreFile是只读的,一旦建立后就不能够再修改。所以Hbase的更新实际上是不断追加的操做。当一个Store中的StoreFile达到必定阈值后,就会进行一次合并操做,将对同一个key的修改合并到一块儿,造成一个大的StoreFile。当StoreFile的大小达到必定阈值后,又会对 StoreFile进行切分操做,等分为两个StoreFile。

4.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的高机能。

4.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

其它相关内容待补充