16. HBase高级应用

1. HBase存储中的3个核心机制

1.flush机制:
当MemStore达到阈值之后,会flush成一个StoreFile (也就是内存中的数据写入了磁盘)。
2.compact机制:
当StoreFile达到阈值时,合并StoreFile。合并过程中cell版本合并和数据删除。
3.split机制:
当region不断增大,达到阈值,region会分成两个新的region。

2.HBase Java API使用

1. 为HBase Java编程准备开发环境

使用java进行HBase编程,pom文件需要添加2个依赖,分别是hbase-client 、 hbase-server(可以没有)、hadoop-client。

查看HBase的API文档,以下几个类是比较常用的,需要熟悉:
HBaseAdmin (管理操作、创建表等)
HTable (操作表、上传数据)
Configuration

HBase的java API开发与HBase shell的命令基本上是一致的。例如shell中的put操作,对应着API中的Put对象。

2. 添加IDE依赖的jar包:

HBase的开发,需要在pom.xml中引入 hbase-client、hbase-server和hadoop-client几个依赖包(选取的版本是:hadoop: 2.5.0 ; hbase:0.98.6-hadoop2),如下是pom.xml定义:

<properties>
    <hadoop.version>2.5.0</hadoop.version>
    <hbase.version>0.98.6-hadoop2</hbase.version>
</properties>
<dependencies>
    <!-- hbase client -->
    <dependency>
      <groupId>org.apache.hbase</groupId>
      <artifactId>hbase-client</artifactId>
      <version>${hbase.version}</version>
    </dependency>
    
    <dependency>
      <groupId>org.apache.hbase</groupId>
      <artifactId>hbase-server</artifactId>
      <version>${hbase.version}</version>
    </dependency>
    
    <!-- hadoop client -->
    <dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-client</artifactId>
      <version>${hadoop.version}</version>
    </dependency>
</dependencies>

3. 添加配置文件:

需要将HBase和Hadoop的配置文件,添加到项目的Classpath。新建“Source Folder”:src/main/resources,将hadoop和hbase安装目录下的配置文件挪到这个目录下(主要是core-site.xml、hdfs-site.xml和hbase-site.xml):


Resources文件.png

4. 获取HBase配置环境信息:

在使用Java API时,Client端需要知道HBase的环境配置,使用Configuration类来封装该信息。

Configuration conf = HBaseConfiguration.create();

在创建该对象时,首先在classpath中寻找hbase-site.xml文件来读取配置,如果不存在该文件,则寻找hbase-default.xml文件来读取配置(也就是默认配置)。

5. Get获取数据:

使用Get对象获取数据:

      // 抽象的获取HTable对象的静态方法,返回HTable对象
    public static HTable getTable (String tablename) throws IOException {
        Configuration conf = HBaseConfiguration.create();
        HTable table = new HTable(conf,tablename);
        return table;
    }
    
    //根据row_key返回这条记录中的信息
    public static void getByRowKey(String tablename,String rowkey) 
            throws IOException
    {
        HTable table = HBaseAPIOper.getTable(tablename);
        
        //Get Object is bound to one row(identified by rowkey)
        Get get = new Get(Bytes.toBytes(rowkey));
        
        Result rs = table.get(get);
        
        Cell[] cells = rs.rawCells();
        for (Cell cell : cells){
            System.out.print( Bytes.toString(CellUtil.cloneFamily(cell)) + ":" );
            System.out.print( Bytes.toString(CellUtil.cloneQualifier(cell)) + "=>" );
            System.out.print( Bytes.toString(CellUtil.cloneValue(cell)) + "\n"  );
        }
        
        table.close();
    }
    
    //返回某个row_key、某个列族、某个列的数据(只返回指定列的信息)
    public static void getByColumns (String tablename,String rowkey,
            String family,String qualifier) throws IOException{
        HTable table = HBaseAPIOper.getTable(tablename);
        
        //Get Object is bound to one row(identified by rowkey)
        Get get = new Get(Bytes.toBytes(rowkey));
        
        get.addColumn(Bytes.toBytes(family), Bytes.toBytes(qualifier));
        
        Result rs = table.get(get);
        
        Cell[] cells = rs.rawCells();
        for (Cell cell : cells){
            System.out.print( Bytes.toString(CellUtil.cloneFamily(cell)) + ":" );
            System.out.print( Bytes.toString(CellUtil.cloneQualifier(cell)) + "=>" );
            System.out.print( Bytes.toString(CellUtil.cloneValue(cell)) + "\n"  );
        }
        
        table.close();
    }

Get get = new Get(rowkey的字节数组)。 Get对象和rowkey进行绑定。Result result = HTable对象.get(Get对象)。下面遍历结果集,使用rawCells()方法,获取所有查到的单元格信息。CellUtil类,是用于操作单元格的工具类,CellUtil.cloneFamily()获取列族信息,CellUtil.cloneQualifier()获取列信息,CellUtil.cloneValue()获取对应的值。为了防止资源使用崩溃,一定要记得关闭table对象
同时,也可以通过操作Get对象,来限定只显示部分列。get.addColumn("列族","列名")

6. Put插入数据:

实体信息的插入,通过put操作完成。

// Put rows by rowkey (Auto Generated!!)
    public static void putRows(String tablename) throws IOException{        
        HTable table = HBaseAPIOper.getTable(tablename);
        long rowkey = System.currentTimeMillis();
        // The Integer rowkey must be cast to String.
        Put put0 = new Put(Bytes.toBytes(Long.toString(rowkey)));
        put0.add(
                Bytes.toBytes("info"), 
                Bytes.toBytes("name"), 
                Bytes.toBytes("natty") 
                )   ;
        put0.add(
                Bytes.toBytes("info"), 
                Bytes.toBytes("age"), 
                Bytes.toBytes("31") 
                )   ;
        
        // The Integer rowkey must be cast to String.
        Put put1 = new Put(Bytes.toBytes(Long.toString(rowkey + 1)));
        put1.add(
                Bytes.toBytes("info"), 
                Bytes.toBytes("name"), 
                Bytes.toBytes("natty") 
                )   ;
        put1.add(
                Bytes.toBytes("info"), 
                Bytes.toBytes("age"), 
                Bytes.toBytes("31") 
                )   ;
        
        ArrayList<Put> list = new ArrayList<Put>();
        list.add(put0);
        list.add(put1);
        table.put(list);
        table.close();
    }

put操作对应于Put对象。创建Put对象, Put put = new Put(rowkey对应的字节数组);之后添加列信息,put.add("列族","列名","列值"),通过多次put.add()可以一次添加多个列值信息。将列信息添加到表格,表格对象.put(Put对象),或者添加多个put对象,表格对象.put(含有多个Put对象的list集合)。

7. Delete删除数据和Update数据:

删除数据需要使用Delete对象, Delete delete = new Delete(行键对应的字节数组)。指定要删除的列(列族),delete.deleteColumn("列族","列名")

    public static void deleteByRowkey(String tablename,String rowkey) 
            throws IOException{
        HTable table = HBaseAPIOper.getTable(tablename);
        Delete del = new Delete(Bytes.toBytes(rowkey));
        
        //delete all the family
        del.deleteFamily(Bytes.toBytes("info"));
        //delete just one column
        del.deleteColumn(Bytes.toBytes("info"), Bytes.toBytes("name"));
        table.delete(del);
        table.close();
    }

HBase中Update操作也使用Put对象完成,操作方法与插入操作完全一致。

8. Scan操作:

ResultScanner是由查询结果Result对象组成的,可以通过2次遍历获取数据。getRow()获得行键。另外,也可以使用IOUtils.closeStream()来关闭table对象等资源。通过setStartRow()和setStopRow()方法,限定scan的查询范围。通过scan.addFamily()或者scan.addColumn()增加通过列族/列筛选数据。

    public static void scanByTable(String tablename) throws IOException
    {
        HTable table = HBaseAPIOper.getTable(tablename);
        
        Scan scan = new Scan();
        //make the scope of scan.
        // >= setStartRow()  AND  < setStopRow() 
        scan.setStartRow(Bytes.toBytes("10001"));
        scan.setStopRow(Bytes.toBytes("10004"));
        
        //filter the data through Family or Column
        scan.addFamily(Bytes.toBytes("info"));
        scan.addColumn(Bytes.toBytesBinary("info"), Bytes.toBytes("name"));
        
        ResultScanner resultscanner = table.getScanner(scan);
        
        for (Result result:resultscanner)
        {
            // getRow() method can get the rowkey.
            System.out.println(Bytes.toString(result.getRow()));
            Cell[] cells = result.rawCells();
            for (Cell cell : cells){
                System.out.print( Bytes.toString(CellUtil.cloneFamily(cell)) + ":" );
                System.out.print( Bytes.toString(CellUtil.cloneQualifier(cell)) + "=>" );
                System.out.print( Bytes.toString(CellUtil.cloneValue(cell)) + "\n"  );
            }
        }
        IOUtils.closeStream(resultscanner);
        IOUtils.closeStream(table);
    }

3.HBase架构深入总结

1.客户端作用:

1.整个HBase集群的访问入口;
2.使用HBase RPC机制与HMaster 和 HRegionServer通信。
3.与HMaser通信进行管理类操作。
4.与HRegionServer通信进行数据读写类操作。

2.Zookeeper作用:

1.实现HMaster的HA,保证集群中只有一个HMaster。
2.保存root region的位置(meta表),Region的寻址入口。
客户端在访问表时,需要找到表的每个region对应的RegionServer(管理Region的角色)。Root(新版本是meta)表存储了Region的分布情况以及每个Region的详细信息。
3.实时监控RegionServer的上下线信息,并及时通知Master。
4.存储HBase的schema和table元数据(有哪些表、每个表有哪些列族)。

3.HMaster作用和特点:

1.HMaster作用:
(1). HMaster负责Table和Region的管理工作,为RegionServer分配Region。
(2). 管理Region Server的负载均衡(为每一个Region Server分配多少Region),调整Region分布。
(3). 当某一个Region Server停机下线后,负责失效Region Server上的Region的迁移。
(4). 监听zookeeper,基于zookeeper来得知Region Server上下线。
(5). 监听zookeeper,基于zookeeper来保证Master的HA
2.HMaster的特点:
(1)HMaster没有单点故障问题(SPOF:Single Point Of Failure)。HBase可以启动多个HMaster,Zookeeper保证只有一个HMaster运行。
启动backup master节点方法:在conf下修改配置文件backup-masters,通过hbase-daemons.sh脚本启动backup master。

$bin/hbase-daemons.sh start master-backup

(2)不参与客户端数据读写
(3)HMaster的负载很低(在同一个主机上可以和NN、SNN等服务共同运行)。

4.Region Server的作用:

  1. 维护Region(HMaster分配的),响应客户端的IO访问请求(读写),向HDFS读写数据。
  2. 负责处理region的 flush、compact、split 几个过程。
  3. 维护region的cache
HBase与Zookeeper的关系.png

4.HBase数据检索三种方式

HBase的数据检索,主要提供了3种方式,分别是:Get方式检索、Scan范围检索、Scan全表扫描。

  1. Get方式:
    Get需要使用rowkey作为参数检索。
    在hbase shell中使用get命令
    在java API中使用Get对象。
  2. Scan 范围搜索:
    依据rowkey匹配查找,默认根据rowkey匹配
    在hbase shell中使用scan命令
    在java API中使用Scan对象。
  3. Scan 全部扫描:
    全表扫描
    和MapReduce/Spark一起使用。

5.HBase与MapReduce集成

1.HBase和MapReduce的整合场景:

第一种应用场景: 文本文档txt或者csv文件导入到HBase中。
第二种应用场景: HBase的表导成另外一个表。
Data Source(数据源): 。本地、HBASE表、HDFS
Data Sink: 数据写进哪个地方。
Data Source & Data Sink:

2.HBase和MapReduce的原因和方法:

  1. 为什么使用MapReduce导入:
    MapReduce是并行处理框架,比较快。
  2. HBase和MapReduce整合的方法:
    使用如下命令可以返回hbase的classpath的jar包:
$ bin/hbase mapredcp

查看命令的具体含义:

$ bin/hbase 

3.HBase的默认MapReduce程序:

HBase默认集成了一些mapreduce程序。这些程序存放在这个jar包(HBase的安装目录下)中 :
/opt/modules/hbase-0.98.6-cdh5.3.6/lib/hbase-server-0.98.6-cdh5.3.6.jar
下面,我们执行这个jar包:
(1) 导入HBASE_CLASS path环境变量:

export HADOOP_HOME=/opt/modules/hadoop-2.5.0-cdh5.3.6
export HBASE_HOME=/opt/modules/hbase-0.98.6-cdh5.3.6
export HADOOP_CLASSPATH=`$HBASE_HOME/bin/hbase mapredcp`

上边步骤设置HBase的CLASSPATH。变量引入,一般写进shell脚本,跟随job任务执行的命令一起。如果要写入/etc/profile 会永久生效,并且需要加export。

(2)通过yarn执行mapreduce的jar包:
查看整个jar包所提供的所有功能:

$ /opt/modules/hadoop-2.5.0-cdh5.3.6/bin/yarn jar /opt/modules/hbase-0.98.6-cdh5.3.6/lib/hbase-server-0.98.6-cdh5.3.6.jar 
Paste_Image.png

(3)通过mapreduce查看某个表的行数(rowkey的个数):
$ /opt/modules/hadoop-2.5.0-cdh5.3.6/bin/yarn jar /opt/modules/hbase-0.98.6-cdh5.3.6/lib/hbase-server-0.98.6-cdh5.3.6.jar rowcounter 'user'

4.自定义HBase的MapReduce程序:

5.HBase数据迁移工具importTsv:

HBase存在较多数据迁移的场景:例如,需要将一个数据文件直接导入到HBase表中,还有将生产集群的数据迁移到测试集群等等。
ImportTsv是HBase官方提供的基于MapReduce的批量数据导入工具。ImportTsv是一个命令行工具,可以将存储在HDFS上的自定义分隔符(默认\t)的数据文件,通过一条命令导入到HBase表中,非常适合大数据量导入。
下面运行一个实例来演示导入过程:
(1)创建一个将要导入的测试文件:
(2)上传该文件到HDFS上的指定目录:
(3)HBase建表:
(4)开始运行MapReduce执行导入。
(5)验证结果。

6. 使用BulkLoad加载数据:

6.创建HBase表

创建HBase有常见的三种方式:
1.创建表时,指定region划分方式(根据rowkey)

create 'tb1','fa1',SPLITS => ['10','20','30','40']

tb1表有五个Region。SPLITS根据rowkey来将记录分配到各自的region中:


Region划分.png

2.创建表时,通过文件来将表划分为多分区(最常用方式):
将分区范围放在一个物理文件中,然后在创建表时指定这个文件。例如定义下面一个regions.txt文件:

20170605
20170606
20170607
20170608
20170609
20170610

下面创建表,根据这个文件指定划分region。

create table 'tb2','fa2',SPLITS_FILE => '/home/natty/hbase/regions.txt',OWNER => 'natty'

需要注意,这里建议使用绝对路径来指定文件。
3.指定分区的数量,创建表:

create table 'tb3','fa3',{NUMREGIONS => 15, SPLITALGO => 'HexStringSplit'}

如果指定region的起止范围,系统可以自动定义。

7. HBase的RowKey设计

1.表结构设计:

最核心的内容是设计rowkey。设计rowkey的要点:
1.根据需求设计,查询速度快。
2.尽量覆盖更多业务场景,增加复用的可能性。
3.离线设计,避免热点

2.案例设计:

下面介绍一个实例,订单历史表。这个表有以下的查询场景。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,332评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,930评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,204评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,348评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,356评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,447评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,862评论 3 394
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,516评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,710评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,518评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,582评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,295评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,848评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,881评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,121评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,737评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,280评论 2 341

推荐阅读更多精彩内容

  • 上一篇:101-BigData-29Azkaban 一、HBaes介绍 1.1、HBase简介HBase是一个分布...
    AncientMing阅读 639评论 0 1
  • 一、HBase简介 1.1 HBase是什么 HBase是一个分布式的、面向列的开源数据库,Hadoop 数据库。...
    这一刻_776b阅读 902评论 0 0
  • 简介 HBase是高可靠性,高性能,面向列,可伸缩的分布式存储系统,利用HBase技术可在廉价PC Serve...
    九世的猫阅读 2,164评论 1 6
  • 1. hbase 的特点是什么? (1) Hbase一个分布式的基于列式存储的数据库,基于Hadoop的hdfs存...
    Tim在路上阅读 607评论 0 9
  • 01-Hbase的特点 以下五点需要准确说出的,如果可以还可以将一下Hbase的写入比读取快的原因(1) Hbas...
    李小李的路阅读 726评论 0 1