欢迎投稿

今日深度:

Hbase介绍,利用HadoopHD

Hbase介绍,利用HadoopHD


Hbase介绍

什么是Hbase

Hbase是一个高可靠、高性能、面向列、可伸缩的分布式存储系统,利用Hbase技术可在廉价的PC Server上搭建大规模结构化存储集群。

利用Hadoop HDFS作为其文件存储系统,利用Hadoop MapReduce来处理 Hbase中的海量数据,利用Zookeeper作为其分布式协同服务

主要用来存储非结构化和半结构化的松散数据(列存NoSQL数据库)

Hbase 的特点

Hbase 中的表一般有以下特点。

HBase与传统关系数据库的对比分析

数据类型:关系数据库采用关系模型,具有丰富的数据类型和存储方式,HBase则采用了更加简单的数据模型,它把数据存储为未经解释的字符串;

数据操作:关系数据库中包含了丰富的操作,其中会涉及复杂的多表连接。HBase操作则不存在复杂的表与表之间的关系,只有简单的插入、查询、删除、清空等,因为HBase在设计上就避免了复杂的表和表之间的关系;

查询语言:关系型数据库可使用sql进行查询,Hbase只能使用API(get、put、sacn等)进行操作

存储模式:关系数据库是基于行模式存储的。HBase是基于列存储的,每个列族都由几个文件保存,不同列族的文件是分离的;

数据索引:关系数据库通常可以针对不同列构建复杂的多个索引,以提高数据访问性能。HBase只有一个索引——行键,通过巧妙的设计,HBase中的所有访问方法,或者通过行键访问,或者通过行键扫描,从而使得整个系统不会慢下来;

数据维护:在关系数据库中,更新操作会用最新的当前值去替换记录中原来的旧值,旧值被覆盖后就不会存在。而在HBase中执行更新操作时,并不会删除数据旧的版本,而是生成一个新的版本,旧有的版本仍然保留;

可伸缩性:关系数据库很难实现横向扩展,纵向扩展的空间也比较有限。相反,HBase和BigTable这些分布式数据库就是为了实现灵活的水平扩展而开发的,能够轻易地通过在集群中增加或者减少硬件数量来实现性能的伸缩

整体架构

HBase架构中的主要组件

1.ZooKeeper

HBase集群要依赖ZooKeeper才能运行。主要作用是:

2.Client

包含访问HBase的接口并维护cache来加快对HBase的访问。Client可不经过Master直接与Region Server通信,发出读或写请求,所以Master挂掉的情况下,集群仍然可以运行一段时间。

3.HMaster

HMaster是集群的主节点,本质上是一个进程。主要作用有

4.Region Server

Region Server是Region的管理者,本质上是一个进程。主要作用是:

5.Region

Memstore 与 storefile


5.HLog(WAL log):

每个HRegionServer中都会有一个HLog对象,HLog是一个实现Write Ahead Log的类,每次用户操作写入Memstore的同时,也会写一份数据到HLog文件中,HLog文件定期会滚动出新,并删除旧的文件(已持久化到Storefile中的数据),当HRegionServer意外终止后,HMaster会通过Zookeeper感知,HMaster首先处理遗留的HLog文件,将不同region的log数据拆分,分别放在相应region目录下,然后再将失效的region(带有刚刚拆分的log)重新分配,领取到这些region的HRegionServer在Load Region的过程中,会发现有历史HLog需要处理,因此会Replay HLog中的数据到Memstore中,然后flush到StoreFile,完成数据恢复。

7.hbase:meta

hbase:meta(以前叫.META.)是之前说过的命名空间 hbase中的一张表。记录了全部表的所有region相关信息,如region位于哪个Region Server上。 重点:hbase:meta表的位置信息存储在Zookeeper中!!!

hbase:meta(.meta.)表结构

Key:

Region key的格式是:[table],[region start key],[region id]

Values:

info:regioninfo: 序列化的当前region的HRegionInfo实例。

info:server:存储这个region的regionserver的server:port

info:serverstartcode:该Regionserver拥用该region的起始时间

数据模型

hbase在使用之前无需定义一个固定的表结构,同一个表中不同行数据可以包含不同的列。Hbase很适合存储不确定列、不确定大小的半结构化数据。

逻辑模型

逻辑视图

RowKey:是Byte array,是表中每条记录的“主键”,方便快速查找,Rowkey的设计非常重要;

Column Family:列族,拥有一个名称(string),包含一个或者多个相关列;

Column:属于某一个columnfamily,

familyName:columnName,每条记录可动态添加;

Version Number:HBase中通过row和columns确定的为一个存贮单元称为cell。每个 cell都保存着同一份数据的多个版本。版本通过时间戳来索引。时间戳的类型是 64位整型。时间戳可以由hbase(在数据写入时自动 )赋值,此时时间戳是精确到毫秒的当前系统时间。时间戳也可以由客户显式赋值。如果应用程序要避免数据版本冲突,就必须自己生成具有唯一性的时间戳。每个 cell中,不同版本的数据按照时间倒序排序,即最新的数据排在最前面。为了避免数据存在过多版本造成的的管理 (包括存贮和索引)负担,hbase提供了两种数据版本回收方式。一是保存数据的最后n个版本,二是保存最近一段时间内的版本(比如最近七天)。用户可以针对每个列族进行设置。

Value(Cell):由*{row key, column(* = +

以关系型数据的思维下会感觉,上面的表格是一个5列4行的数据表格,但是在HBase中这种理解是错误的,其实在HBase中上面的表格只是一行数据;

物理模型

每个column family存储在HDFS上的一个单独文件中,空值不会被保存。

HBase是一个列式存储数据库,数据按列族聚簇存储在存储文件(StoreFile)中,在逻辑视图上面有些列是空白的,空白的列单元格不会被存储,当请求这些空白的单元格时,会返回null值。如果在查询的时候不提供时间戳,那么会返回距离现在最近的那一个版本的数据,因为在存储的时候,数据会按照时间戳来排序。

(1)HBase中表按照行键的范围被划分为不同的分区(Region),各个分区由分区服务器负责管理并提供数据读写服务,HBase主节点进程(HMaster)负责分区的分配以及在集群中的迁移。

(2)一个分区同时有且仅由一个分区服务器提供服务。当分区增长到配置的大小后,如果开启了自动拆分(也可以手动拆分或者建表时预先拆分),则分区服务器会负责将这个分区拆分成两个。

每个分区都有一个唯一的分区名,格式是“<表名,startRowKey,创建时间>”。一个分区下的每个列族都会有一个存储仓库(Store),因此一个表有几个列族,那么每个分区就会有几个存储仓库。

(3)每个Store(存储仓库)有且仅有一个MemStore(内存仓库),但是可以有多个存储文件。当分区服务器处理写入请求时,数据的变更操作在写入WAL后,会先写入MemStore,同时在内存中按行键排序。

当MemStore到达配置的大小或者集群中所有MemStore使用的总内存达到配置的阈值百分比时,MemStore会刷新为一个StoreFile(存储文件)到磁盘,存储文件只会顺序写入,不支持修改。

(4)数据块(block)是HBase中数据读取的最小单元,StoreFile由数据块组成,可以在建表时按列族指定表数据的数据块大小。如果开启了HBase的数据压缩功能,数据在写入StoreFile之前会按数据块进行压缩,读取时同样对数据块解压后再放入缓存。理想情况下,每次读取数据的大小都是指定的数据块大小的倍数,这样可以避免一些无效的IO,效率最高。


Hbase基本操作

list

  1. 查看表结构信息命令
describe 'tableName'desc 'tableName'

  1. 插入数据
put ‘tableName’,‘rowKey’,‘列族:列名’,‘value

  1. 查询数据(单行)
get 'tableName','rowKey'

  1. 按指定条件获取一批数据
scan 'tableName' 

不指定条件得情况下查询全表。一般可设定起始和结束的rowKey、查询的条数、是否排序等。

  1. 删除数据
delete ‘表’,‘行’,‘列’,时间戳

hbase生存期TTL的设置

即生存期。TTL是作用于列族的,它设置了一个基于时间戳的临界值, 内部的管理会自动检查TTL值是否达到上限,在major合并过程中时间戳被判定为超过TTL的数据会被自动删除

1.建表时直接指定TTL

create 'hbase_test',{NAME => 'cf', TTL=>'86400'},{NAME => 'data'}

2.在已存在表上指定

alter "hbase_test",NAME=>'data',TTL=>'86400' #设置TTL值,作用于列族data

zookeeper中Hbase节点含义

[meta-region-server, rs, splitWAL, backup-masters, flush-table-proc, master-maintenance, online-snapshot, switch, master, running, draining, namespace, hbaseid, table]

序号zookeeper节点名节点含义
1meta-region-server存储HBase集群hbase:meta元数据表所在的RegionServer访问地址。客户端读写数据首先会从此节点读取hbase:meta元数据的访问地址,将部分元数据加载到本地,根据元数据进行数据路由。
2rs/[host-name]每个子znode包含各RegionServer的信息
3master其中包含当前活动(即赢得选举)的HMaster信息
4hbaseid集群id
5table集群中各个表信息
6splitWALreplay过程中等待切分的日志路径
7namespacehabse的namespace
8online-snapshot用来实现在线snapshot操作。表级别在线snapshot同样是一个分布式操作,需要对目标表的每个Region都执行snapshot,全部成功之后才能返回成功。Master作为控制节点给各个相关RegionServer下达snapshot命令,对应RegionServer对目标Region执行snapshot,成功后通知Master。Master下达snapshot命令、RegionServer反馈snapshot结果都是通过ZooKeeper完成的。
9backup-masters/[host-name]每个子znode包含当前作为热备的HMaster信息
10draining当若干个regionserver同时下线时,将要下线的regionserver以临时节点的方式存储在这里,避免要下线的region转移到另个一要下线的regionserver上面
8master-maintenance暂未找到明确含义
12running同上
13switch同上
14flush-table-proc同上

hdfs路径含义

序号路径名称路径含义
1/hbase/datahbase 的核心目录,0.98版本里支持 namespace 的概念模型,系统会预置两个 namespace 即:hbase和default
2/hbase/data/hbase/namespace中存储了 HBase 中的所有 namespace 信息,包括预置的hbase 和 default。
3/hbase/data/hbase/metahbase的元数据表,存储了region的位置信息
4hbase/data/default/存储所有用户数据表/hbase/data/default/表名
5/hbase/.tmp这个目录用来存储临时文件,当对表进行操作的时候,首先会将表移动到该目录下,然后再进行操作。比如,表创建的时候首先会在tmp目录下执行,执行成功后再将tmp目录下的表信息移动到实际表目录下。表删除操作会将表目录移动到tmp目录下,一定时间过后再将tmp目录下的文件真正删除
6/hbase/hbase.id存储集群唯一的 cluster id 号,是一个 uuid。
7/hbase/WALs存储集群中所有RegionServer的HLog日志文件
8/hbase/oldWALs当/hbase/WALs 中的HLog文件被持久化到存储文件中,不再需要日志文件时,它们会被移动到/hbase/oldWALs目录。
9/hbase/hbase.versionHBase软件版本文件,代码静态版本
10/hbase/corrupt存储损坏的HLog文件或者HFile文件
11/hbase/archive存储表的归档和快照,HBase 在做 Split或者 compact 操作完成之后,会将之前的HFile 移到archive 目录中,该目录由 HMaster 上的一个定时任务定期去清理。存储表的归档和快照具体目录:/hbase/archive/data/default/表名/region名/列族名/fd2221d8d1ae4e579c21882f0ec4c5a5,这个目录中的文件会有定时任务定时进行清理。
12.tabledesc表描述文件,记录对应表的基本schema信息。
13.tmp:表临时目录,主要用来存储Flush和Compaction过程中的中间结果。以f lush为例,MemStore中的KV数据落盘形成HFile首先会生成在.tmp目录下,一旦完成再从.tmp目录移动到对应的实际文件目录。
14.regioninfoRegion描述文件。
15recovered.edits存储故障恢复时该Region需要回放的WAL日志数据。RegionServer宕机之后,该节点上还没有来得及flush到磁盘的数据需要通过WAL回放恢复,WAL文件首先需要按照Region进行切分,每个Region拥有对应的WAL数据片段,回放时只需要回放自己的WAL数据片段即可。

HBase数据的读取流程

1.Client访问zookeeper,获取元数据存储所在的regionserver

2.通过刚刚获取的地址访问对应的regionserver,拿到对应的表存储的regionserver

3.去表所在的regionserver进行数据的读取

4.查找对应的region,在region中寻找列族,先找到memstore,找不到去blockcache中寻找,再找不到就进行storefile的遍历

5.找到数据之后会先缓存到blockcache中,再将结果返回

blockcache逐渐满了之后,会采用LRU的淘汰策略。

HBase数据的写入过程

1、Client访问zookeeper,获取元数据存储所在的regionserver

2、通过刚刚获取的地址访问对应的regionserver,拿到对应的表存储的regionserver

3、去表所在的regionserver进行数据的添加

4、查找对应的region,在region中寻找列族,先向memstore中写入数据

5、当memstore写入的值变多,触发溢写操作(flush),进行文件的溢写,成为一个StoreFile

6、当溢写的文件过多时,会触发文件的合并(Compact)操作,合并有两种方式(major,minor)(多个StoreFile合并成一个StoreFile,同时进行版本合并和数据删除)

  • minor compaction:小范围合并,默认是3-10个文件进行合并,不会删除其他版本的数据。
  • major compaction:将当前目录下的所有文件全部合并,一般手动触发,会删除其他版本的数据(不同时间戳的)

7、当region中的数据逐渐变大之后,达到某一个阈值,会进行裂变(一个region等分为两个region,并分配到不同的regionserver),原本的Region会下线,新Split出来的两个Region会被HMaster分配到相应的HRegionServer上,使得原先1个Region的压力得以分流到2个Region上。

Hbase启动时Zookeeper作用

1.Hbase启动时需要读取zookeeper中meta-region-server,以获取Hbase的meta信息(位置信息)。

2.拿到meta的位置信息后,到指定的regionserver读取元数据信息。

3.加载元数据信息中的namespace,加载表。

线上数据迁移问题复现

复现步骤

1.将Hbase集群服务停止。

2.将zookeeper的meta-region-server节点删除。

3.启动Hbase集群,在Hbase shell客户端执行查询操作。

4.查看日志,发现HMaster启动失败。

5.复现步骤结束,得到与线上一致的现象与报错。

6.对比删除zookeeper中meta-region-server节点前后的数据

前:

[zk: localhost:2181(CONNECTED) 3] get /hbase/meta-region-server
�master:16000�Ciq�(PBUF

bigdata06�}�Ϯ��/ 

cZxid = 0x10000035d
ctime = Thu Mar 18 20:34:46 CST 2021
mZxid = 0x2400001ff9
mtime = Wed Nov 03 17:45:32 CST 2021
pZxid = 0x10000035d
cversion = 0
dataVersion = 54
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 56
numChildren = 0

后:

[zk: localhost:2181(CONNECTED) 7] get /hbase/meta-region-server   
?master:16000?~7??1?PBUF

	bigdata07?}????/ 

cZxid = 0x240000206e
ctime = Wed Nov 03 17:54:55 CST 2021
mZxid = 0x2400002070
mtime = Wed Nov 03 17:54:56 CST 2021
pZxid = 0x240000206e
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 56
numChildren = 0

得到结论

由于/hbase/meta-region-server不存在导致获取不到hbase:meta的位置信息(首次启动时可能因为region发生位置变化导致找不到meta的region)。即在加载namespcace时,无法获取namespace信息,导致启动Hbase失败。

修复元数据

利用hbase-client中操作zookeeper的方法,构造相同的参数,使用hbase-client去读写zookeeper节点。

	/**
     * 构造访问zookeeper的Watcher
     */
    public static ZKWatcher getZooKeeperWatcher(String quorum) throws IOException {

        //conf.set(HConstants.ZOOKEEPER_CLIENT_PORT, "2181");
        //conf.set(HConstants.CLIENT_ZOOKEEPER_QUORUM,"bigdata01");
        conf.set(HConstants.ZOOKEEPER_QUORUM,quorum);
        if (zooKeeperWatcher == null) {
            zooKeeperWatcher = new ZKWatcher(conf, "testing utility", new Abortable() {
                @Override
                public void abort(String why, Throwable e) {
                    throw new RuntimeException("Unexpected abort in HBaseZKTestingUtility:" + why, e);
                }

                @Override
                public boolean isAborted() {
                    return false;
                }
            });
        }
        return zooKeeperWatcher;
    }
	/**
     * 参数一 zookeeper连接信息
     * 参数二 元数据位置ServerName
     * 参数三 ENCODED
     */
    public static void main(String[] args) throws IOException, InterruptedException, KeeperException, DeserializationException {
        System.out.println("开始>>>>>>>>>>>>>>>>>>>>>");
        RegionState regionState;

        ZKWatcher zooKeeperWatcher = getZooKeeperWatcher(args[0]);

        // 写入
        ServerName serverName = ServerName.valueOf(args[1]);
        RegionState.State state = RegionState.State.valueOf("OPEN");
        int replicaId = Integer.parseInt(args[2]);

        if (serverName == null) {
            log.warn("Tried to set null ServerName in hbase:meta; skipping -- ServerName required");
            return;
        }
        log.info("Setting hbase:meta replicaId={} location in ZooKeeper as {}, state={}", replicaId,
                serverName, state);
        // Make the MetaRegionServer pb and then get its bytes and save this as
        // the znode content.
        MetaRegionServer pbrsr = MetaRegionServer.newBuilder()
                .setServer(ProtobufUtil.toServerName(serverName))
                .setRpcVersion(HConstants.RPC_CURRENT_VERSION)
                .setState(state.convert()).build();
        byte[] setData = ProtobufUtil.prependPBMagic(pbrsr.toByteArray());
        try {
            ZKUtil.setData(zooKeeperWatcher,
                    "/hbase/meta-region-server", setData);
        } catch(KeeperException.NoNodeException nne) {
            if (replicaId == RegionInfo.DEFAULT_REPLICA_ID) {
                log.info("hbase:meta region location doesn't exist, create it");
            } else {
                log.info("hbase:meta region location doesn't exist for replicaId=" + replicaId +
                        ", create it");
            }
            ZKUtil.createAndWatch(zooKeeperWatcher, "/hbase/meta-region-server",
                    setData);
        }
        System.out.println(">>>>>>>>>>>>元数据写入完成");

         // 读取
        System.out.println(">>>>>>>>>>>>元数据读取");
        byte[] data = ZKUtil.getData(zooKeeperWatcher, "/hbase/meta-region-server");
        regionState = ProtobufUtil.parseMetaRegionStateFrom(data, 0);
        System.out.println(">>>>>>>>>>>>>>>>" + regionState);
    }

www.htsjk.Com true http://www.htsjk.com/hbase/45715.html NewsArticle Hbase介绍,利用HadoopHD Hbase介绍 什么是Hbase Hbase是一个高可靠、高性能、面向列、可伸缩的分布式存储系统利用Hbase技术可在廉价的PC Server上搭建大规模结构化存储集群。 利用Hadoop HDFS作...
评论暂时关闭