一图看懂 HBase 架构(全面详细)

HBase

一图看懂 HBase 架构

HBase 最常用的shell操作

HBase 工作机制及读写流程



前言

本篇博客,为大家梳理 HBase 的组件架构和底层原理。希望能对 HBase 感兴趣/想了解的同学有所帮助。 同时也希望有发现内容不正确或者有疑问的地方,望指明,一起探讨,学习,进步。


HBase 简介

什么是HBase

HBase是 Google 的 Bigtable 开发的java版本。是一个建立在 HDFS 之上,面向列的针对结构化数据的可伸缩、高可靠、高性能、分布式和面向列的动态模式(实时读写nosql)数据库。

HBase是列式NoSql数据库。Hbase中仅支持的数据类型为byte[];它主要用来存储结构化和半结构化的松散数据。

HBase可以理解为一个非常大的分布式HashMap,在hadoop集群的各个节点中以行主键+列族(包含列)+时间戳为键,以储存的值为值。

与hadoop一样,Hbase主要依靠横向扩展,通过不断增加廉价的商用服务器,来增加计算和存储能力。

HBase 特点

HBase中的表一般有这样的特点:

  • 大:一个表可以有上十亿行,上百万列
  • 面向列:面向列(族)的存储和权限控制,列(族)独立检索。
  • 稀疏:对于为空(null)的列,并不占用存储空间,因此,表可以设计的非常稀疏。

HBase的特点:

  • 海量存储
    Hbase适合存储PB级别的海量数据,在PB级别的数据以及采用廉价PC存储的情况下,能在几十到百毫秒内返回数据;同时能够达到随机读取20~100k ops/s(每秒操作次数)的速度。这与Hbase的极易扩展性息息相关。正式因为Hbase良好的扩展性,才为海量数据的存储提供了便利。

  • 列式存储
    这里的列式存储其实说的是列族存储,Hbase是根据列族来存储数据的。列族下面可以有非常多的列,列族在创建表的时候就必须指定。需要注意的是,列族理论上可以很多,但实际上建议不要超过6个。

  • 极易扩展
    Hbase的扩展性主要体现在两个方面,一个是基于上层处理能力(RegionServer)的扩展,一个是基于存储的扩展(HDFS)。

    通过横向添加RegionSever的机器,扩展的机器可以达到20000+,进行水平扩展,提升Hbase上层的处理能力,提升Hbsae服务更多Region的能力。通过横向添加Datanode的机器,进行HDFS存储层扩容,提升Hbase的数据存储能力和提升后端存储的读写能力。

  • 高并发
    由于目前大部分使用Hbase的架构,都是采用的廉价PC,因此单个IO的延迟其实并不小,一般在几IO延迟下降并不多。能获得高并发、低延迟的服务。

  • 稀疏
    稀疏主要是针对Hbase列的灵活性,在列族中,你可以指定任意多的列,在列数据为空的情况下,是不会占用存储空间的。

NoSQL与RDBMS对比

对比NoSQLRDBMS
常用数据库HBase、MongoDB、RedisOracle、DB2、MySQL
存储格式文档、键值对、图结构表格式,行和列
存储规范鼓励冗余规范性,避免重复
存储扩展横向扩展,分布式(列扩展)纵向扩展(横向扩展有限)(行扩展)
查询方式结构化查询语言SQL非结构化查询
事务不支持事务一致性支持事务
性能读写性能高读写性能差
成本简单易部署,开源,成本低成本高

HBase生态圈技术

  • Lily – 基于HBase的CRM(客户关系数据系统管理)
  • OpenTSDB – HBase面向时间序列数据管理
  • Kylin – HBase上的OLAP(联机分析处理)
  • Phoenix – SQL操作HBase工具
  • Splice Machine – 基于HBase的OLTP(联机事务处理)
  • Apache Tephra – HBase事务支持
  • TiDB – 分布式SQL DB
  • Apache Omid - 优化事务管理
  • Yarn application timeline server v.2 迁移到HBase
  • Hive metadata存储可以迁移到HBase
  • Ambari Metrics Server将使用HBase做数据存储

HBase 架构

HBase依旧采用Master/Slave架构搭建集群,它隶属于Hadoop生态圈,依附于ZooKeeper集群的协调一致性服务,由HMaster节点和HRegionServer节点组成;而在底层,它将数据存储于HDFS中,因而涉及到HDFS的NameNode、DataNode等,总体结构如下:
在这里插入图片描述

Client客户端

HBase 有两张特殊的表:

  • META: 记录了用户所有表拆分出来的 Region 映射信息,META可以有多个 Region

  • ROOT(新版中已去掉这一层): 记录了 META表的 Region 信息,ROOT只有一个 Region,无论如何都不会分裂

ROOT表的位置保存在ZooKeeper中,它存储了META表的RegionInfo信息。而META表 则存储了用户Table的RegionInfo信息,它可以被切分成多个HRegion。

Client 客户端通常通过以下API 访问HBase:

API类别		API信息
Java		https://hbase.apache.org/apidocs/
Python 		https://happybase.readthedocs.org/en/latest/
scala		Through Java/Spark
Thrift		https://wiki.apache.org/hadoop/Hbase/ThriftApi
REST		http://blog.cloudera.com/blog/2013/03/how-to-use-the-apache-hbase-rest-interface-part-1/

Client 客户端访问HBase 方式 :

First Visit: create cache with 【regin postion】
Other Visit: use cache
Retry: fetch region and update client cache

Client 访问用户数据前需要首先访问 ZooKeeper,找到ROOT表的 Region 所在的服务器位置,然后访问ROOT表,接着HRegionServer中根据请求的Root表和RowKey读取META表位置,最后才能找到用户数据的服务器位置,并访问META表的内容。在这期间会有多次网络操作,不过 Client 端会做 cache 缓存。

ZooKeeper集群协调一致性服务

ZooKeeper集群协调一致性服务可以分为如下三种功能:

  • 协调监督保障 HMaster 高可用
    只有一个HMaster,如果HMaster异常或死亡,则通过Failover 竞争机制产生新的HMaster。如何选举HMaster,有点类似 ZooKeeper的选举机制
  • 监控HRegionServer的状态
    当HRegionServer异常时,HMaster会通过Zookeeper收到HRegionServer上下线状态
  • 元数据入口地址
    ROOT表在哪台服务器上,ROOT这张表的位置信息;存储 HBase 的 Schema,包括有哪些 Table,每个 Table 有哪些 Column Family

在这里插入图片描述

HMaster节点

具体如下图所示,HMaster节点的功能总结如下:

  • 故障转移:监控HRegionServer,当某HRegionServer异常或死亡,将HRegion转移到其他HRegionServer上执行(通过与zookeeper的Heartbeat和监听ZooKeeper中的状态,并不直接和slave相连
  • 新HRegion分配:HRegion分裂后的重新分配
  • 元数据变更(Admin职能):增删改 Table 操作
  • 数据负载均衡:空闲时在HRegionServer之间迁移HRegion
  • 发送自己位置给Client:借Zookeeper实现

在这里插入图片描述
HMaster节点有点像hadoop 系统yarn核心体系中的组件ResourceManager的ResourceScheduler,进行资源分配和调度。关于yarn体系组件可以参考YARN 架构组件

值得注意的是在HBase集群中HMaster通常也会有一个backup-Masters的备份文件,意思是说有一个备用HMaster,供故障时使用。

HRegionServer节点

具体如下图所示,HRegionServer节点的功能总结如下:

  • 处理分配的HRegion
  • 刷新Cache(读写缓存)到HDFS
  • 维护WAL(Write Ahead Log, HLog)(高容错)
  • 处理来之用户Clinet的读写请求
  • 处理HRegion变大后的拆分
  • 负责StoreFile的合并工作
    在这里插入图片描述

可以看到,client 访问 hbase 上数据的过程并不需要master参与(寻址访问 zookeeper 和 region server,数据读写访问regione server),master 仅仅维护者table和region的元数据信息,负载很低。

BigTable 中指出:

一个HRegionServer可以存放1000个HRegion(可以通过修改配置文件更改)

HBase使用RowKey将表水平切割成多个HRegion,从HMaster的角度,每个HRegion都纪录了它的StartKey和EndKey(第一个HRegion的StartKey为空,最后一个HRegion的EndKey为空,类似链表),由于RowKey是排序的,因而Client可以通过HMaster快速的定位每个RowKey在哪个HRegion中。

底层Table数据存储于HDFS中,而HRegion所处理的数据尽量和数据所在的DataNode在一起,实现数据的本地化;数据本地化并不是总能实现,比如在HRegion移动(如因Split)时,需要等下一次Compact才能继续回到本地化。

HDFS

  • 提供元数据和表数据的底层分布式存储服务
  • WAL(Write Ahead Log, HLog)落盘
  • 数据多副本,保证的高可靠和高可用性

HBase 组件

整体物理结构

在这里插入图片描述

  1. Table 中的所有行都按照 RowKey 的字典顺序进行排列;HBase就是一个庞大的HashMap, RowKey 的字典顺序就类似HashMap中key的哈希算法排序的。
  2. Table 在行的方向上分割为多个 HRegion,类似于hadoop下mapreduce中的文件切割。
  3. HRegion 是按大小分割的(默认为 10G),每个表一开始只有一个 HRegion,随着表中的数据不断增加,HRegion 不断增大,当增大到一个阈值的时候,HRegion 就会等分为两个新的 HRegion,当表中的行不断增多,就会有越来越多的 HRegion。
  4. HRegion 是 HBase 中分布式存储和负载均衡的最小单元。最小单元就表示不同的 HRegion 可以分布在不同的 HRegionServer 上。但是一个 HRegion 是不会拆分到多个 Server 上的
  5. HRegion 虽然是负载均衡的最小单元,但并不是物理存储的最小单元。事实上,HRegion 是由一个或多个 Store 组成,每个 Store 保存一个 Column Family。每个 Store 又由一个 MemStore 和 0 到多个 StoreFile 组成。

Region

Hbase表的分片,HBase表会根据RowKey值被切分成不同的region存储在RegionServer中,在一个RegionServer中可以有多个不同的region。具体如下表:

在这里插入图片描述
Row Key

与nosql数据库们一样,row key是用来检索记录的主键。Row key行键 (Row key)可以是任意字符串(最大长度是 64KB,实际应用中长度一般为 10-100bytes),在hbase内部,row key保存为字节数组。Hbase会对表中的数据按照rowkey排序(字典顺序),例如:

字典序对int排序的结果是
        1,10,100,11,12,13,14,15,16,17,18,19,2,20,21,,9,91,92,93,94,95,96,97,98,99。要保持整形的自然序,行键必须用0作左填充。

存储时,数据按照Row key的字典序(byte order)排序存储。设计key时,要充分考虑排序存储这个特性,将经常一起读取的行存储放到一起。(位置相关性)。

HRegion大小达到一定值时,会进行按rowkey裂变,HBase Table中的行的三种方式:

1.通过单个 RowKey 访问
2.通过 RowKey 的 range(正则)
3.全表扫描

列族Column Family

每一个列族对应一个 Store,也对应 HDFS 一个目录,类似于 Hive 分区操作一样,HBase相当于按列族进行了分区。hbase表中的每个列,都归属与某个列族。列族是表的schema的一部分(而列不是),必须在使用表之前定义。(schema包含表名和列族)

列名都以列族作为前缀。例如courses:history , courses:math 都属于 courses 这个列族。

访问控制、磁盘和内存的使用统计都是在列族层面进行的。列族越多,在取一行数据时所要参与IO、搜寻的文件就越多,所以,如果没有必要,不要设置太多的列族

列 Column

列族下面的具体列,属于某一个ColumnFamily,类似于我们mysql当初创建的具体的列。

时间戳

HBase中通过row和columns确定的为一个存贮单元称为cell。每个 cell都保存着同一份数据的多个版本。版本通过时间戳来索引。时间戳的类型是 64位整型。时间戳可以由hbase(在数据写入时自动 )赋值,此时时间戳是精确到毫秒的当前系统时间。时间戳也可以由客户显式赋值。如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳,一定要用单cell中不重复的时间戳
每个 cell中,不同版本的数据按照时间倒序排序,即最新的数据排在最前面。为避免Cell数据过大,HBase提供两种机制:保留最新的N条数据,或保留截止当下多长时间的数据。

Cell

Cell是存储数据的最小单位。由{row key, column( = + ), version} 唯一确定的单元。Cell类似于excel的一个单元格,Cell中的数据是没有类型的,全部是字节码形式储存。

VersionNum

数据的版本号,每条数据可以有多个版本号,默认值为系统时间戳,类型为Long。

WAL

WAL 意为Write-Ahead logs, HLog文件就是一个普通的Hadoop Sequence File,类似mysql中的binlog,用来做灾难恢复时用,Hlog记录数据的所有变更,一旦数据修改,就可以从log中进行恢复。

当对HBase读写数据的时候,数据不是直接写进磁盘,它会在内存中保留一段时间(时间以及数据量阈值可以设定)。但把数据保存在内存中可能有更高的概率引起数据丢失,为了解决这个问题,所有写操作都会先保证将数据写入这个Log文件( 每个Region Server 维护一个Hlog,每个HRegionServer只有一个)后,才会真正更新MemStore,最后写入HFile中。这样即使HRegionServer宕机,我们依然可以从HLog中恢复数据。

Hlog的切分机制:

1.当数据写入hlog以后,hbase发生异常,关闭当前的hlog文件
2.当日志的大小达到HDFS数据块的0.95倍的时候,关闭当前日志,生成新的日志
3.每隔一小时生成一个新的日志文件

由于HDFS只允许同一时刻对一个文件只能一个客户端写入,所以对HLog只能单线程写入。这样很明显会影响性能,所以在HBase1.0以后的版本,多个WAL并行写(MultiWAL),该实现采用HDFS的多个管道写,以单个HRegion为单位。

StoreFile(HFile)

StoreFile 以 HFile 格式保存在 HDFS 上,是在磁盘上保存原始数据的实际的物理文件,是实际的存储文件。具体如下图所示:

在这里插入图片描述

HFile 分为六个部分:

  • Data Block 段:保存表中的数据,这部分可以被压缩。数据存放在Data块中,Data块的大小可以用户指定,大的Data块适合scan,小的Data块适合随机查找
  • Meta Block 段(可选):保存用户自定义的 Key-Value 对,可以被压缩。HFile里面的每个KeyValue对就是一个简单的byte数组。但是这个byte数组里面包含了很多项,并且有固定的结构。
  • File Info 段:HFile 的元信息,不可被压缩,用户也可以在这一部分添加自己的元信息;例如 AVE_KEY_LEN, AVG_VALUE_LEN, LAST_KEY, COMPARATOR, MAX_SEQ_ID_KEY 等。
  • Data Block Index 段:Data Block 的索引。每条索引的 Key 是被索引的 Block 的第一条记录的 Key,同时需要将索引一次性读入内存。
  • Meta Block Index 段(可选):Meta Block 的索引,同Data Block Index 段。
  • Trailer 段:这一段是定长的。保存了每一段的偏移量,读取一个 HFile 时,会首先读取 Trailer,Trailer 保存了每个段的起始位置(段的 Magic Number 用来做安全 Check),然后 DataBlock Index 会被读取到内存中。这样,当检索某个 Key 时,不需要扫描整个HFile,而只需要从内存中找到 Key 所在的 Block,通过一次磁盘 IO 将整个 Block 读取到内存中,再找到需要的 Key,DataBlock Index 采用 LRU 机制淘汰。

HFile中Block 存储的数据

HFile里面的每个KeyValue对就是一个简单的byte数组。但是这个byte数组里面包含了很多项,并且有固定的结构。我们来看看里面的具体结构:
在这里插入图片描述
开始是两个固定长度的数值,分别表示Key的长度和Value的长度。紧接着是Key,开始是固定长度的数值,表示RowKey的长度,紧接着是 RowKey,然后是固定长度的数值,表示Family的长度,然后是Family,接着是Qualifier(限定符),然后是两个固定长度的数值,表示Time Stamp和Key Type(Put/Delete)。Value部分没有这么复杂的结构,就是纯粹的二进制数据了。

简单的来说,在HFile中的数据是按RowKey、Column Family、Column排序,对相同的Cell(即这三个值都一样),则按timestamp倒序排列

HFile 内部优化

在最新版本的HBase中,为了解决了上述HFile中不定长部分的内存占用,特别是Bloom File(海量数据Block File的所占内存空间)和Block Index过大。把Bloom File和Block Index打散放入Data,每次查询不用加载全部信息。它本质上就是一个多层的类B+树索引,采用这种设计,可以实现查找不需要读取整个文件。
在这里插入图片描述
Data Block中的Cell都是升序排列,每个block都有它自己的Leaf-Index,每个Block的最后一个Key被放入Intermediate-Index中,Root-Index指向Intermediate-Index。Bloom过滤器用于快速定位没有在DataBlock中的数据。

Store(HStore)

HFile存储在Store中,一个Store对应HBase表中的一个列族Column Family;即每个Column Family就是一个集中的存储单元,因而最好将具有相近IO特性的Column存储在一个Column Family,以实现高效读取(数据局部性原理,可以提高缓存的命中率)。

一个HRegion由多个store组成,一个Store由一个MemStore 和0个或多个HFile组成。Store包括位于内存的memstore和位于硬盘的storefile。

MemStore

顾名思义,就是内存存储,位于内存中,用来保存当前的数据操作,所以当数据保存在WAL中之后,RegsionServer会在内存中存储键值对。

每个HStore中都有一个MemStore,即它是一个HRegion的一个Column Family对应一个实例。它的排列顺序以RowKey、Column Family、Column的顺序以及Timestamp的倒序(HFile已经说过)。客户端检索数据时,先在memstore找,找不到再找storefile。

写操作先写入memstore,当memstore中的数据量达到某个阈值(默认为128M),或者HRegionServer上所有MemStore的大小超过了机器上默认40%的内存使用量,或者WAL过大这三种情况下,Hregionserver启动flashcache进程写入storefile,每次写入形成单独一个storefile,输出多个storefile后,当storefile数量达到阈值时,将多个合并成一个大的storefile。当storefile大小超过一定阈值后,会把当前的region分割成两个,并由Hmaster分配给相应的region服务器,实现负载均衡。

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值