分布式存储系统——HBase

一、什么是Hbase?

HBase-Hadoop Database,是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用HBase技术可在廉价PC Server上搭建起大规模结构化存储集群。当你需要对庞大数据量(上至千万亿字节)进行随机实时读写操作时,HBase是一个很好的选择。不同于传统的关系型数据库,HBase是一种非关系型数据库,即NoSQL数据库。

      Google三驾马车:GFS、MapReduce和BigTable代表Google针对大数据存储与处理提出的三种框架。其中,GFS是面向大规模数据密集型应用的、可伸缩的分布式文件系统(HFDS);MapReduce是处理海量数据的分布式并行计算的执行框架(MapReduce);BigTable是处理海量数据的分布式结构化数据存储系统。HBase的体系结构是一个主从架构,主节点HMaster在整个集群中只有一个Active,从节点HRegion Server有多个运行,整个集群通过Zookeeper(单数)来维护集群中的Server状态,Zookeeper存储顶级索引入口。

      底层实现:布隆过滤器+跳表(多层索引表,每个索引范围数据存储不同节点),Java语言编写

1、Hbase基本概念

表(Table:HBase将数据组织成表;

行(Row:在表内,数据存储在其对应的行中。每一行都有一个唯一的行键(Row Key进行标识。

列族(Column Family:在行内,数据被分组为不同的列族。同一张表中,每一行列族的划分都是相同的。同时列族必须作为表模板预先定义好。

列限定符(Column Qualifier:或称为列(Column,以列族作为前缀,每个列族可有有多个列成员中,如列族名:列限定符名。与列族不同的是,每行的列限定符都可以不相同,也不需要在建表时定义。

单元格(Cell:一组行键、列族和列限定符的组合标明了一个唯一的单元格。存储在单元格中的数据被称作单元格的值(Value)。

时间戳(Timestamp:每个单元格的值都是版本化的,有一至多个版本(Version,每个版本由其版本号标明。默认情况下,版本号是其对应值写入单元格时给定的时间戳,若写入值时未给定时间戳,则时间戳为写入时的当前时间;若读取值时未给定时间戳,则返回最新的版本。

2、HBase架构的优点

强一致性:当Write放回时,所有的reader都会读到同样的值;

自动扩展性:数据变大时region会分裂,使用HDFS存储备份数据;

内置恢复功能:使用WAL实现故障恢复;

Hadoop结合:底层使用MapReduce处理HBase数据。

3、Hbase数据模型

(1)表模型

数据模型展现了两行存储在HBase表中的两行数据,此表有两个列族,行与列的交叉点为单元格,每个单元格中的数据又分为多个版本。要注意的是,表中的每行都要有相同的列族,却可以有不同的列限定符

(2)“多维键值对”模型

HBase表的第一行数据呈现为了多维键值对。当检索行键“00001”下的列族“HikDepartment”时,将得到该列族下的“Primary”和“Secondary”两组键值对。

4、Hbase架构组件

HBase是由三种类型的server组成的主从架构:

Region Server:负责管理Region处理数据的读写请求,客户端请求数据时直接和Region Server交互。

HBase Master:负责Region的分配,DDL(创建,删除)等操作。

Zookeeper:作为HDFS的一部分,负责维护集群状态。

:Hadoop DataNode负责存储Region Server所管理的数据,HBase所有数据都存储在HDFS文件中。Region Server与HDFS DataNode往往向数据靠拢,即数据本地化。

Regions:是HBase的最小数据单元,table根据rowkey的范围被水平拆分为若干个Region,每个Region包含了start key和end key之间的所有行,所有Region统一由Region Server管理,进行数据的读写。

HBase Master:即HMaster,1)监控集群中和所有的Region Server,在集群启动时分配Region,故障恢复和负载均衡时重新分配Region;2)向Client提供创建、删除和更新HBase Table的接口。

Zookeeper:维护HBase集群中所有服务的状态,维护集群的健康情况和故障通知,同时使用一致性协议(ZAB)保证分布式状态一致性(单数台机器)。Zookeeper与active HMaster、Region Server保持会话(Session),并通过心跳检测维护所有临时节点。HMaster们会竞争创建临时节点,Zookeeper决定谁作为active HMaster,其他作为Standby,然后active HMaster监控每个Region Server(每个创建一个临时节点)。

HBase Meta Table:是一个特殊的HBase table,保存了系统中所有region列表,类似一个b-tree,Zookeeper保存了meta table的位置。其结构为:

Key:table,region start key,region id

Value:region server

Region Server由四个部分构成,具体分为如下:

WAL:Write Ahead Log,用于存储新的还未被持久化存储的数据,被用来做故障恢复

BlockCache:读缓存,在内存中存储了最常访问的数据,采用LRU(Least Recently Used)缓存。

MemStore:写缓存,在内存中存储了还未被持久化到硬盘的数据,当数据写入磁盘时,数据会首先被排序,每个Region的每个Column Family都会有一个MemStore,所有更新都以Column Family为单位进行排序。

HFile:在磁盘上(HDFS)存储的数据,以有序键值对形式,当MemStore累积了足够多的数据后,整个有序数据集就会被写入一个新的Hfile文件,整个过程是一个顺序写操作,不需要移动磁盘头,因此速度非常快。

HFile使用多次索引来查询数据而不必读取整个文件,这种多层索引类似于一个B+ tree:

  1. KeyValue有序存储;
  2. Rowkey指向index,而index则指向具体的data block;
  3. 每个block都有它的叶索引;
  4. 每个block的最后一个key都被索引在中间层索引;
  5. 索引根节点指向中间层索引。

其中,HFile被打开时会被载入内存,这样数据查询只要一次硬盘查询。

HBase读写流程

1) 第一次读操作:

 

  1. Client从Zookeeper获取哪一台Region Server负责管理Meta table;
  2. Client查询管理Meta table的Region Server,获取哪一台Region Server本次数据请求需要的rowkey,然后Client缓存该信息,以及Meta table的位置信息;
  3. Client访问对应Region Server,获取数据。

2) HBase写数据流程:

当Client发起一个写操作请求,第一步首先将数据写入到WAL中,新数据会被追加到WAL文件尾部,数据被写入WAL后,会被加入到写缓存MemStore中,然后服务端向Client返回ACK应答。

HBase Region Flush

当MemStore中累积了足够多的数据后,整个有序数据集就会被写入一个新的HFile文件到HDFS上,然后记录最后写入数据的最大序列号(sequence number。HBase同样为每个Column Family都创建一个HFile,里面存储了具体的Cell。

3) HBase读数据流程:

因为缓存,写入的时间不同,读取某行(rowkey)的cell时,数据可能位于不同地方。因此一次读操作系统会将BlockCache,MemStore和HFile中的Cell进行合并:

  1. 首先Sacnner从BlockCache读取Cells;
  2. 然后Scanner读取MemStore;
  3. 最后HBase会使用BlockCache中的索引和布隆过滤器加载对应的HFile到内存。

注:每个MemStore可能会有多个HFile,所以一次读操作可能需要读多个文件,则可能影响性能,这被称为读放大(Read Amplification

HBase Minor Compaction

HBase会自动合并一些小的HFile,重写成少量更大的HFile,该过程被称为Minor Compaction,使用归并排序算法,将小文件合成大文件,有效减少HFile数量。

HBase Major Compaction

Major Compaction合并重写每个Column Family下的所有HFile,成为一个单独的HFile,过程中,被删除和过期的数据真正意义上被删除,该过程会重写所有HFile,提高读性能,但是会产生大量IO和网络开销,因此安排在半夜和周末执行,这种被称为写放大(Write Amplification

Region分裂

一开始每个table只有一个region,当一个region逐渐变得很大时,它会分裂(split)成两个字region,每个region都包含原来一半的数据,这两个region并行在原Region Server上创建,分裂动作会报告给HMaster,(处于负载均衡目的,HMaster可能会将新的region迁移至其他Region Server)。

Read负载均衡

Splitting出于负载均衡会将新的Region迁移至其他Region Server,这会导致那些Region Server需要访问离它比较远的HDFS数据,直到major compaction到来,会将那些远方的数据重新迁移到region server节点附件的地方。

HDFS数据备份

所有读写都发生在HDFS的主DataNode节点上,HDFS会自动备份WAL和HFile的文件blocks,HBase依赖HDFS保证数据的完整安全,当数据写入HDFS时,一份写入本地节点,另外两个备份会被写入其他节点。

 

HBase故障恢复

当HMaster发现某个region server故障,HMaster会将这个region server所管理的regions分配给其他健康region server,为了恢复故障region server中MemStore还未被持久化到HFile的数据,HMaster会将WAL分割为几个文件,将他们保存到不同新的region server,每个region server回放自己拿到的WAL碎片中的数据,为它们分配到新的Region建立Memstore。

HBase读操作

1、从Zookeeper拿到meta表信息
2、根据rowkey确定往哪个RegionServer写
3、写MemStore内存同时记录日志
4、内存满后刷写StoreFile
5、StoreFile一定条件下触发合并

HBase写操作

1、从Zookeeper拿到meta信息

2、找到数据分布的RegionServer

3、分别在MemStore和StoreFile查找

4、根据数据版本组织key-value进行返回

二、基本操作

根据使用场景的不同,HBase提供了两种方式操作集群:(1)在Linux  Shell环境下利用HBase自带的HBase shell脚本;(2)支持Rest风格的Http API访问HBase(3)HBase对多种编程语言提供的API调用,演示以Java API为例。

1、HBaseshell脚本操作:

(1)HBase集群的启动与停止

启动

./bin/start-hbase.sh 

/单例HMaster进程

 ./bin/hbase-daemon.sh start master 

单例HRegionServer进程

 ./bin/hbase-daemon.sh start regionserver

停止

./bin/stop-hbase.sh 

单例HMaster进程

 ./bin/hbase-daemon.sh stop master  

单例HRegionServer进程

./bin/hbase-daemon.sh stop regionserver

(2)启动Shell客户端脚本

--Hbase shell

--status   状态查看

--version   版本查看

(3)表的相关操作

list—— 列出HBase中存在的所有表

create  ‘表名’ , ‘列族1’ , ‘列族2’ , ‘列族N’—— 创建表

desc/describe  ‘表名’—— 查看表的基本信息

enable/disable  ‘表名’—— 启用/禁用表

is_ enable/ is_ disable  ‘表名’—— 查看该表是否启用/禁用

(4)增删改

drop  ‘表名’—— 删除表 注:删除前先禁用disable  ‘表名’

alter  ‘表名’ , ‘列族名’—— 添加列族

alter  ‘表名’ , {NAME => ‘列族名’ , METHOD=>‘delete’}—— 删除列族

alter  ‘表名’ , {NAME => ‘列族名’ , VERSION=>3}—— 更改列族存储版本

put  ‘表名’ , ‘行键’ , ‘列族:列’ , ‘值’—— 插入数据

delete  ‘表名’ , ‘行键’ , [ ‘列族:列’]—— 删除指定行、列的信息

(5)查询

HBase中访问数据有两种基本的方式:

  1. 按指定rowkey获取数据:get方法
  2. 按指定条件获取数据:scan方法

get  ‘表名’ , ‘行键’ , [‘列族’ / ‘列族:列’]—— 获取指定行、列族、列的信息

scan ‘表名’ —— 查询整表数据

scan ‘表名’ , {COLUMN=>[‘列族’ / ‘列族:列’]}—— 查询列族/列的数据

scan ‘表名’ , FILTER=>”ValueFilter (=,’binary:xx / substring:yy’) / CoulmnPrefixFilter ‘zz’) [AND / OR] ”—— 条件查询值等XX / 值包含YY /列名前缀为ZZ / [多条件查询]的数据

scan ‘表名’ , FILTER=>”PrefixFilter(‘xx’)”—— 查询Rowkey前缀判断

2、HBaseJava API操作:

(1)创建配置信息

//创建配置文件
Configuration conf = new Configuration();
conf.set("hbase.zookeeper.quorum","10.3.69.118");
conf.set("hbase.zookeeper.property.clientPort","31704");
conf.set("zookeeper.znode.parent","/hbp_root/kobe/hbase");

注:Hbase是基于Zookeeper维护的服务,配置Hbase的服务IP、端口Port以及操作文件路径。

(2)建立连接

connection = ConnectionFactory.createConnection(conf);

Admin admin = connection.getAdmin();

(3)创建表

HBase2.0.0之前:

TableName tableName = TableName.valueOf("table_name");

HTableDescriptor htable = new HTableDescriptor(tableName);

HColumnDescriptor family = new HColumnDescriptor("family_name");

htable.addFamily(family);

admin.createTable(htable);

HBase2.0.0之后弃用HTableDescriptor和HColumnDescriptor,并在HBase3.0.0之后彻底删除,使用TableDescriptorBuilder和ColumnFamilyDescriptor替代。

HBase2.0.0之后:

//创建表名为HBase_test的表

TableName tableName = TableName.valueOf("HBase_test");

TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(tableName);

//创建列族1

ColumnFamilyDescriptor family1 = ColumnFamilyDescriptorBuilder.of("column_1");

tableDescriptorBuilder.setColumnFamily(family1);

//创建列族2

ColumnFamilyDescriptor family2 = ColumnFamilyDescriptorBuilder.of("column_2");

tableDescriptorBuilder.setColumnFamily(family2);

TableDescriptor build = tableDescriptorBuilder.build();

admin.createTable(build);

(4)增加数据

//向'hbasetest'数据表插入数据

TableName name = TableName.valueOf("hbasetest");

Table htable = connection.getTable(name);

String rowkey = "r1";

for(int i=0;i<3;i++){

    //操作put对象

    Put put = new Put(Bytes.toBytes(rowkey));

    put.addColumn("cf".getBytes(),"name1".getBytes(),"this is name1".getBytes());

    put.addColumn("cf".getBytes(),"name2".getBytes(),"this is name2".getBytes());

    put.addColumn("cf".getBytes(),"age1".getBytes(),"this is age1".getBytes());

    put.addColumn("cf".getBytes(),"age2".getBytes(),"this is age2".getBytes());

    put.addColumn("cf".getBytes(),"time1".getBytes(),"this is time1".getBytes());

    put.addColumn("cf".getBytes(),"time2".getBytes(),"this is time2".getBytes());

    htable.put(put);

}

htable.close();

(5)查看所有数据表

//遍历HBase中的所有数据表

    for(TableName index:admin.listTableNames()){

        System.out.println(index);

    }

  (6)按行键查询数据

TableName name = TableName.valueOf("hbasetest");

            Table htable = connection.getTable(name);

            String rowkey = "r1";

            //获取数据

            Get get = new Get(Bytes.toBytes(rowkey));

            Result result = htable.get(get);

            for(Cell kv:result.rawCells()){
System.out.println(Bytes.toString(CellUtil.cloneValue(kv)));

            }

            htable.close();


 

 

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值