Hbase

HBase的理论知识

 

1 HBase的概念

HBase基于Google Bigtable实现的开源、分布式、可伸缩的列式存储数据库,诞生于Hadoop,也是Hadoop生态的重要一环,如今作为一个Apache顶级项目,早已经不能将其仅仅看作Hadoop的一部分,基于Storm,Spark等框架的数据处理方案中,都有它的身影,可以说它已经成为大数据工具箱中非常重要的一种数据存储工具,也因此必然会被很纳入很多人学习计划。

HBase的理论知识

 

Hbase的元数据放在zookeeper,真实数据放在hdfs上。

命名空间(namespace):0.96版本开始支持,是对多个表的逻辑分组,类似于关系数据库的database。

1.1 HBase 这个 NoSQL 数据库的要点

① 它介于 NoSQL 和 RDBMS 之间,仅能通过主键(rowkey)和主键的范围来检索数据

② HBase 查询数据功能很简单,不支持 join 等复杂操作

③ 不支持复杂的事务,只支持行级事务(可通过 hive 支持来实现多表 join 等复杂操作)。

④ HBase 中支持的数据类型:byte[](底层所有数据的存储都是字节数组)

⑤ 主要用来存储结构化和半结构化的松散数据。

1.2 HBase 中的表特点

1、:一个表可以有上十亿行,上百万列

2、面向列:面向列(族)的存储和权限控制,列(簇)独立检索。

3、稀疏:对于为空(null)的列,并不占用存储空间,因此,表可以设计的非常稀疏。

4、无模式:每行都有一个可排序的主键和任意多的列,列可以根据需要动态的增加,同一张表中不同的行可以有截然不同的列

HBase的理论知识

 

1.3 Rowkey的概念

Rowkey的概念和mysql中的主键是完全一样的,Hbase使用Rowkey来唯一的区分某一行的数据。

由于Hbase只支持3中查询方式:

1、基于Rowkey的单行查询

2、基于Rowkey的范围扫描

3、全表扫描

因此,Rowkey对Hbase的性能影响非常大,Rowkey的设计就显得尤为的重要。设计的时候要兼顾基于Rowkey的单行查询也要键入Rowkey的范围扫描。具体Rowkey要如何设计后续会整理相关的文章做进一步的描述。这里大家只要有一个概念就是Rowkey的设计极为重要。

rowkey 行键可以是任意字符串(最大长度是 64KB,实际应用中长度一般为 10-100bytes),最好是 16。在 HBase 内部,rowkey 保存为字节数组。HBase 会对表中的数据按照 rowkey 排序 (字典顺序)

 

1.4 HBase写数据流程

1、Client先访问zookeeper,从meta表获取相应region信息,然后找到meta表的数据

2、从namespace、表名和rowkey根据meta表的数据找到写入数据对应的region信息

3、找到对应的regionserver

4、把数据分别写到HLog和MemStore上一份

5、MemStore达到一个阈值后则把数据刷成一个StoreFile文件。(若MemStore中的数据有丢失,则可以从HLog上恢复)

6、当多个StoreFile文件达到一定的大小后,会触发Compact合并操作,合并为一个StoreFile,(这里同时进行版本的合并和数据删除。)

7、当Storefile大小超过一定阈值后,会把当前的Region分割为两个(Split),并由Hmaster分配到相应的HRegionServer,实现负载均衡

 

1.5 HBase读数据流程

1、Client先访问zookeeper,从meta表读取region的位置,然后读取meta表中的数据。meta中又存储了用户表的region信息。

2、根据namespace、表名和rowkey在meta表中找到对应的region信息

3、找到这个region对应的regionserver

4、查找对应的region

5、先从MemStore找数据,如果没有,再到StoreFile上读(为了读取的效率)。

2 HBase的RowKey设计

2.1 Rowkey长度原则

Rowkey是一个二进制码流,Rowkey的长度被很多开发者建议说设计在10~100个字节,不过建议是越短越好,不要超过16个字节。

原因如下:

(1)数据的持久化文件HFile中是按照KeyValue存储的,如果Rowkey过长比如100个字节,1000万列数据光Rowkey就要占用100*1000万=10亿个字节,将近1G数据,这会极大影响HFile的存储效率;

(2)MemStore将缓存部分数据到内存,如果Rowkey字段过长内存的有效利用率会降低,系统将无法缓存更多的数据,这会降低检索效率。因此Rowkey的字节长度越短越好。

(3)目前操作系统是都是64位系统,内存8字节对齐。控制在16个字节,8字节的整数倍利用操作系统的最佳特性。

2.2 Rowkey散列原则

如果Rowkey是按时间戳的方式递增,不要将时间放在二进制码的前面,建议将Rowkey的高位作为散列字段,由程序循环生成,低位放时间字段,这样将提高数据均衡分布在每个Regionserver实现负载均衡的几率。如果没有散列字段,首字段直接是时间信息将产生所有新数据都在一个 RegionServer上堆积的热点现象,这样在做数据检索的时候负载将会集中在个别RegionServer,降低查询效率。

2.3 Rowkey唯一原则

必须在设计上保证其唯一性。

 

问:你们公司hbase遇到过数据倾斜热点问题吗?你们是怎么解决的?

   答: 有,我们在md5的方式在row key上加上一个随机数,只要region所管理的start-end keys范围比较随机往region上写数据时就不会按照自下而上的方式写数据,而是随机的写,这样就解决了数据热点问题。

3 HBase架构组成

HBase采用Master/Slave架构搭建集群,它隶属于Hadoop生态系统,由以下类型节点组成:HMaster节点、HRegionServer节点、ZooKeeper集群,而在底层,它将数据存储于HDFS中,因而涉及到HDFS的NameNode、DataNode等,总体结构如下:

 

HBase的理论知识

HMaster与HRegionServer进行心跳感知!!!

其中

3.1 HMaster节点用于:
1、管理HRegionServer,实现其负载均衡。

2、管理和分配HRegion,比如在HRegion split时分配新的HRegion;在HRegionServer退出时迁移其内的HRegion到其他HRegionServer上。

3、实现DDL操作(Data Definition Language,namespace和table的增删改,column familiy的增删改等)。

4、管理namespace和table的元数据(实际存储在HDFS上)。

5、权限控制(ACL)。

3.2 HRegionServer节点用于:

1、存放和管理本地HRegion。

2、读写HDFS,管理Table中的数据。

3、Client直接通过HRegionServer读写数据(从HMaster中获取元数据,找到RowKey所在的HRegion/HRegionServer后)。

HRegionServer一般和DataNode在同一台机器上运行,实现数据的本地性。HRegionServer包含多个HRegion,由WAL(HLog)、BlockCache、MemStore、HFile组成。
WAL即Write Ahead Log,在早期版本中称为HLog,它是HDFS上的一个文件,如其名字所表示的,所有写操作都会先保证将数据写入这个Log文件后,才会真正更新MemStore,最后写入HFile中。采用这种模式,可以保证HRegionServer宕机后,我们依然可以从该Log文件中读取数据,Replay所有的操作,而不至于数据丢失。这个Log文件会定期Roll出新的文件而删除旧的文件(那些已持久化到HFile中的Log可以删除)。WAL文件存储在/hbase/WALs/${HRegionServer_Name}的目录中(在0.94之前,存储在/hbase/.logs/目录中),一般一个HRegionServer只有一个WAL实例,也就是说一个HRegionServer的所有WAL写都是串行的(就像log4j的日志写也是串行的),这当然会引起性能问题,因而在HBase 1.0之后,通过HBASE-5699实现了多个WAL并行写(MultiWAL),该实现采用HDFS的多个管道写,以单个HRegion为单位。关于WAL可以参考Wikipedia的Write-Ahead Logging。顺便吐槽一句,英文版的维基百科竟然能毫无压力的正常访问了,这是某个GFW的疏忽还是以后的常态?

BlockCache是一个读缓存,即“引用局部性”原理(也应用于CPU,分空间局部性和时间局部性,空间局部性是指CPU在某一时刻需要某个数据,那么有很大的概率在一下时刻它需要的数据在其附近;时间局部性是指某个数据在被访问过一次后,它有很大的概率在不久的将来会被再次的访问),将数据预读取到内存中,以提升读的性能。HBase中提供两种BlockCache的实现:默认on-heap LruBlockCache和BucketCache(通常是off-heap)。通常BucketCache的性能要差于LruBlockCache,然而由于GC的影响,LruBlockCache的延迟会变的不稳定,而BucketCache由于是自己管理BlockCache,而不需要GC,因而它的延迟通常比较稳定,这也是有些时候需要选用BucketCache的原因。这篇文章BlockCache101对on-heap和off-heap的BlockCache做了详细的比较。

HRegion是一个Table中的一个Region在一个HRegionServer中的表达一个Table可以有一个或多个Region,他们可以在一个相同的HRegionServer上,也可以分布在不同的HRegionServer上,一个HRegionServer可以有多个HRegion,他们分别属于不同的Table。

HRegion由多个Store(HStore)构成,每个HStore对应了一个Table在这个HRegion中的一个Column Family,即每个Column Family列族就是一个集中的存储单元,因而最好将具有相近IO特性的Column存储在一个Column Family列族,以实现高效读取(数据局部性原理,可以提高缓存的命中率)。HStore是HBase中存储的核心,它实现了读写HDFS功能,一个HStore由一个MemStore 和0个或多个StoreFile组成。

 

MemStore是一个写缓存(In Memory Sorted Buffer),所有数据的写在完成WAL日志写后,会写入MemStore中,由MemStore根据一定的算法将数据Flush到地层HDFS文件中(HFile),通常每个HRegion中的每个 Column Family有一个自己的MemStore。

HFile(StoreFile) 用于存储HBase的数据(Cell/KeyValue)。在HFile中的数据是按RowKey、Column Family、Column排序,对相同的Cell(即这三个值都一样),则按timestamp倒序排列。

3.3 ZooKeeper集群是协调系统,用于:
1、存放整个 HBase集群的元数据以及集群的状态信息。

2、实现HMaster主从节点的失效备援 
ZooKeeper为HBase集群提供协调服务,它管理着HMaster和HRegionServer的状态(available/alive等),并且会在它们宕机时通知给HMaster,从而HMaster可以实现HMaster之间的失效备援,或对宕机的HRegionServer中的HRegion集合的修复(将它们分配给其他的HRegionServer)。ZooKeeper集群本身使用一致性协议(PAXOS协议)保证每个节点状态的一致性。

HBase的理论知识

3.4 How The Components Work Together

ZooKeeper协调集群所有节点的共享信息,在HMaster和HRegionServer连接到ZooKeeper后创建Ephemeral节点,并使用Heartbeat机制维持这个节点的存活状态,如果某个Ephemeral节点效,则HMaster会收到通知,并做相应的处理。

HBase的理论知识

另外,HMaster通过监听ZooKeeper中的Ephemeral节点(默认:/hbase/rs/*)来监控HRegionServer的加入和宕机。在第一个HMaster连接到ZooKeeper时会创建Ephemeral节点(默认:/hbasae/master)来表示Active的HMaster,其后加进来的HMaster则监听该Ephemeral节点,如果当前Active的HMaster宕机,则该节点消失,因而其他HMaster得到通知,而将自身转换成Active的HMaster,在变为Active的HMaster之前,它会创建在/hbase/back-masters/下创建自己的Ephemeral节点。

HBase的理论知识

 

HBase Client通过RPC方式和HMaster、HRegionServer通信;一个HRegionServer可以存放1000个HRegion;底层Table数据存储于HDFS中,而HRegion所处理的数据尽量和数据所在的DataNode在一起,实现数据的本地化;数据本地化并不是总能实现,比如在HRegion移动时,需要等下一次Compact才能继续回到本地化。

Hbase中的meta表放在zookeeper里,meta表里有info元数据,当执行start-hbase.sh的时候,会将zookeeper里存放的meta表结构信息放入内存,然后将hdfs上的真实数据组合起来!!!

本着半翻译的原则,再贴一个《An In-Depth Look At The HBase Architecture》的架构图:

HBase的理论知识

这个架构图比较清晰的表达了HMaster和NameNode都支持多个热备份,使用ZooKeeper来做协调;ZooKeeper并不是云般神秘,它一般由三台机器组成一个集群,内部使用PAXOS算法支持三台Server中的一台宕机,也有使用五台机器的,此时则可以支持同时两台宕机,既少于半数的宕机,然而随着机器的增加,它的性能也会下降RegionServer和DataNode一般会放在相同的Server上实现数据的本地化。

3.5 HRegion

HBase使用RowKey将表水平切割成多个HRegion,从HMaster的角度,每个HRegion都纪录了它的有且仅有一个StartKey和有且仅有一个EndKey(第一个HRegion的StartKey为空,最后一个HRegion的EndKey为空),由于RowKey是排序的环形缓冲区进行字典排序或者是LinkedHashmap排序,每个HRegion里的RowKey是有序的,各个HRegion相对是无序的,因而Client可以通过HMaster快速的定位每个RowKey在哪个HRegion中。HRegion由HMaster分配到相应的HRegionServer中,然后由HRegionServer负责HRegion的启动和管理,和Client的通信,以及负责数据的读(使用HDFS)。每个HRegionServer可以同时管理1000个左右的HRegion(这个数字怎么来的?没有从代码中看到限制,难道是出于经验?超过1000个会引起性能问题?

来回答这个问题:感觉这个1000的数字是从BigTable的论文中来的(5 Implementation节):Each tablet server manages a set of tablets(typically we have somewhere between ten to a thousand tablets per tablet server))。
HBase的理论知识

4 META表结构

在 HBase Shell 里对meta表进行 scan 和 describe :

HBase的理论知识

 

 

可以看出,meta表的结构如下:

HBase的理论知识

 

meta表中每一行记录了一个Region的信息。

1) RowKey

RowKey就是Region Name,它的命名形式是TableName,StartKey,TimeStamp.Encoded.

其中 Encoded 是TableName,StartKey,TimeStamp的md5值。

例如:

mytable,,1438832261249.ea2b47e1eba6dd9a7121315cdf0e4f67.

表名是mytable,StartKey为空,时间戳是1438832261249,前面三部分的md5是:

$ echo -n "mytable,,1438832261249" | md5sum   # -n选项表示不输出换行符

ea2b47e1eba6dd9a7121315cdf0e4f67  -

2) Column Family

.META.表有两个Column Family:info 和 historian

其中info包含了三个Column:

  • regioninfo:region的详细信息,包括StartKey、EndKey以及Table信息等等。
  • server:管理该region的 RegionServer 的地址。
  • serverstartcode:RegionServer 开始托管该region的时间。

至于historian

That was a family used to keep track of region operations like open, 
close, compact, etc. It proved to be more troublesome than handy so we 
disabled this feature until coming up with a better solution. The 
family stayed for backward compatibility.

大致的意思是:这个Column Family是用来追踪一些region操作的,例如open、close、compact等。事实证明这非常的麻烦,所以在想出一个更好的解决方案之前我们禁用了此功能。这个列族会保持向后兼容。

综上所述.META.表中保存了所有用户表的region信息,在进行数据访问时,它是必不可少的一个环节。当Region被拆分、合并或者重新分配的时候,都需要来修改这张表的内容来保证访问数据时能够正确地定位region。

5 进入HBase命令行

hbase shell 进入命令行模式

6 过滤器

1、SingleColumnValueFilter

SingleColumnValueFilter 用于测试值的情况(相等,不等,范围 、、、)

2、SingleColumnValueExcludeFilter

跟SingleColumnValueFilter 功能一样,只是不查询出该列的值。

3、FamilyFilter

用于过滤列族(通常在 Scan 过程中通过设定某些列族来实现该功能,而不是直接使用该过滤器)。

4、QualifierFilter

用于列名(Qualifier)过滤

5、ColumnPrefixFilter 

用于列名(Qualifier)前缀过滤,即包含某个前缀的所有列名。

6、RowFilter 

行键过滤器,一般来讲,执行 Scan 使用 startRow/stopRow 方式比较好,而 RowFilter 过滤器也可以完成对某一行的过滤。

7、RandomRowFilter

该过滤器是随机选择一行的过滤器。参数 chance 是一个浮点值,介于 0.1 和 1.0 之间。

8、PageFilter

用于按行分页。

相关文章:

  • 2021-11-25
  • 2021-07-08
  • 2022-01-01
  • 2021-08-20
  • 2021-05-03
  • 2021-04-21
  • 2021-04-27
猜你喜欢
  • 2021-09-04
  • 2021-11-07
  • 2021-04-17
  • 2021-12-18
  • 2021-06-11
  • 2021-12-12
  • 2021-11-30
相关资源
相似解决方案