想快速了解HBase,了解这些就够了
1.写这篇文章的缘由
首先Hbase 在大数据存储和数据查询方面有着比较优秀的表现,它的技术架构和底层存储值得每个大数据从业者学习和借鉴,其次在用户画像标签和实时计算场景中经常会被用到,也是面试官在面试中经常问到的大数据组件之一,因此有必要整理一些HBase的基础内容供大家了解。
Hbase起源最早可追溯到Google奠定大数据基础的三驾马车之一Bigtable,是一种分布式NoSQL 数据库实现,可以看做是Hadoop的Database,底层采用java语言编写。
关于HBase在Hadoop 生态中的位置,我们可以这样对比理解。Google Bigtable 利用 GFS作为文件存储系统,Hbase利用Hadoop HDFS作为文件存储系统。Google 运行MapReduece来处理Bigtable中海量数据,HBase 同样可以用于MapReduce。Google Bigtable 利用Chubby作为协调服务,Hbase利用开源的Zookeeper作为协调服务。
既然Hbase是一种Nosql数据库,那我们自己就联想到和关系型数据库的对比,以MySQL关系数据库为例子,它们之间有很多的区别,HBase是列存储的,列是非固定的,多个列存储在一起称为列簇。我们以用户画像数据对比说明下。
Mysql 存储:
HBase存储: rowkey : substr(md5(uid),1,4) + uid
HBase 中数据存储模型可以简化为下面这样:
在HBase中,每个单元(cell) 由五元组(RowKey, Column Family, Qualifier, Timestamp, Value)组成的结构,其中 type 表示 Put/Delete 这样的操作类型, timestamp 代表这个 cell 的版本。这个结构在数据库中实际是以 KV 结构存储的,其中(RowKey, Column Family, Qualifier, Timestamp)是 K , Value 字段对应 KV 结构的 V 。
Row Key(行键) :标识了HBase表中的一行,相当于关系型数据库中的主键,Row Key 是字典有序的,HBase 基于Row Key 建立索引,RowKey是每个Cell的唯一定位符。
Column Family(列簇):是一组逻辑相关的列的集合。列簇是在创建表时定义,数据是按列族存储和管理的。每个列族都将其数据存储在HBase服务器文件系统的同一个目录下。
Column Qualifier(列修饰符):具体的列,属于某一个列簇,可以动态添加,以用来进一步细分列族下的数据。
Tmestamp(时间戳):是cell数据的版本控制。当一个cell的值被更新时,会保留之前的旧值,并给新值分配一个新的时间戳,缺省情况下是数据写入的时间。HBase可以根据时间戳检索特定版本的数据。
Value(单元值): 指的是存储在特定行键、列族和列限定符下的数据本身。
HBase 架构中包括HMaster 和RegionServer、ZooKeeper、Client几个模块,他们之间的关系如下图。
HMaster:不参与数据读写,执行表的DDL操作,分配Regin到具体的Region Server。上报最新的元数据存储地址信息到ZooKeeper中。
Region Server:管理着Region ,参与数据的读写,是HBase 中数据节点,存储具体的数据,同时也存档Hbase:meta信息的存储,在client第一次访问时,会通过zookeeper获取其地址并访问。
ZooKeeper:协调中心。负责 Master 选举,节点协调,存储 hbase:meta 等元数据,供client 第一次访问时读取。
Client: 客户端访问Region Server数据,只需要知道ZooKeeper的地址。
HDFS:底层存储系统。负责存储数据,Region 中的数据通过 HDFS 进行存储。
上面主要是存逻辑角度说明,在HBase中逻辑和物理角度的概念还不太一样,下面做下对比。
逻辑结构 | 物理结构 |
Region Server | HRegion Server |
Region | HRegion |
CF(Column Qualifier) | HStore(这里指的是Store) |
上图显示了各个模块之间的数据流转,那么模块之间是如何协作的,我们可以把HMaster的角色称为老板,其他BackUp Masters角色是二老板、三老板;ZooKeeper的角色是秘书,Region Server的角色是员工,Client的角色是客户。我们可以通过三个问题来了解模块之间的协作过程。
场景:早上去公司上班打卡
当Hbase启动时,注册到ZooKeeper,(注册到backup master节点, 为啥是backup master,因为其他节点也要注册成功为backup master节点,只有抢占成功,才会删除backup master节点,成为active master之后,才会实例化一些类,如MasterFileSystem,ServerManager,TableStateManager等),等待Region Server汇报。
Region Server(HBase的运行进程)注册到ZooKeeper,并向HMaster汇报(上班打卡), 老板就拿到了一份清单(谁正常来上班了,谁没有请假就无故旷工了,谁打了卡人却不知道跑哪去了)。
对各个Region Server(包括失效的)的数据进行整理,分配Region和Meta信息(记录了所有表相关的region(最小的负载单元), 各个Region Server负责哪些数据,就把这张表交给自己的秘书ZK,然后告诉ZK,没什么事就别老烦我,自己就和二老板、三老板们喝茶去了,于是其他的backup master会定期的从HMaster处保持数据的更新,以保证自己的Meta表是最新的)。
Region Server作为员工注册到集群后,有很多工作要做,比如设置WAL预写日志相关信息,定期的刷新MemStore,保证数据最终写入到HFile文件。有时候还有负责接待ZK介绍过来的客户,配合这些客户读取或者写入数据。
场景:RegionServerA 怒吼老板自己去喝茶,也不给我涨工资,老子不干了。ZK作为秘书一看有员工罢工了,赶紧跟老板汇报,老板心想一个小小的员工还能翻天,直接把Meta表中的RegionServerA划掉,告诉他可以直接找财务领工资走人了 。
HMaster将失效的RegionServerA上的Region分配到RegionServerB的节点;
HMaster把更新后hbase:meta表交给自己的秘书ZK以保证数据可以正常访问 。
所以RegionServerA 罢工了,丝毫不影响集群的正常运行。
场景:老板要去三亚旅游,你们该干啥干啥,然后做飞机就走了。
如果配置了HA, 这个时候ZK会从其他的backup master(二老板、三老板们)中推选出一个转成active状态。
如果没有配置HA,作为员工的Region Server也只能羡慕羡慕, 当客户通过ZK介绍过来,Region Server还需要接待客户,还得照样配合这些客户读取或者写入数据,过着苦逼的生活。但是如果这个时候客户提出了新的要求,比如新建一个表,或者说这张表的结构我需要改改,这个时候ZK会说我们老板不在,你晚点再来吧。然后给客户抛了一个异常。
所以如果没有配置HA ,数据可以正常读写,但是不能创建删除表,也不能更改表结构。因为这些操作涉及到Meta表的更新,而HMaster处于失效状态的。
为了更好的理解,画了一个table视角的存储结构对比,用于说明相互之间的逻辑联系。
HRegionServer HBase的运行进程,在HBase集群中为一个节点,复制处理Client的IO 请求。
HLog Client 提交写入数据时,会同时写入HLog和MemStore,写入HLog是为了保证高可用。
HStore 最小的存储单元。最大值10G,如果大于10G会进行分裂。由MemStore和HFile组成。
HRegion 最小的负载单元。
MemStore 存储在内存中,最大值128M。超过这个最大值就会进行刷盘到StoreFile。
HFile StoreFile落盘后形成的HDFS文件,会通过DFS Client上传到Hadoop的HDFS DataNode中。HFIle文件存储在/hbase/WALs和/hbase/oldWALs文件夹下。其中,/hbase/oldWALs为过期日志
。从上图的表述中可以很清晰的看到下面两点信息。
一个Rowkey Ranage 对应的是一个Region。一个table 可能有多个Region,但每一个RowKey 一定只属于某一个Region。
一个列簇对应一个Store。一个RowKey的列簇的可能分布在不同的Store中,但一定同一个Region中
。HFile文件主要分为4个部分:Scanned block部分、Non-scanned block部分、Load-on-open部分和Trailer,如图所示。
Scanned block部分,表示顺序扫描HFile时所有的数据块将被读取;该部分包含3种数据块,DataBlock:存储用户的KeyValue数据,LeafIndex Block:存储索引树的叶子节点数据,Bloom Block:存储布隆过滤器相关数据。
Non-scanned block部分,表示在HFIle顺序扫描时不会被读取的布恩,包括Meta Block 和 Intermediate Level Data Index Blocks部分。
Load-on-open部分,这部分数据会在RegionServer打开Hfile时直接加载到内存中,包括FileInfo、布隆过滤器MetaBlock、Root Data Index 和Meta INdexBlock。
Trailer部分,这部分主要记录了HFile的版本信息,其他各个部分的偏移值和寻址信息。
在RegionServer中,有一个Hlog或者多个;每个HLog是多个Region共享的。Hlog日志单元为WALEntry,其标示一次行级更新的最小追加单元,由HlogKey和WALEdit两部分组成。如下图所示。
HLogKey 由sequenceId、writeTime、clusterId、regionName以及tableName组成。
sequenceId 日志写入时分配给数据的一个自增数字,先写入的日志数据sequenceId小,后写入的sequenceId大。可以根据sequenceId值判断数据是否已经刷盘
WALEdit 标示一个事务中的更新集合,在0.94版本之后,Hbase将同一个行级事务的写入操作标示为一条记录。如,我们在一个事务中对于一行 R的三列c1、c2 、c3分别做了修改,在0.94的版本中,Hlog中会有3条记录;在0.94后的版本中,Hlog中仅由一条记录,具体如下表
:版本 | HlogKey | WALEdit |
<0.94 | <logseq1-for-edit1> | <keyvalue-for-edit-c1> |
<keyvalue-for-edit-c2> | ||
<keyvalue-for-edit-c3> | ||
>=0.94 | <logseq1-for-edit1> | <WALEdit-for-entire-txn> |
Hlog 存储在HDFS指定目录下,/hbase/WALs下由多个子目录,每个子目录代表一个RegionServer。
MemStore使用跳表数据结构。底层采用两个Java 的ConcurrentSkipListMap实现,当一个ConcurrentSkipListMap 存储值超过最大阀值时,会启用另一个ConcurrentSkipListMap接受写入操作,并对超过阀值的ConcurrentSkipListMap执行刷盘操作。
HFile文件由各种不同类型的Block构成,如图所示。Block块可以通过blockSize指定,大号的block利于大规模顺序扫描,小号的block利于随机查询。Hfile中所有Block都拥有相同的数据结构,Hbase将所有Block统一抽象为HFile-Block。
涤生大数据往期精彩推荐
8.SQL之优化篇:一文搞懂如何优化线上任务性能,增效降本!
10.基于FlinkSQL +Hbase在O2O场景营销域实时数仓的实践
12.涤生大数据实战:基于Flink+ODPS历史累计计算项目分析与优化(一)
13.涤生大数据实战:基于Flink+ODPS历史累计计算项目分析与优化(二)
14.5分钟了解实时车联网,车联网(IoV)OLAP 解决方案是怎样的?
15.企业级Apache Kafka集群策略:Kakfa最佳实践总结