欢迎你们前往腾讯云技术社区,获取更多腾讯海量技术实践干货哦~java
做者:张秀云 node
最近在跟进Hbase的相关工做,因为以前对Hbase并不怎么了解,所以系统地学习了下Hbase,为了加深对Hbase的理解,对相关知识点作了笔记,并在组内进行了Hbase相关技术的分享,因为Hbase涵盖的内容比较多,所以计划分享2期,下面就是针对第一期Hbase技术分享总体而成,第一期的主要内容以下:mysql
1、Hbase介绍
2、Hbase的Region介绍
3、Hbase的写逻辑介绍
4、Hbase的故障恢复
5、Hbase的拆分和合并sql
以下ppt所示:shell
下面就来针对各个部分的内容来进行详细的介绍:数据库
Hbase是Hadoop Database的简称 ,Hbase项目是由Powerset公司的Chad Walters和Jim Kelleman在2006年底发起,根据Google的Chang等人发表的论文“Bigtable:A Distributed Storage System for Strctured Data“来设计的。2007年10月发布了第一个版本。2010年5月,Hbase从Hadoop子项目升级成Apache顶级项目。后端
Hbase是分布式、面向列的开源数据库(其实准确的说是面向列族)。HDFS为Hbase提供可靠的底层数据存储服务,MapReduce为Hbase提供高性能的计算能力,Zookeeper为Hbase提供稳定服务和Failover机制,所以咱们说Hbase是一个经过大量廉价的机器解决海量数据的高速存储和读取的分布式数据库解决方案。api
提炼出Hbase的几个特色,以下图所示:缓存
2.一、海量存储安全
Hbase适合存储PB级别的海量数据,在PB级别的数据以及采用廉价PC存储的状况下,能在几十到百毫秒内返回数据。这与Hbase的极易扩展性息息相关。正式由于Hbase良好的扩展性,才为海量数据的存储提供了便利。
2.二、列式存储
这里的列式存储其实说的是列族存储,Hbase是根据列族来存储数据的。列族下面能够有很是多的列,列族在建立表的时候就必须指定。为了加深对Hbase列族的理解,下面是一个简单的关系型数据库的表和Hbase数据库的表:
RDBMS的表:
Hbase的表:
下图是针对Hbase和关系型数据库的基本的一个比较:
2.三、极易扩展
Hbase的扩展性主要体如今两个方面,一个是基于上层处理能力(RegionServer)的扩展,一个是基于存储的扩展(HDFS)。
经过横向添加RegionSever的机器,进行水平扩展,提高Hbase上层的处理能力,提高Hbsae服务更多Region的能力。
备注:RegionServer的做用是管理region、承接业务的访问,这个后面会详细的介绍经过横向添加Datanode的机器,进行存储层扩容,提高Hbase的数据存储能力和提高后端存储的读写能力。
2.四、高并发
因为目前大部分使用Hbase的架构,都是采用的廉价PC,所以单个IO的延迟其实并不小,通常在几十到上百ms之间。这里说的高并发,主要是在并发的状况下,Hbase的单个IO延迟降低并很少。能得到高并发、低延迟的服务。
2.五、稀疏
稀疏主要是针对Hbase列的灵活性,在列族中,你能够指定任意多的列,在列数据为空的状况下,是不会占用存储空间的。
在我学习Hbase的时候有几个概念须要重点理解一下,列出4个基础概念以下图所示:
3.一、Column Family的概念
Column Family又叫列族,Hbase经过列族划分数据的存储,列族下面能够包含任意多的列,实现灵活的数据存取。刚接触的时候,理解起来有点吃力。我想到了一个很是相似的概念,理解起来就很是容易了。那就是家族的概念,咱们知道一个家族是因为不少个的家庭组成的。列族也相似,列族是由一个一个的列组成(任意多)。
Hbase表的建立的时候就必须指定列族。就像关系型数据库建立的时候必须指定具体的列是同样的。
Hbase的列族不是越多越好,官方推荐的是列族最好小于或者等于3。咱们使用的场景通常是1个列族。
3.二、Rowkey的概念
Rowkey的概念和mysql中的主键是彻底同样的,Hbase使用Rowkey来惟一的区分某一行的数据。
因为Hbase只支持3中查询方式:
所以,Rowkey对Hbase的性能影响很是大,Rowkey的设计就显得尤其的重要。设计的时候要兼顾基于Rowkey的单行查询也要键入Rowkey的范围扫描。具体Rowkey要如何设计后续会整理相关的文章作进一步的描述。这里你们只要有一个概念就是Rowkey的设计极为重要。
3.三、Region的概念
Region的概念和关系型数据库的分区或者分片差很少。
Hbase会将一个大表的数据基于Rowkey的不一样范围分配到不通的Region中,每一个Region负责必定范围的数据访问和存储。这样即便是一张巨大的表,因为被切割到不通的region,访问起来的时延也很低。
3.四、TimeStamp的概念
TimeStamp对Hbase来讲相当重要,由于它是实现Hbase多版本的关键。在Hbase中使用不一样的timestame来标识相同rowkey行对应的不通版本的数据。
在写入数据的时候,若是用户没有指定对应的timestamp,Hbase会自动添加一个timestamp,timestamp和服务器时间保持一致。
在Hbase中,相同rowkey的数据按照timestamp倒序排列。默认查询的是最新的版本,用户可同指定timestamp的值来读取旧版本的数据。
Hbase的架构图以下图所示:
从图中能够看出Hbase是由Client、Zookeeper、Master、HRegionServer、HDFS等几个组建组成,下面来介绍一下几个组建的相关功能:
4.一、Client
Client包含了访问Hbase的接口,另外Client还维护了对应的cache来加速Hbase的访问,好比cache的.META.元数据的信息。
4.二、Zookeeper
Hbase经过Zookeeper来作master的高可用、RegionServer的监控、元数据的入口以及集群配置的维护等工做。具体工做以下:
经过Zoopkeeper来保证集群中只有1个master在运行,若是master异常,会经过竞争机制产生新的master提供服务
经过Zoopkeeper来监控RegionServer的状态,当RegionSevrer有异常的时候,经过回调的形式通知Master RegionServer上下限的信息
经过Zoopkeeper存储元数据的统一入口地址
4.三、Hmaster
master节点的主要职责以下:
为RegionServer分配Region
维护整个集群的负载均衡
维护集群的元数据信息
发现失效的Region,并将失效的Region分配到正常的RegionServer上
当RegionSever失效的时候,协调对应Hlog的拆分
4.四、HregionServer
HregionServer直接对接用户的读写请求,是真正的“干活”的节点。它的功能归纳以下:
管理master为其分配的Region
处理来自客户端的读写请求
负责和底层HDFS的交互,存储数据到HDFS
负责Region变大之后的拆分
负责Storefile的合并工做
4.五、HDFS
HDFS为Hbase提供最终的底层数据存储服务,同时为Hbase提供高可用(Hlog存储在HDFS)的支持,具体功能归纳以下:
提供元数据和表数据的底层分布式存储服务
数据多副本,保证的高可靠和高可用性
Hbase是一个经过廉价PC机器集群来存储海量数据的分布式数据库解决方案。它比较适合的场景归纳以下:
有几个典型的场景特别适合使用Hbase来存储:
海量订单流水数据(长久保存)
交易记录
数据库历史数据
前面已经介绍了Region相似于数据库的分片和分区的概念,每一个Region负责一小部分Rowkey范围的数据的读写和维护,Region包含了对应的起始行到结束行的全部信息。master将对应的region分配给不一样的RergionServer,由RegionSever来提供Region的读写服务和相关的管理工做。这部分主要介绍Region实例以及Rgeion的寻找路径:
上图模拟了一个Hbase的表是如何拆分红region,以及分配到不一样的RegionServer中去。上面是1个Userinfo表,里面有7条记录,其中rowkey为0001到0002的记录被分配到了Region1上,Rowkey为0003到0004的记录被分配到了Region2上,而rowkey为000五、0006和0007的记录则被分配到了Region3上。region1和region2被master分配给了RegionServer1(RS1),Region3被master配分给了RegionServer2(RS2)
备注:这里只是为了更容易的说明拆分的规则,其实真实的场景并不会几条记录拆分到不通的Region上,而是到必定的数据量才会拆分,具体的在Region的拆分那部分再具体的介绍。
既然读写都在RegionServer上发生,咱们前面有讲到,每一个RegionSever为必定数量的region服务,那么client要对某一行数据作读写的时候如何能知道具体要去访问哪一个RegionServer呢?那就是接下来咱们要讨论的问题
2.一、老的Region寻址方式
在Hbase 0.96版本之前,Hbase有两个特殊的表,分别是-ROOT-表和.META.表,其中-ROOT-的位置存储在ZooKeeper中,-ROOT-自己存储了 .META. Table的RegionInfo信息,而且-ROOT-不会分裂,只有一个region。而.META.表能够被切分红多个region。读取的流程以下图所示:
第1步:client请求ZK得到-ROOT-所在的RegionServer地址
第2步:client请求-ROOT-所在的RS地址,获取.META.表的地址,client会将-ROOT-的相关信息cache下来,以便下一次快速访问
第3步:client请求 .META.表的RS地址,获取访问数据所在RegionServer的地址,client会将.META.的相关信息cache下来,以便下一次快速访问
第4步:client请求访问数据所在RegionServer的地址,获取对应的数据
从上面的路径咱们能够看出,用户须要3次请求才能直到用户Table真正的位置,这在必定程序带来了性能的降低。在0.96以前使用3层设计的主要缘由是考虑到元数据可能须要很大。可是真正集群运行,元数据的大小其实很容易计算出来。在BigTable的论文中,每行METADATA数据存储大小为1KB左右,若是按照一个Region为128M的计算,3层设计能够支持的Region个数为2^34个,采用2层设计能够支持2^17(131072)。那么2层设计的状况下一个 集群能够存储4P的数据。这仅仅是一个Region只有128M的状况下。若是是10G呢? 所以,经过计算,其实2层设计就能够知足集群的需求。所以在0.96版本之后就去掉了-ROOT-表了。
2.二、新的Region寻址方式
如上面的计算,2层结构其实彻底能知足业务的需求,所以0.96版本之后将-ROOT-表去掉了。以下图所示:
访问路径变成了3步:
第1步:Client请求ZK获取.META.所在的RegionServer的地址。
第2步:Client请求.META.所在的RegionServer获取访问数据所在的RegionServer地址,client会将.META.的相关信息cache下来,以便下一次快速访问。
第3步:Client请求数据所在的RegionServer,获取所须要的数据。
总结去掉-ROOT-的缘由有以下2点:
其一:提升性能
其二:2层结构已经足以知足集群的需求
这里还有一个问题须要说明,那就是Client会缓存.META.的数据,用来加快访问,既然有缓存,那它何时更新?若是.META.更新了,好比Region1不在RerverServer2上了,被转移到了RerverServer3上。client的缓存没有更新会有什么状况?
其实,Client的元数据缓存不更新,当.META.的数据发生更新。如上面的例子,因为Region1的位置发生了变化,Client再次根据缓存去访问的时候,会出现错误,当出现异常达到重试次数后就会去.META.所在的RegionServer获取最新的数据,若是.META.所在的RegionServer也变了,Client就会去ZK上获取.META.所在的RegionServer的最新地址。
Hbase的写逻辑涉及到写内存、写log、刷盘等操做,看起来简单,其实里面又有不少的逻辑,下面就来作详细的介绍
Hbase的写入流程以下图所示:
从上图能够看出氛围3步骤:
第1步:Client获取数据写入的Region所在的RegionServer
第2步:请求写Hlog
第3步:请求写MemStore
只有当写Hlog和写MemStore都成功了才算请求写入完成。MemStore后续会逐渐刷到HDFS中。
备注:Hlog存储在HDFS,当RegionServer出现异常,须要使用Hlog来恢复数据。
为了提升Hbase的写入性能,当写请求写入MemStore后,不会当即刷盘。而是会等到必定的时候进行刷盘的操做。具体是哪些场景会触发刷盘的操做呢?总结成以下的几个场景:
2.一、全局内存控制
这个全局的参数是控制内存总体的使用状况,当全部memstore占整个heap的最大比例的时候,会触发刷盘的操做。这个参数是hbase.regionserver.global.memstore.upperLimit,默认为整个heap内存的40%。但这并不意味着全局内存触发的刷盘操做会将全部的MemStore都进行输盘,而是经过另一个参数hbase.regionserver.global.memstore.lowerLimit来控制,默认是整个heap内存的35%。当flush到全部memstore占整个heap内存的比率为35%的时候,就中止刷盘。这么作主要是为了减小刷盘对业务带来的影响,实现平滑系统负载的目的。
2.二、MemStore达到上限
当MemStore的大小达到hbase.hregion.memstore.flush.size大小的时候会触发刷盘,默认128M大小
2.三、RegionServer的Hlog数量达到上限
前面说到Hlog为了保证Hbase数据的一致性,那么若是Hlog太多的话,会致使故障恢复的时间太长,所以Hbase会对Hlog的最大个数作限制。当达到Hlog的最大个数的时候,会强制刷盘。这个参数是hase.regionserver.max.logs,默认是32个。
2.四、手工触发
能够经过hbase shell或者java api手工触发flush的操做。
2.五、关闭RegionServer触发
在正常关闭RegionServer会触发刷盘的操做,所有数据刷盘后就不须要再使用Hlog恢复数据。
2.六、Region使用HLOG恢复完数据后触发
当RegionServer出现故障的时候,其上面的Region会迁移到其余正常的RegionServer上,在恢复完Region的数据后,会触发刷盘,当刷盘完成后才会提供给业务访问。
3.一、Hlog简介
Hlog是Hbase实现WAL(Write ahead log)方式产生的日志信息,内部是一个简单的顺序日志。每一个RegionServer对应1个Hlog(备注:1.x版本的能够开启MultiWAL功能,容许多个Hlog),全部对于该RegionServer的写入都被记录到Hlog中。Hlog实现的功能就是咱们前面讲到的保证数据安全。当RegionServer出现问题的时候,能跟进Hlog来作数据恢复。此外为了保证恢复的效率,Hbase会限制最大保存的Hlog数量,若是达到Hlog的最大个数(hase.regionserver.max.logs参数控制)的时候,就会触发强制刷盘操做。对于已经刷盘的数据,其对应的Hlog会有一个过时的概念,Hlog过时后,会被监控线程移动到 .oldlogs,而后会被自动删除掉。
Hbase是如何判断Hlog过时的呢?要找到这个答案,咱们就必须了解Hlog的详细结构。
3.二、Hlog结构
下图是Hlog的详细结构(图片来源 http://hbasefly.com/ ):
从上图咱们能够看出都个Region共享一个Hlog文件,单个Region在Hlog中是按照时间顺序存储的,可是多个Region可能并非彻底按照时间顺序。
每一个Hlog最小单元由Hlogkey和WALEdit两部分组成。Hlogky由sequenceid、timestamp、cluster ids、regionname以及tablename等组成,WALEdit是由一系列的KeyValue组成,对一行上全部列(即全部KeyValue)的更新操做,都包含在同一个WALEdit对象中,这主要是为了实现写入一行多个列时的原子性。
注意,图中有个sequenceid的东东。sequenceid是一个store级别的自增序列号,这东东很是重要,region的数据恢复和Hlog过时清除都要依赖这个东东。下面就来简单描述一下sequenceid的相关逻辑。
3.三、Hlog的生命周期
Hlog从产生到最后删除须要经历以下几个过程:
产生
全部涉及到数据的变动都会先写Hlog,除非是你关闭了Hlog
滚动
Hlog的大小经过参数hbase.regionserver.logroll.period控制,默认是1个小时,时间达到hbase.regionserver.logroll.period 设置的时间,Hbase会建立一个新的Hlog文件。这就实现了Hlog滚动的目的。Hbase经过hbase.regionserver.maxlogs参数控制Hlog的个数。滚动的目的,为了控制单个Hlog文件过大的状况,方便后续的过时和删除。
过时
前面咱们有讲到sequenceid这个东东,Hlog的过时依赖于对sequenceid的判断。Hbase会将Hlog的sequenceid和Hfile最大的sequenceid(刷新到的最新位置)进行比较,若是该Hlog文件中的sequenceid比刷新的最新位置的sequenceid都要小,那么这个Hlog就过时了,过时了之后,对应Hlog会被移动到.oldlogs目录。
这里有个问题,为何要将过时的Hlog移动到.oldlogs目录,而不是直接删除呢?
答案是由于Hbase还有一个主从同步的功能,这个依赖Hlog来同步Hbase的变动,有一种状况不能删除Hlog,那就是Hlog虽然过时,可是对应的Hlog并无同步完成,所以比较好的作好是移动到别的目录。再增长对应的检查和保留时间。
此文已由做者受权腾讯云技术社区发布,转载请注明文章出处原文连接:https://cloud.tencent.com/community/article/761242