IT学习笔记--Hbase

1.Hbase简介

Hbase是分布式、面向列的开源数据库(其实准确的说是面向列族)。HDFS为Hbase提供可靠的底层数据存储服务,MapReduce为Hbase提供高性能的计算能力,Zookeeper为Hbase提供稳定服务和Failover机制,因此我们说Hbase是一个通过大量廉价的机器解决海量数据的高速存储和读取的分布式数据库解决方案。

2. Hbase的几个特点

1)海量存储:适合存储PB级别的海量数据,在PB级别的数据以及采用廉价PC存储的情况下,能在几十到百毫秒内返回数据。

2)列式存储:其实说的是列族存储,Hbase是根据列族来存储数据的。列族下面可以有非常多的列,列族在创建表的时候就必须指定。

下面是一个简单的关系型数据库的表和Hbase数据库的表:

RDBMS的表:

Hbase的表:

下图是针对Hbase和关系型数据库的基本的一个比较:

3)极易扩展:主要体现在两个方面,一个是基于上层处理能力(RegionServer)的扩展,一个是基于存储的扩展(HDFS)。通过横向添加RegionSever(作用是管理region、承接业务的访问)的机器,进行水平扩展,提升Hbase上层的处理能力,提升Hbsae服务更多Region的能力。

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

3. Hbase几个重要概念

1)Column Family:又叫列族,Hbase通过列族划分数据的存储,列族下面可以包含任意多的列,实现灵活的数据存取。可以用家族的概念来理解,一个家族是由很多个家庭组成的。列族也类似,列族是由一个一个的列组成(任意多)。

注意:1)Hbase表的创建的时候就必须指定列族。就像关系型数据库创建的时候必须指定具体的列是一样的。

            2)Hbase的列族不是越多越好,官方推荐的是列族最好小于或者等于3。我们使用的场景一般是1个列族。

             3)每一个列,都必须归属于一个Column Family,这个归属关系是在写数据时指定的,而不是建表时预先定义。

2)Rowkey:它和mysql中的主键是完全一样的,Hbase使用Rowkey来唯一的区分某一行的数据。由于Hbase只支持3中查询方式:

  • 基于Rowkey的单行查询
  • 基于Rowkey的范围扫描
  • 全表扫描

因此,Rowkey对Hbase的性能影响非常大,Rowkey的设计就显得尤为的重要。设计的时候要兼顾基于Rowkey的单行查询也要兼顾Rowkey的范围扫描。 

3)Region:它和关系型数据库的分区或者分片差不多。Hbase会将一个大表的数据基于Rowkey的不同范围分配到不同的Region中,每个Region负责一定范围的数据访问和存储。这样即使是一张巨大的表,由于被切割到不同的region,访问起来的时延也很低。Region是Hbase中负载均衡的基本单元,当一个Region增长到一定大小以后,会自动分裂成两个。

4)TimeStamp:它对Hbase来说至关重要,因为它是实现Hbase多版本的关键。

  • 在Hbase中使用不同的timestame来标识相同rowkey行对应的不通版本的数据。
  • 在写入数据的时候,如果用户没有指定对应的timestamp,Hbase会自动添加一个timestamp,timestamp和服务器时间保持一致。
  • 在Hbase中,相同rowkey的数据按照timestamp倒序排列。默认查询的是最新的版本,用户可同指定timestamp的值来读取旧版本的数据。

 5)KeyValue:

KeyValue类是HBase中数据存储的核心,由keylength、valuelength、key、value四个部分组成,其中Key又由Row Length、Row、Column Family Length、Column Family、Column Qualifier(列名)、Time Stamp、Key Type七部分组成。每一行中的每一列数据,都被包装成独立的拥有特定结构的KeyValue。 
KeyValue不会在块之间拆分。例如,如果有一个8 MB的KeyValue,即使块大小是64kb,这个KeyValue将作为一个连贯块读取。 
结构如下:

这里写图片描述

其中: 

  • KeyLength存储Key的长度,占4B;
  •  ValueLength存储Value的长度,4B;
  • Key存储具体的Cell数据为:
1、 Row Length:存储rowkey的长度,占2B (Bytes.SIZEOF_INT);
2、 Row:存储Rowkey实际内容,其大小为Row Length ;
3、 Column Family Length:存储列簇Column Family的长度,占1B (Bytes.SIZEOF_BYTE); 
4、 Column Family:存储Column Family实际内容,大小为Column Family Length;
5、 Column Qualifier:存储Column Qualifier对应的数据。
6、 Time Stamp:存储时间戳Time Stamp,占8B (Bytes.SIZEOF_LONG);
7、 Key Type:存储Key类型Key Type,占1B ( Bytes.SIZEOF_BYTE),Type分为Put、Delete、DeleteColumn、DeleteFamilyVersion、DeleteFamily、Maximum、Minimum等类型,标记这个KeyValue的类型;
由于Key中其它的字段占用大小已经知道,并且知道整个Key的大小,因此没有存储Column Qualifier的大小。
  • Value:存储单元格Cell对应的实际的值Value。例如:对于Put : rowkey=row1, cf:attr1=value1操作,Key对应关系如下:
rowlength -----------→ 4
row -----------------→ row1
columnfamilylength --→ 2
columnfamily --------→ cf
columnqualifier -----→ attr1
timestamp -----------→ server time of Put
keytype -------------→ Put

rowlength占用2B空间,因此解释了rowkey的最大长度不能超过64kb。

4. Hbase存储系统的架构

HBase分布式数据库,只是分布式存储系统中的一部分,其系统组成包含HDFS、Region Server、Master节点、ZooKeeper集群等四大部分。各部分的具体功能如下描述:

1)HDFS

HBase底层存储上依赖于HDFS,HDFS保证了HBase的高可靠性。HDFS为RegionServer和Master节点提供分布式存储服务,同时保证数据的可靠性,主要功能如下:

  • 提供元数据和表数据的存储
  • 数据多副本保存,保证数据的高可靠性和高可用性

2)Master节点主要负责:

  • 为Region Server(在hbase中称之为RegionServer)分配region。
  • 负责整个集群的负载均衡
  • 维护集群中的元数据
  • 负责监控整个集群,发现失效的RegionServer,并重新分配其上的Region

3)RegionServer主要负责:

  • 管理Master分配的Region,处理来自客户端对Region的读取工作
  • 切分在运行过程中变得过大的Region
  • 负责和底层的HDFS交互,存储数据

4)ZooKeeper功能:

  • 保证集群中仅仅存在一个Master能够运行
  • 监控RegionServer的状态,通过回调的形式通知Master  RegionServer的上下线的信息
  • 存储寻址的入口地址

5. Hbase的Region实例及寻址

Region类似于数据库的分片和分区的概念,每个Region负责一小部分Rowkey范围的数据的读写和维护,Region包含了对应的起始行到结束行的所有信息。master将对应的region分配给不同的RergionServer,由RegionSever来提供Region的读写服务和相关的管理工作。

1)region实例

上图模拟了一个Hbase的表是如何拆分成region,以及分配到不同的RegionServer中去。上面是1个Userinfo表,里面有7条记录,其中rowkey为0001到0002的记录被分配到了Region1上,Rowkey为0003到0004的记录被分配到了Region2上,而rowkey为0005、0006和0007的记录则被分配到了Region3上。region1和region2被master分配给了RegionServer1(RS1),Region3被master配分给了RegionServer2(RS2)。

2)region的寻址

既然读写都在RegionServer上发生,我们前面有讲到,每个RegionSever为一定数量的region服务,那么client要对某一行数据做读写的时候如何能知道具体要去访问哪个RegionServer呢?那就是接下来我们要讨论寻址问题。

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不在RegionServer2上了,被转移到了RegionServer3上。client的缓存没有更新会有什么情况?
其实,Client的元数据缓存不更新,当.META.的数据发生更新。如上面的例子,由于Region1的位置发生了变化,Client再次根据缓存去访问的时候,会出现错误,当出现异常达到重试次数后就会去.META.所在的RegionServer获取最新的数据,如果.META.所在的RegionServer也变了,Client就会去ZK上获取.META.所在的RegionServer的最新地址。

6. Hbase的写逻辑:Hbase的写逻辑涉及到写内存、写log、刷盘等操作。

1)Hbase写入逻辑:其流程如下

从上图可以看出氛围3步骤:

第1步:Client获取数据写入的Region所在的RegionServer
第2步:请求写Hlog
第3步:请求写MemStore

只有当写Hlog和写MemStore都成功了才算请求写入完成。MemStore后续会逐渐刷到HDFS中。

注意:Hlog存储在HDFS,当RegionServer出现异常,需要使用Hlog来恢复数据。

2)MemStore刷盘:

为了提高Hbase的写入性能,当写请求写入MemStore后,不会立即刷盘。而是会等到一定的时候进行刷盘的操作。在以下几个场景会触发刷盘的操作:

(1)全局内存控制

这个全局的参数是控制内存整体的使用情况,当所有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大小。

(3)RegionServer的Hlog数量达到上限

前面说到Hlog为了保证Hbase数据的一致性,那么如果Hlog太多的话,会导致故障恢复的时间太长,因此Hbase会对Hlog的最大个数做限制。当达到Hlog的最大个数的时候,会强制刷盘。这个参数是hase.regionserver.max.logs,默认是32个。

(4)手动触发

可以通过hbase shell或者java api手工触发flush的操作。

(5)关闭RegionServer触发

在正常关闭RegionServer会触发刷盘的操作,全部数据刷盘后就不需要再使用Hlog恢复数据。

(6)Region使用Hlog恢复完数据后触发

当RegionServer出现故障的时候,其上面的Region会迁移到其他正常的RegionServer上,在恢复完Region的数据后,会触发刷盘,当刷盘完成后才会提供给业务访问。

7. 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,然后会被自动删除掉。

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并没有同步完成,因此比较好的做好是移动到别的目录。再增加对应的检查和保留时间。

  • 删除
    如果Hbase开启了replication,当replication执行完一个Hlog的时候,会删除Zoopkeeper上的对应Hlog节点。在Hlog被移动到.oldlogs目录后,Hbase每隔hbase.master.cleaner.interval(默认60秒)时间会去检查.oldlogs目录下的所有Hlog,确认对应的Zookeeper的Hlog节点是否被删除,如果Zookeeper 上不存在对应的Hlog节点,那么就直接删除对应的Hlog。
    hbase.master.logcleaner.ttl(默认10分钟)这个参数设置Hlog在.oldlogs目录保留的最长时间。

8. Eclipse 连接Hbase需要注意的地方:

1) 首先查看linux服务器/etc/hostname文件配置,将/etc/hosts文件127.0.0.1 localhost注释掉,改成ip hostname。服务器端就处理完了。

windows客户端修改hosts为linux服务器ip linux服务器hostname(做个域名映射)。

启动hbase,在浏览器访问查看master地址,之前我的master地址一直是127.0.0.1或localhost,所以访问不到,经以上所述配置,master地址就是hostname,以下测试代码能测通了。

2)在hbase-site.xml的配置项中加入:

这里写图片描述

重启hbase之后,再次用telnet测试就可以了: 
如下: 
这里写图片描述 
telnet结果如下,什么都没有表示已经通了 
这里写图片描述

同时用netstat再次查看hbase服务: 
这里写图片描述

 解决了下面这个问题,即:

能够正常ping通,如下: 
这里写图片描述

但是telnet不通: 
这里写图片描述

这说明本机的ip到hbase集群所在的linux机器的网络是通的,但是外部并不能访问hbase服务。

具体可参考这篇文档:Eclipse和HBase连不上的问题分析 

3)在windows下要修改C:\Windows\System32\drivers\etc的hosts,添加上虚拟机的ip和名称对应。

猜你喜欢

转载自blog.csdn.net/xudasong123/article/details/81141874