博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Apache Hbase基本概念及Java API
阅读量:3958 次
发布时间:2019-05-24

本文共 7179 字,大约阅读时间需要 23 分钟。

一、Apache Hbase基本概述

Apache Hbase是一个基于Hadoop的数据库,它可靠、数据多版本、分布式适合结构化大数据的存储,Apache Hbase是Google BigTable开源实现,基于列储存的菲关系型数据库。

(1)列储存和行储存的区别

列储存和行储存是指数据子存储介质中的额储存方式

**·**关系型数据库(行储存):Oracle、mysql等
**·**非关系型数据库(列储存):Hbase、Redis
在这里插入图片描述

(2)Hbase数据模型及概念

在这里插入图片描述

(1)主键rowkey:获取数据的唯一标识,不能重复,根据字典顺序自动排序,底层储存时byte【】。
(2)列簇column family:多个列的集合,通常一个列簇中存放的是一组功能相近或者业务相近的集合。
(3)单元格cell:rowkey+column family + column定位一个cell,cell有多版本,默认为1个。
(4)多版本:cell允许有读个数据版本。
(5)版本号:系统当前的时间戳,默认会将时间戳最新的cell数据返回给用户。
(6)列column:colume列簇中的一个字段,用来存放某一类别的数据。

(3)Hbase特点:

(1)大:一个表可以有上百亿行上百万列。

(2)面向列:面向列表(列簇)的存储和控制权限
(3)结构稀疏:对于为空(NULL)的列,并不占用储存空间,因此,表可以设计的非常稀疏。
(4)无模式:每一行都有一个可以排序的主键和任意多的列,列可以根据需要动态增加,同一张表中的不同行可以有截然不同的列。
(5)数据多版本:每个单元格中的数据可以有多个版本,默认情况下,版本号自动分配,版本就是单元格插入时的时间戳。
(6)数据类型单一:Hbase中的数据在底层储存是都是byte【】,可以存放任意类型的数据。

(4)Hbase架构详解及完全分布式结构

完全分布式结构:

在这里插入图片描述
zookeeper作为hbase集群的入口(后面java api中从连接hbase的方式就能看出来)

hbase架构详解:

在这里插入图片描述
HBase中的每张表都通过rowKey按照一定的范围被分割成多个子表(HRegion),默认一个HRegion超过256M就要被分割成两个,这个过程由HRegionServer管理,而HRegion的分配由HMaster管理。

HMaster的作用:

(1)为HRegionServer分配HRegion

(2)负责HRegionServer的负载均衡
(3)发现失效的HRegionServer并重新分配
(4)HDFS上的垃圾文件回收
(5)处理Schema更新请求

HRegionServer的作用:

(1)维护HMaster分配给它的HRegion,处理对这些HRegion的IO请求

(2)负责切分正在运行过程中变得过大的HRegion

可以看到,Client访问HBase上的数据并不需要HMaster参与,寻址访问ZooKeeper和HRegionServer,数据读写访问HRegionServer, HMaster仅仅维护Table和Region的元数据信息,Table的元数据信息保存在ZooKeeper上,负载很低。HRegionServer存取一个子表时,会创建一个HRegion对象,然后对表的每个列簇创建一个HStore对象,每个HStore都会有一个MemStore和0或多个StoreFile与之对应,每个StoreFile都会对应一个HFile,HFile就是实际的存储文件。因此,一个HRegion有多少列簇就有多少个Store。 一个HRegionServer会有多个HRegion和一个HLog。

HRegion

Table在行的方向上分割为多个HRegion,HRegion是HBase中分布式存储和负载均衡的最小单元,即不同的HRegion可以分别在不同的HRegionServer上,但同一个HRegion是不会拆分到多个HRegionServer上的。HRegion按大小分割,每个表一般只有一个HRegion,随着数据不断插入表,HRegion不断增大,

当HRegion的某个列簇达到一个阀值(默认256M)时就会分成两个新的HRegion。

1、
<表名,startrowkey, 创建时间>
2、由目录表(-ROOT-和.META.)记录该Region的EndRowKeyHRegion定位:HRegion被分配给哪个HRegionServer是完全动态的,所以需要机制来定位HRegion具体在哪个HRegionServer,HBase使用三层结构来定位HRegion: 1、通过zk里的文件/hbase/rs得到-ROOT-表的位置。-ROOT-表只有一个region。 2、通过-ROOT-表查找.META.表的第一个表中相应的HRegion位置。其实-ROOT-表是.META.表的第一个region; .META.表中的每一个Region在-ROOT-表中都是一行记录。 3、通过.META.表找到所要的用户表HRegion的位置。用户表的每个HRegion在.META.表中都是一行记录。 -ROOT-表永远不会被分隔为多个HRegion,保证了最多需要三次跳转,就能定位到任意的region。Client会将查询的位置信息保存缓存起来,缓存不会主动失效, 因此如果Client上的缓存全部失效,则需要进行6次网络来回,才能定位到正确的HRegion,其中三次用来发现缓存失效,另外三次用来获取位置信息。

HStore

每一个HRegion由一个或多个HStore组成,至少是一个HStore,HBase会把一起访问的数据放在一个HStore里面,即为每个ColumnFamily建一个HStore,如果有几个ColumnFamily,也就有几个HStore。一个Store由一个MemStore和0或者多个StoreFile组成。 HBase以Store的大小来判断是否需要切分HRegion。

MemStore

MemStore 是放在内存里的,保存修改的数据即keyValues。当MemStore的大小达到一个阀值(默认64MB)时,MemStore会被Flush到文件, 即生成一个快照。目前HBase会有一个线程来负责MemStore的Flush操作。

StoreFile

  MemStore内存中的数据写到文件后就是StoreFile,StoreFile底层是以HFile的格式保存

HLog

  HLog(WAL log):WAL意为write ahead log,用来做灾难恢复使用,HLog记录数据的所有变更,一旦region server 宕机,就可以从log中进行恢复。

简单描述一下Hbase故障恢复的过程:

Hmaster发现某些HregionServer不可用,开始故障恢复,获取故障的HregionServer的Hlog,分离每一个HRegion写指令,重新分配Hregion,在配到HregionServer中恢复HRegion数据,执行分离的HRegion写指令恢复MemStore,持久化完成的数据可以直接从HDFS中获取。

(二)Hbase Java API

org.apache.hbase
hbase-client
1.2.4
org.apache.hbase
hbase-common
1.2.4
org.apache.hbase
hbase-protocol
1.2.4
org.apache.hbase
hbase-server
1.2.4
junit
junit
4.12
org.apache.hbase
hbase-client
1.2.4
org.apache.hbase
hbase-common
1.2.4
org.apache.hbase
hbase-protocol
1.2.4
org.apache.hbase
hbase-server
1.2.4
junit
junit
4.12
package com.learn;import org.apache.hadoop.conf.Configuration;import org.apache.hadoop.hbase.*;import org.apache.hadoop.hbase.client.*;import org.apache.hadoop.hbase.util.Bytes;import org.junit.After;import org.junit.Before;import org.junit.Test;import java.io.IOException;import java.util.ArrayList;import java.util.Iterator;public class HbaseAPI {    private Admin admin;    private Connection connection;    @Before    public void doBefore() throws IOException {        Configuration configuration = HBaseConfiguration.create();        configuration.set(HConstants.ZOOKEEPER_QUORUM,"192.168.139.156:2181");        connection = ConnectionFactory.createConnection(configuration);        admin = connection.getAdmin();    }    @Test    public void testCreateNameSpace() throws IOException {        NamespaceDescriptor namespaceDescriptor = NamespaceDescriptor.create("gaoj").addConfiguration("author", "gaojian").build();        admin.createNamespace(namespaceDescriptor);    }    @Test    public void testCreateTable() throws IOException {        HTableDescriptor hTableDescriptor = new HTableDescriptor(TableName.valueOf("gaoj:t_order"));        HColumnDescriptor cf1 = new HColumnDescriptor("cf1");        cf1.setMaxVersions(3);        HColumnDescriptor cf2 = new HColumnDescriptor("cf2");        cf2.setTimeToLive(1800);        hTableDescriptor.addFamily(cf1);        hTableDescriptor.addFamily(cf2);        admin.createTable(hTableDescriptor);    }    @Test    public void testInsert() throws IOException {        Table table = connection.getTable(TableName.valueOf("gaoj:t_order"));        Put put = new Put(Bytes.toBytes("order101"));        put.addColumn(Bytes.toBytes("cf1"),Bytes.toBytes("count"),Bytes.toBytes(123));        table.put(put);    }    @Test    public void testSelect() throws IOException {        Table table = connection.getTable(TableName.valueOf("gaoj:t_order"));        Get get = new Get(Bytes.toBytes("order101"));        Result result = table.get(get);        String name = Bytes.toString(result.getValue(Bytes.toBytes("cf1"), Bytes.toBytes("name")));        System.out.println(name);    }    @Test    public void testDelete() throws IOException {        Table table = connection.getTable(TableName.valueOf("gaoj:t_order"));        Delete delete = new Delete(Bytes.toBytes("order101"));        ArrayList
list = new ArrayList
(); list.add(delete); table.delete(list); } @Test public void testScan() throws IOException { Table table = connection.getTable(TableName.valueOf("gaoj:t_order")); Scan scan = new Scan(); ResultScanner scanner = table.getScanner(scan); Iterator
iterator = scanner.iterator(); while (iterator.hasNext()){ Result next = iterator.next(); String row = Bytes.toString(next.getRow()); String name = Bytes.toString(next.getValue(Bytes.toBytes("cf1"), Bytes.toBytes("name"))); System.out.println(row + "*" + name); } } @After public void doAfter() throws IOException { if(admin != null){ admin.close(); } if(connection != null){ connection.close(); } }}

以上api实现了数据的增删改查,关于Hbase,更多的掌握的是API的使用,在学习的过程中,我们可以使用help指令帮助学习。

转载地址:http://simzi.baihongyu.com/

你可能感兴趣的文章
网络 https 握手
查看>>
去掉调试信息
查看>>
lsof 使用
查看>>
golang获取本机地址
查看>>
date 使用
查看>>
ipcalc
查看>>
网络 linux 禁止 ping
查看>>
ELF 格式详解
查看>>
chromium 使用
查看>>
linux 检测虚拟机类型
查看>>
go - 运行时:内存不足
查看>>
top 使用
查看>>
Linux Netlink通信机制详解
查看>>
rsync 远程同步
查看>>
nano使用
查看>>
c函数
查看>>
linux 链接
查看>>
centos6.x 添加开机启动服务
查看>>
zfs 简单使用
查看>>
linux EXT4格式分区扩容
查看>>